[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: Lua State and callbacks from C
- From: Tim Caswell <tim@...>
- Date: Wed, 10 Oct 2012 12:56:54 -0500
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
>