skynet lua业务逻辑的启动--skynet.start()

上两篇skynet主体流程, skynet怎么启动lua文件介绍了skynet代码的主体流程,还有怎么启动lua逻辑.

我们知道skynet业务逻辑都是在lua里写的,这样大大提高了开发效率,而且使热更新成为可能,究竟lua层是怎么保证逻辑正常运行,一个服务在lua层的表现形式又是怎么样的呢?这篇将为您讲解.

一个服务在lua层的入口是skynet.start(),他的实现为:

function skynet.start(start_func)
    c.callback(skynet.dispatch_message)    --①
    skynet.timeout(0, function()           --②
        skynet.init_service(start_func)
    end)
end

①这里是在c接口里指定服务的lua层回调函数dispatch_message,上篇我们有讲到过.

②是通过timeout接口来间接执行服务的入口函数

timeout的实现:

function skynet.timeout(ti, func)
    local session = c.intcommand("TIMEOUT",ti)    -- ①
    assert(session)
    local co = co_create(func)                    -- ②
    assert(session_id_coroutine[session] == nil)
    session_id_coroutine[session] = co
end

① 调用c的timeout接口,他会产生一个session id

② 启动协程池,关联func,session Id

c接口的timeout的实现:

1 根据context产生一个该context递增的session id

2 如果参数time==0,产生一条PTYPE_RESPONSE类型的消息压入队列;如果不为0,则增加时间节点

由于上面的参数是0,则产生一条PTYPE_RESPONSE类型的消息,包含了session id

当消息队列捕获并执行该消息的时候,就会调用lua层的回调函数skynet.dispatch_message了,最终调用raw_dispatch_message.它的实现:

local function raw_dispatch_message(prototype, msg, sz, session, source, ...)
    -- skynet.PTYPE_RESPONSE = 1, read skynet.h
    if prototype == 1 then
        local co = session_id_coroutine[session]      ①
        if co == "BREAK" then
            session_id_coroutine[session] = nil
        elseif co == nil then
            unknown_response(session, source, msg, sz)
        else
            session_id_coroutine[session] = nil
            suspend(co, coroutine.resume(co, true, msg, sz))    --②
        end
    else
        local p = proto[prototype]
        if p == nil then
            if session ~= 0 then
                c.send(source, skynet.PTYPE_ERROR, session, "")
            else
                unknown_request(session, source, msg, sz, prototype)
            end
            return
        end
        local f = p.dispatch
        if f then
            local ref = watching_service[source]
            if ref then
                watching_service[source] = ref + 1
            else
                watching_service[source] = 1
            end
            local co = co_create(f)
            session_coroutine_id[co] = session
            session_coroutine_address[co] = source
            suspend(co, coroutine.resume(co, session,source, p.unpack(msg,sz, ...)))
        else
            unknown_request(session, source, msg, sz, proto[prototype].name)
        end
    end
end

timeout产生的消息执行时会走分支①,他的session关联了一个协程,他是在timeout中调用co_create()产生的. co_create()是为了复用协程而产生的,具体请参考这篇:lua协程池

找到session关联的协程后,②开始执行suspend(co, corutine.resume(co,...)),实际上是先执行了corutine.resume(co),启动协程,执行了协程里的函数,即timeout传入的函数.suspend函数用来对协程的调度和调配,为了突出主干,下篇再讲suspend函数.至此一个服务的入口函数就通skynet.start()调用起来了

你可能感兴趣的:(skynet lua业务逻辑的启动--skynet.start())