we are developing game server using lua.
the server is single threaded, we'll call lua from c++.
every c++ service will create a lua thread from a global lua state which is shared by all service.
the lua script executed by lua thread will call a c api which will make a rpc call to remote server.
then the lua thread is suspened, because it's c function never return.
when the rpc response get back, we'll continue the c code ,which will return to the lua script.
so, we will have multiple lua thread execute parallel on a same global lua state, but they will never run concurrently. and the suspend is not caused but lua yield function, but from the c side.
is it safe to do something like this?
#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;
}