skynet skynet.wait()以及skynet.wakeup()分析

话不多说 先上测试代码

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流程
skynet skynet.wait()以及skynet.wakeup()分析_第1张图片如上图依次唤醒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分析,这里就不赘述了
skynet skynet.wait()以及skynet.wakeup()分析_第2张图片
那么就会执行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的逻辑

你可能感兴趣的:(skynet框架分析)