当前位置: 首页>后端>正文

skynet.send skynet.call流程

skynet.send


function skynet.send(addr, typename, ...)
    local p = proto[typename]
    return c.send(addr, p.id, 0 , p.pack(...))
end

skynet.call


function skynet.call(addr, typename, ...)
    local p = proto[typename]
    local session = c.send(addr, p.id , nil , p.pack(...)) -- 这里的第三个参数如果是nil就会ALLOCSESSION
    if session == nil then
        error("call to invalid address " .. skynet.address(addr))
    end
    return p.unpack(yield_call(addr, session))
end

lualib-src/lua-skynet.c


    int type = luaL_checkinteger(L, idx_type+0); // idx_type =2
    int session = 0;
    if (lua_isnil(L,idx_type+1)) {
        type |= PTYPE_TAG_ALLOCSESSION;
    } else {
        session = luaL_checkinteger(L,idx_type+1);
    }

下面是yield_call,他在watching_session里面加了一个映射


local function yield_call(service, session)
    watching_session[session] = service
    session_id_coroutine[session] = running_thread
    local succ, msg, sz = coroutine_yield "SUSPEND" --挂起在这里
    watching_session[session] = nil
    if not succ then
        error "call failed"
    end
    return msg,sz
end

下面看下怎么把如上的挂起给唤醒,以使skynet.call流程继续


function skynet.ret(msg, sz)
    msg = msg or ""
    local co_session = session_coroutine_id[running_thread]
    if co_session == nil then
        error "No session"
    end
    session_coroutine_id[running_thread] = nil
    if co_session == 0 then
        if sz ~= nil then
            c.trash(msg, sz)
        end
        return false    
        -- send dont need ret
    end
    local co_address = session_coroutine_address[running_thread]
    local ret = c.send(co_address, skynet.PTYPE_RESPONSE, co_session, msg, sz)
    if ret then
        return true
    elseif ret == false then
        -- If the package is too large, returns false. so we should report error back
        c.send(co_address, skynet.PTYPE_ERROR, co_session, "")
    end
    return false
end

可以看到最后是在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
            local tag = session_coroutine_tracetag[co]
            if tag then c.trace(tag, "resume") end
            session_id_coroutine[session] = nil
            suspend(co, coroutine_resume(co, true, msg, sz, session))
        end
    else
...

https://www.xamrdz.com/backend/33p1931643.html

相关文章: