lua-users home
lua-l archive

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


Hello,

is it possible to yield and resume the main thread, even if the
yielding function runs in another coroutine?

(related: http://lua-users.org/lists/lua-l/2019-05/msg00081.html )

My Lua script runs in an event-driven environment and I need to
halt it to until an external resource is ready. This works really
nice as long as the state is started with lua_resume and the
C callbacks yield back to the "ground" layer of C.

But when the script calls these functions in a coroutine, they just
yield the script's coroutine and don't stop the execution of Lua.

I tried to yield the main thread directly, but resuming it continues
execution at the wrong point:

print 'A'
cb() --> lua_yield(main thread) / Should pause the script
print 'B'
coroutine.resume(coroutine.create(function()
   print '   X'
   cb() --> lua_yield(main thread) / Should pause the script
   print '   Y'
end))
print 'C'

Prints (Y is missing):

[Resume state]
A
[Yielded]
[Resume state]
B
   X
[Yielded]
[Resume state]
C
[Finished]

Now my questions are:
A) Can a CFunction call lua_yield with anything other than the
   lua_State passed as argument?
B) If not, can the entire script be yielded/resumed directly in
   standard Lua?

I'm sorry for the naive questions, but I couldn't find a direct
statement in the manual.

Here is the C test program:

// gcc -Wall -Ilua-5.4.0/src main.c lua-5.4.0/src/liblua.a -ldl -lm
#include <stdio.h>
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>

lua_State* L;

int luacb(lua_State* T)
{
    return lua_yield(L, 0);
}

int main()
{
    L = luaL_newstate();
    luaL_openlibs(L);
    lua_register(L, "cb", luacb);
    const char script[] =
        "print 'A'\n"
        "cb()\n"
        "print 'B'\n"
        "coroutine.resume(coroutine.create(function()\n"
        "   print '   X'\n"
        "   cb()\n"
        "   print '   Y'\n"
        "end))\n"
        "print 'C'\n";
    if (luaL_loadbufferx (L, script, sizeof script - 1, "script", "t")
!= LUA_OK) {
        printf("[Error] %s\n", lua_tostring(L, -1));
        goto close_state;
    }
    for (;;) {
        printf("[Resume state]\n");
        int nresults = 0;
        int lr = lua_resume(L, NULL, 0, &nresults);
        switch (lr) {
            case LUA_OK:
                lua_pop(L, nresults);
                printf("[Finished]\n");
                goto close_state;
            case LUA_YIELD:
                lua_pop(L, nresults);
                printf("[Yielded]\n");
                continue;
            default: {
                printf("[Error] %s\n", lua_tostring(L, -1));
                goto close_state;
            }
        }
    }
close_state:
    lua_close(L);
}