lua-users home
lua-l archive

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


In the C libraries I'm binding to, there is always some void* pointer
I can store stuff in when starting the call and it's given back to me
in the C callback.  I create a custom struct I store in there that
contains (among other things) the current lua_State* and an integer
ref using the global registry.  I store either my userdata or
callback, or anything else I don't want getting GCed while the request
is in flight.

Github is down for me atm, but https://github.com/creationix/luv is
lua bindings I wrote just the last couple days.  Look at luv_handle_t
and luv_req_t to see what kinds of structs I store in the void*
pointers.

For the handles which may have more than one concurrent request out
for them, I use a refcounting system.  I only luaL_ref when the count
going from zero to non-zero, and I free the ref when it goes back to
zero.  For requests which are basic one-shot callbacks, I always store
the callback in a ref and free it when I call the callback later.

On Wed, Oct 10, 2012 at 9:59 AM, Roberto Ierusalimschy
<roberto@inf.puc-rio.br> wrote:
>> If I anchor the Lua state/thread in my 'C' registration function will this
>> prevent my coroutine thread from being garbage collected until *after* I've
>> called into Lua and released the anchor?
>>
>> Lua state/thread lifetime seems a little vague in this context. I think the
>> difficulty lies in the fact that "L" combines them both and you can
>> separately reference them.
>
> You can think (as this is the actual implementation :) that each "L"
> represents a thread, and each thread points to its corresponding state.
> If a thread is collected, the structure that its L points to will be
> released, so the L becomes an invalid pointer and there is nothing you
> can do with it.
>
> If you anchor the thread into the state, it will not be collected. So,
> if you have an external pointer to it, the pointer will stay valid.
> So, in a first approximation, if you anchor the thread when the callback
> is registered and keeps a C pointer to it, you can use that C pointer
> to retrieve the callback and call the callback using that thread.
>
> However, there are other problems with this approach. The thread
> cannot be collected, but it can be in a state of error. If a coroutine
> ends with an error, the corresponding thread goes to an error state.
> You should not call a thread in that state. Also, the coroutine can
> be in a suspended state (that is, it yielded), and again you should
> not call it except to resume the yield.
>
> My suggestion is that you either use the main thread or that you create
> an exclusive thread to run your calllbacks. (If you call a thread with
> lua_pcall instead of lua_resume, it does not become dead after an
> error.)
>
> -- Roberto
>