首页 > 解决方案 > 让两个 lua 线程在同一个 lua 状态下并行运行而不并发执行是否安全?

问题描述

我们正在使用 lua 开发游戏服务器。

服务器是单线程的,我们将从 C++ 调用 lua。

每个 C++ 服务都会从全局 lua 状态创建一个 lua 线程,该状态由所有服务共享。

lua 线程执行的 lua 脚本将调用 ac api,后者将对远程服务器进行 rpc 调用。

然后lua线程被挂起,因为它的c函数永远不会返回。

当 rpc 响应返回时,我们将继续 c 代码,这将返回到 lua 脚本。

因此,我们将有多个 lua 线程在同一个全局 lua 状态上并行执行,但它们永远不会同时运行。而suspend不是引起的而是lua的yield函数,而是来自c端。

做这样的事情安全吗?

#include <stdio.h>
#include <stdlib.h>
#include <ucontext.h>
#include "lua/lua.hpp"

static ucontext_t uctx_main, uctx_func1, uctx_func2;

lua_State* gLvm;
int gCallCnt = 0;

static int proc(lua_State *L) {
    int iID = atoi(lua_tostring(L, -1));

    printf("begin proc, %s\n", lua_tostring(L, -1));
    if(iID == 1)
    {
        swapcontext(&uctx_func1, &uctx_main);
    }
    else
    {
        swapcontext(&uctx_func2, &uctx_main);
    }
    printf("end proc, %s\n", lua_tostring(L, -1));
    return 0;  
}

static void func1(void)
{
    gCallCnt++;
    printf("hello, func1\n");

    lua_State*thread = lua_newthread (gLvm);

    lua_getglobal(thread, "proc");
    char szTmp[20];
    sprintf(szTmp, "%d", gCallCnt);
    lua_pushstring(thread, szTmp);
    int iRet = lua_resume(thread, gLvm, 1);
    printf("lua_resume return:%d\n", iRet);
}

static void func2(void)
{
    gCallCnt++;
    printf("hello, func2\n");

    lua_State*thread = lua_newthread (gLvm);

    lua_getglobal(thread, "proc");
    char szTmp[20];
    sprintf(szTmp, "%d", gCallCnt);
    lua_pushstring(thread, szTmp);
    int iRet = lua_resume(thread, gLvm, 1);
    printf("lua_resume return:%d\n", iRet);
}



int main(int argc, char *argv[]){
    int iRet = 0;

    gLvm = luaL_newstate();
    luaL_openlibs(gLvm);

    lua_pushcfunction(gLvm, proc);
    lua_setglobal(gLvm, "proc");

    char func1_stack[16384];
    char func2_stack[16384];
    getcontext(&uctx_func1);
    uctx_func1.uc_stack.ss_sp = func1_stack;
    uctx_func1.uc_stack.ss_size = sizeof(func1_stack);
    uctx_func1.uc_link = &uctx_main;
    makecontext(&uctx_func1, func1, 0);

    getcontext(&uctx_func2);
    uctx_func2.uc_stack.ss_sp = func2_stack;
    uctx_func2.uc_stack.ss_size = sizeof(func2_stack);
    uctx_func2.uc_link = &uctx_main;
    makecontext(&uctx_func2, func2, 0);

    swapcontext(&uctx_main, &uctx_func1);

    swapcontext(&uctx_main, &uctx_func2);

    swapcontext(&uctx_main, &uctx_func1);

    swapcontext(&uctx_main, &uctx_func2);

    printf("hello, main\n");

    return 0;
}

标签: luacoroutineucontext

解决方案


推荐阅读