zoukankan      html  css  js  c++  java
  • skynet服务之协程的威力

        接上一篇分析skynet服务之launcher,本篇我们继续来分析一下lua中的协程如何与服务有机结合的,关于lua中协程的解释参见本文lua中协程的理解》;

    上一篇分析到,当一个lua服务收到消息后,在lua层,最终会执行到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)))
            elseif session ~= 0 then
                c.send(source, skynet.PTYPE_ERROR, session, "")
            else
                unknown_request(session, source, msg, sz, proto[prototype].name)
            end
        end
    end

    函数先通过f = p.dispatch取到特定服务的消息处理函数,然后调用co_create(f)创建一个协程,该函数实现如下:

    local coroutine_pool = setmetatable({}, { __mode = "kv" })

    local function co_create(f)
        local co = table.remove(coroutine_pool)
        if co == nil then
            co = coroutine.create(function(...)
                f(...)
                while true do
                    f = nil
                    coroutine_pool[#coroutine_pool+1] = co
                    f = coroutine_yield "EXIT"
                    f(coroutine_yield())
                end
            end)
        else
            coroutine_resume(co, f)
        end
        return co
    end

    以上代码的中使用了弱表来作为协程池,关于lua中的弱表请参考《lua中的弱表理解》;

    上述函数先通过table.remove(coroutine_pool)coroutine_pool表中pop最后一个元素,即一个协程,

    如果不存在协程,就会执行coroutine.create(function(...))来创建一个新的协程,协程执行函数接受可变参数,

    注意:此时并未执行协程函数;

    如果从协程库中取到了一个协程,直接调用了coroutine_resume(co, f),这个函数对应函数为:

    local coroutine_resume = profile.resume

    而profile.resume对应C库函数lresume(),该函数实现代码如下:

    static int
    lresume(lua_State *L) {
        lua_pushvalue(L,1);
        
        return timing_resume(L);
    }

    接着调用了timing_resume(L),函数实现代码如下

    static int
    timing_resume(lua_State *L) {
        lua_pushvalue(L, -1);
        lua_rawget(L, lua_upvalueindex(2));
        if (lua_isnil(L, -1)) {        // check total time
            lua_pop(L,2);    // pop from coroutine
        } else {
            lua_pop(L,1);
            double ti = get_time();
    #ifdef DEBUG_LOG
            fprintf(stderr, "PROFILE [%p] resume %lf ", lua_tothread(L, -1), ti);
    #endif
            lua_pushnumber(L, ti);
            lua_rawset(L, lua_upvalueindex(1));    // set start time
        }

        lua_CFunction co_resume = lua_tocfunction(L, lua_upvalueindex(3));

        return co_resume(L);
    }

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

  • 相关阅读:
    基数排序
    希尔排序
    归并排序
    选择排序
    冒泡排序
    堆排序
    快速排序
    Python selenium 4种常用定位 id,class_name,text,xpath
    python selenium 用索引值定位
    python pycharm 建立新项目时使用上个项目所下载的第三方库方法
  • 原文地址:https://www.cnblogs.com/skiing886/p/7761858.html
Copyright © 2011-2022 走看看