lua-users home
lua-l archive

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


On Mon, Jul 14, 2014 at 07:59:53PM +0000, Thijs Schreijer wrote:
> 
> 
> > -----Original Message-----
> > From: lua-l-bounces@lists.lua.org [mailto:lua-l-bounces@lists.lua.org] On
> > Behalf Of Steven Degutis
> > Sent: maandag 14 juli 2014 17:52
> > To: Lua mailing list
> > Subject: How do you usually mix Lua and C callbacks?
> > 
> > I've got some C functions that take callback which has a void* pointer
> > for programmer-use. The technique I've been using is making a little
> > struct that holds the lua_State* and an int, which I store the return
> > value of luaL_ref'ing the given function. Then inside the C callback,
> > I take the Lua state and lua_rawgeti the function out of
> > LUA_REGISTRYINDEX, and call it.
> > 
> > But this seems very cumbersome and awkward. (Plus it means my function
> > won't be garbage-collected until I luaL_unref it out of there, but I'm
> > not sure that can be solved without making use of an explicit
> > "unregister" method for this C callback). Is there a better way to do
> > this that is less cumbersome and awkward? Thanks.
> > 
> > -Steven
> 
> If your application is not multithreaded, the reference can be stored in a
> global variable, and the lua pieces can remain on the stack.
> 
> If you do have a multithreaded environment, then I don't know simpler
> solutions
> 

That won't work for system-level multithreading, _nor_ for coroutine based
multithreading where multiple callbacks could be outstanding (e.g. with an
event loop). The latter is far more common and if the callback is triggered
from a reuseable module should probably be taken into account (either
support it or throw an error on concurrent requests) lest somebody get
burned.

As long as a callback is outstanding one would want the reference to be
pinned in memory anyhow, regardless of what's happening in Lua-space.
There's nothing awkward about this.

But if the callback is cancelable and one wanted to integrate this into the
GC to detect when a callback will go unused--the coroutine or object is
garbage collected before the callback completes--they could use the specific
coroutine in, or object on which the method was called as a key in a weak
table** in the registry. Then from some __gc handler (which handler depends
on how you anchor it in the weak table) one could cancel the request so a
callback doesn't try to re-enter Lua using an invalid state context.

** Preferably a Lua 5.2+ ephemeron table in case the coroutine or userdata's
uservalue has a problematic reference cycle.