lua-users home
lua-l archive

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

Am 03.07.2020 um 18:49 schrieb Francisco Olarte:
> 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 tried this approach as well and it gives the same result - it
skips the 'Y'.

The 5.1 manual is more direct about what yield does:
"When a C function calls lua_yield in that way, the running coroutine
suspends its execution, and the call to lua_resume that started this
coroutine returns."

But is this still true? Or can the CFunction yield a different thread
as well?

After yielding the 3 different threads in the callback (the one passed
as parameter, the main thread, the extra thread created as you
suggested) on 5.1.5, 5.3.5, 5.4.0 and LuaJIT2.1 it looks like they
all do different things, including crashing, printing a random double,
or ignoring the second yield.

To me it seems that it is not safe to yield directly into the
"ground layer" C.

> 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.

Thanks for the interesting story! Are there multiple threads or
processors involved or is it fully cooperative?