123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132 |
- -- You should use this module (skynet.coroutine) instead of origin lua coroutine in skynet framework
- local coroutine = coroutine
- -- origin lua coroutine module
- local coroutine_resume = coroutine.resume
- local coroutine_yield = coroutine.yield
- local coroutine_status = coroutine.status
- local coroutine_running = coroutine.running
- local select = select
- local skynetco = {}
- skynetco.isyieldable = coroutine.isyieldable
- skynetco.running = coroutine.running
- skynetco.status = coroutine.status
- local skynet_coroutines = setmetatable({}, { __mode = "kv" })
- function skynetco.create(f)
- local co = coroutine.create(f)
- -- mark co as a skynet coroutine
- skynet_coroutines[co] = true
- return co
- end
- do -- begin skynetco.resume
- local profile = require "skynet.profile"
- -- skynet use profile.resume_co/yield_co instead of coroutine.resume/yield
- local skynet_resume = profile.resume_co
- local skynet_yield = profile.yield_co
- local function unlock(co, ...)
- skynet_coroutines[co] = true
- return ...
- end
- local function skynet_yielding(co, from, ...)
- skynet_coroutines[co] = false
- return unlock(co, skynet_resume(co, from, skynet_yield(from, ...)))
- end
- local function resume(co, from, ok, ...)
- if not ok then
- return ok, ...
- elseif coroutine_status(co) == "dead" then
- -- the main function exit
- skynet_coroutines[co] = nil
- return true, ...
- elseif (...) == "USER" then
- return true, select(2, ...)
- else
- -- blocked in skynet framework, so raise the yielding message
- return resume(co, from, skynet_yielding(co, from, ...))
- end
- end
- -- record the root of coroutine caller (It should be a skynet thread)
- local coroutine_caller = setmetatable({} , { __mode = "kv" })
- function skynetco.resume(co, ...)
- local co_status = skynet_coroutines[co]
- if not co_status then
- if co_status == false then
- -- is running
- return false, "cannot resume a skynet coroutine suspend by skynet framework"
- end
- if coroutine_status(co) == "dead" then
- -- always return false, "cannot resume dead coroutine"
- return coroutine_resume(co, ...)
- else
- return false, "cannot resume none skynet coroutine"
- end
- end
- local from = coroutine_running()
- local caller = coroutine_caller[from] or from
- coroutine_caller[co] = caller
- return resume(co, caller, coroutine_resume(co, ...))
- end
- function skynetco.thread(co)
- co = co or coroutine_running()
- if skynet_coroutines[co] ~= nil then
- return coroutine_caller[co] , false
- else
- return co, true
- end
- end
- end -- end of skynetco.resume
- function skynetco.status(co)
- local status = coroutine.status(co)
- if status == "suspended" then
- if skynet_coroutines[co] == false then
- return "blocked"
- else
- return "suspended"
- end
- else
- return status
- end
- end
- function skynetco.yield(...)
- return coroutine_yield("USER", ...)
- end
- do -- begin skynetco.wrap
- local function wrap_co(ok, ...)
- if ok then
- return ...
- else
- error(...)
- end
- end
- function skynetco.wrap(f)
- local co = skynetco.create(function(...)
- return f(...)
- end)
- return function(...)
- return wrap_co(skynetco.resume(co, ...))
- end
- end
- end -- end of skynetco.wrap
- return skynetco
|