Re: ffi: callback lifetime

  • From: Dimiter 'malkia' Stanev <malkia@xxxxxxxxx>
  • To: luajit@xxxxxxxxxxxxx
  • Date: Fri, 18 May 2012 09:15:17 -0700

On 5/18/2012 6:19 AM, Cosmin Apreutesei wrote:
Thanks, for the explanation.

I did read the docs, I guess the phrase "Callbacks due to implicit
conversions are permanent!" got me thinking what kind of callbacks
aren't permanent.

Now I picture them like file handles, in that there's a finite number
of them and I must free them manually, except file handlers also have
a __gc which is not very useful anyway with a non-deterministic
collector.

Hmm.. I guess that would be a good way for me to think about them! Thanks for it :)


On Fri, May 18, 2012 at 3:46 PM, Mike Pall<mike-1205@xxxxxxxxxx>  wrote:
Cosmin Apreutesei wrote:
AFAIU implicit callback objects created by assigning a Lua function to
a function pointer are internally anchored along with the Lua function
and there's no way to access them or free them (or the Lua function).
But callbacks created by ffi.cast() are not anchored and thus subject
to normal garbage collection rules, and thus no need to "unanchor"
them by cb:free(), is that right?
No, there's no difference between these. Callbacks are always
anchored independently and managed manually. That's why you need
to explicitly free them.

The only difference is that with implicit conversions, you can't
catch the callback function pointer in a variable, so you'll have
a hard time calling cb:free() on it. In other words: only the
explicit conversion with ffi.cast() allows you to free the
callback. Otherwise it'll never be freed (until the lua_close()).

So if I pass some_lua_function where a function pointer is expected,
the callback is permanent, but if I pass ffi.cast('WNDPROC',
some_lua_function) the callback is only guaranteed to last until the
function returns, and will be freed on the next gc cycle without me
having to cb:free() it, right? Or do I always have to manually
cb:free() it afterwards if I don't need it ? In other words, does a cb
object have a __gc that does self:free() ?
Nope. Callbacks are never subject to GC. That's because in general
the VM cannot tell how long the C side may hold onto the callback
address. But you can tell -- by reading the docs. :-)

An allocated callback keeps the callback slot alive (there's a
limited number of these) as well as the Lua closure. If you free
the callback, the slot is immediately available again and the Lua
closure is now subject to regular GC (depends on whether it's
anchored somewhere else, too).

--Mike



Other related posts: