-- -- 用户操作锁 -- local skynet = require "skynet" local coroutine = coroutine local xpcall = xpcall local traceback = debug.traceback local table = table local queue = { queue = {} } function queue.critical_section(uid) local pq = queue.queue[uid] if pq == nil then pq = {ref = 0, thread_queue = {}} queue.queue[uid] = pq end local function xpcall_ret(ok, ...) pq.ref = pq.ref - 1 if pq.ref == 0 then pq.current_thread = table.remove(pq.thread_queue, 1) if pq.current_thread then skynet.wakeup(pq.current_thread) end end assert(ok, (...)) return ... end return function(f, ...) local thread = coroutine.running() if pq.current_thread and pq.current_thread ~= thread then table.insert(pq.thread_queue, thread) skynet.wait() assert(pq.ref == 0) -- current_thread == thread end pq.current_thread = thread pq.ref = pq.ref + 1 return xpcall_ret(xpcall(f, traceback, ...)) end end return queue