lua-users home
lua-l archive

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


On Fri, Jul 3, 2020 at 2:50 PM Stefan <ste@evelance.de> wrote:
>
> Hello,
>
> is it possible to yield and resume the main thread, even if the
> yielding function runs in another coroutine?

Although you maay be able to yield from the main thread I do not think
this is totally supported given:

"coroutine.isyieldable ()
Returns true when the running coroutine can yield.
A running coroutine is yieldable if ***it is not the main thread****
and it is not inside a non-yieldable C function. "

Probably "lua_isyieldable [-0, +0, –]
int lua_isyieldable (lua_State *L);
Returns 1 if the given coroutine can yield, and 0 otherwise. "

could help you assert this.

Anyway, you do not have to use the main coroutine to run your thread,
why don't you just use an alternate one and lua_yield on whatever
lua_state is passed into your C callback?

If I'm not too confused just try:

> int main()
> {
>     L = luaL_newstate();
>     luaL_openlibs(L);
>     lua_register(L, "cb", luacb);

MAINL = luaL_newstate(), openlibs and register in mainL, then do...

    L = lua_newthread(MAINL);

All the rest mainly unchanged.
>     const char script[] =
...
   }
> close_state:
>     lua_close(L);

And  change this to lua_close(MAINL) here.

i.e., the same thing you could do in pure lua. ( you create the
coroutine with the function you want to run and then resume it, you
cannot resume main thread or create the main thread with an arbitrary
function ). Bear in mind the C code in main is running in the main
thread, so it is resuming itself, and chaos ensues sooner or later.

I do a variation of this with some event handler code, for IVRs. When
I get a call I start a coroutine with the IVR from main and yield from
it when it needs to do blocking stuff. And for some administrative
tasks which I need to call and may need to do blocking things I create
a one-off coroutine to do the work which can yield if needed, although
it normally does not do it. Some registry storing with lightuserdata
to C events ( the blocking things are typically handled with a C
function which takes a pointer which it passes to a C callback when
done, which you normally use for some struct used on the callback. I
use this pointer as key to save the coroutine in the registry so the C
callbacks now which coroutine to resume ) and you can juggle a lot of
events seamlessly.

For some other stuff I've found easier to just handling all the
yielding and resuming in lua, the main coroutine just runs a
scheduler, an when it has no slave coroutine to run I just return
giving the C calling code an indication of what to do/queue.

I've been using coroutine packages since CP/M and MSDOS, even written
some for those, and I've normally found "do not run app code in the
main coroutine" to be the easier thing. In fact package I wrote having
the resume/yield style did not have a main coroutine.

Francisco Olarte.