话不多说 先上测试代码
local skynet = require("skynet")
function task1( )
skynet.error("start wait") --1 因为1先fork
skynet.wait() --挂起
skynet.error("end wait") --4
end
function task2( co )
skynet.error("start wakeup:",co) --2 然后是fork 2
skynet.wakeup(co)
skynet.error("end wakeup") --3 执行完毕
end
skynet.start(function ( ... )
local co = skynet.fork(task1)
skynet.fork(task2,co)
end)
function skynet.fork(func,...)
local args = table.pack(...)
local co = co_create(function()
func(table.unpack(args,1,args.n))
end)
table.insert(fork_queue, co)
return co
end
由start函数可知,fork_queue队列中已经有两个co
那么什么时候处理fork_queue中的co呢,当然是有消息来的时候,而且在这里这个消息时Timer线程发过来的超时消息,具体细节见博客 skynet.start流程
如上图依次唤醒fork_queue队列中的co,而执行task1时,又去skynet.wait() ,那么此时挂起让出执行权,等待被唤醒.
当唤醒task2时,调用 skynet.wakeup(co) 来看看实现
function skynet.wakeup(token)
if sleep_session[token] then
table.insert(wakeup_queue, token)
return true
end
end
其实就是往wakeup_queue中添加要唤醒的co,添加完成继续往下执行,此时返回到635行 执行suspend
参数是 co,true,SUSPEND,如不清楚,见博客skynet.fork分析,这里就不赘述了
那么就会执行dispatch_wakeup()函数,看看实现
local function dispatch_wakeup()
local token = table.remove(wakeup_queue,1)
if token then
local session = sleep_session[token]
if session then
local co = session_id_coroutine[session]
local tag = session_coroutine_tracetag[co]
if tag then c.trace(tag, "resume") end
session_id_coroutine[session] = "BREAK"
return suspend(co, coroutine_resume(co, false, "BREAK"))
end
end
end
coroutine_resume(co, false, “BREAK”)唤醒协程,传入参数false,BREAK
那么就来到
function skynet.wait(token)
local session = c.genid()
token = token or coroutine.running()
local ret, msg = suspend_sleep(session, token) //ret = false,msg = BREAK
sleep_session[token] = nil
session_id_coroutine[session] = nil
end
然后继续跑完task1的逻辑