12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849 |
- --
- -- 用户操作锁
- --
- 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
|