lua-users home
lua-l archive

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


R. Lake wrote,

> I am curious as to whether anyone is seriously contemplating using
yielding
> hook functions (and if so, for what) because I have some (fairly
technical)
> ideas about how to implement these features in an alternative manner which
> might be slightly more general. It seems to me that the main reason for
> yielding count/line hooks is to try to implement non-cooperative
> concurrency.

That's indeed what I used it for. It allows multiple concurrent Lua
scripts to run inside a single thread:

void opcodecounthook(lua_State *L, lua_Debug *ar) {
    /* We can't yield across a metamethod/C-call boundary. */
   if (L->nCcalls > 0) return;
   /* Yield without args */
   lua_yield(L, 0);
   /* never reached */
}

Yielding from the line count hook should be useful for stepping through
a Lua program with a synchronous update of some source code display
on the C side.

An interesting implication of being able to yield from a C function (not
a hook) is that it can enable callbacks to any language (let's call it
"A" for the sake of argument) that can call C yet cannot handle C-like
callbacks. The way this can be made to work is to register a C function
that is an intermediary between Lua and "A":

/*
* This function is registered with a special funcnumber upvalue for
* each "A" function. It passes the funcnumber via a backlink to
* the my_user_state structure and yields with its args.
*/
int Lua_to_A(lua_State *L) {
   /* Pass the function number via the user state backlink */
   (*(struct my_user_state **)(((LUA_USERSTATE *)L)-1))->funcnumber
                                     = (int32)lua_tonumber(L,
lua_upvalueindex(1));
   /* Yield with the args on the stack so as to pass them out to "A" */
   return lua_yield(L, lua_gettop(L));
}

On a yield, the C code can return to the "A" side, passing along
the funcnumber and script state. The "A" code can then use the Lua
API (called via C) to pull arguments, execute the required functionality
implemented in "A", and push return values (again using the Lua API).
Next, "A" can call back into C where something akin to auxresume is
used to resume the Lua script while passing along the return values of
the "A"-side function.

Unfortunately, such "A"-side functions cannot be called from a coroutine
nor protected using pcall.