lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]

在 2018/7/25 10:03, 小爬虫 写道:
> I've worked on a C coroutine framework implemented with ucontext.
> For each client request, the framework will alloc a C coroutine to process the request.
> I wanna add lua to this system. However, I met some problems.
> It's hard to change C coroutine to lua coroutine, since it's a big codebase. Use lua as  glue to aggregate all the C api seems a reasonable way.
> So lua will not use coroutine, leave the coroutine to C.
> However, the C stack changes when switch C coroutines. It's possible to use multiple  lua virtual machine, one for each C coroutine. But it is not efficient. Each creation of C Coroutine will need create a new virtual machine and load all the scripts.
> If I use only one Lua virtual machine,and create thread for each coroutine, it's much more light-weighted and scripts can be shared among different lua_thread. However, the switch execution of  C coroutine  requires  lua_thread to be suspended and resumed. Since lua only allow one running lua_thread.
> Are these any solutions for this problem? Thanks in advance.

I don't know much about ucontext, but if you are stuck with your current C coroutine system,
I don't think there is a better solution in plain Lua, other than one Lua VM for each C coroutine.

actually this might not be as bad as you would think. you should always measure.

if you are not restricted to your own C coroutine system, and you are OK with a patched Lua VM,
there is[1] a patch from LuaJIT 1.x branch called coco, which essentially rebuilt Lua's
coroutine on top of a custom C coroutine system, implemented using platform specific tricks.

it is very cool, and actually compatible with plain Lua (not ABI compatible for C modules of course).

although the patch is for Lua 5.1, it should not be very hard to adapt it to current version,
once you understands the implementation mechanism.

basically, lua_newthread(), will allocate a new C stack (with a stub context pointing to
a thunk of code) and associate the stack with the lua_State. lua_resume() switches to the new stack
and then jump into the context. lua_yield() saves current context then jump out to previous context.

so instead of integrate Lua's coroutine with your C coroutine system, you can implement your coroutine
system on top of Lua/coco's coroutine.

for example, coroutine_create() can be implemented as lua_newthread() followed by lua_pushcfunction()
coroutine_resume() is just lua_resume(), and coroutine_suspend() is just lua_yield().
you can directly use L as your coroutine handle.

you may need to differentiate Lua yields and C library yields in your scheduler/IO-multiplexer though,
but that should be straightforward.


the nerdy Peng / 书呆彭 /