[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: Best way to manage refs in C + Garbage collection in a single collectgarbage() call.
- From: Mark Hamburg <mark@...>
- Date: Thu, 24 Jul 2008 09:46:40 -0700
If it is fine to have the only long term references to these objects
be from Lua (and from your description it sounds like it is), then you
don't actually need to use lua_refs. Rather you need a way to have the
container point to the widget. The way to do this is via the
environment table on the container. You'll need to generate a new
environment table when you create a container, but after that you can
use it just like any other Lua table to store links to other objects.
Roughly...
int WidgetContainer_AddWidget( lua_State* L ) {
lua_settop( L, 2 ); /* Fix the stack height. */
lua_getfenv( L, 1 ); /* Get the environment for the user data at
index 3. */
lua_pushvalue( L, 2 ); /* Get the widget onto the top of the stack. */
lua_rawseti( L, 3, lua_objlen( L, 3 ) + 1 ); /* env[ #env + 1 ] =
widget */
return 0;
}
The benefit of this approach is that it saves you from the risk of
creating uncollectable data via the lua_ref mechanism. You have to
explicitly dispose of lua_refs for them to go away. If you get a cycle
of links between objects that includes a lua_ref, then that cycle is
uncollectable because the existence of the cycle will make the lua_ref
appear to be in use which will in turn keep the cycle alive. By
instead using straight Lua tables to store the object graph, you allow
the GC to do its work without being tricked by a false root.
If you are storing pointers into data structures beyond the bounds of
Lua -- e.g., a view hierarchy in some native code system -- then you
probably need the native objects to be reference counted and the Lua
side just adds and removes references. If equality isn't a matter and
reference to other Lua data doesn't matter, then every time you need
to expose one of these native objects to Lua, you can just generate a
new userdata proxy. If equality does matter but you still don't need
to attach Lua data, then you can use a weak table mapping light
userdata (the native address) to full userdata (the proxy).
If you do need to attach Lua data, then you are back to needing to use
the userdata environment tables and you need to keep the userdata
alive as long as the native object stays alive without creating an
uncollectable cycle between the Lua-side data and the native-side
data. Basically, what you need to do is arrange for the Lua proxies to
stay alive as long as the native side has a reference count of 2 or
more -- i.e., there's a native reference in addition to the reference
from the proxy -- but become eligible for collection if the reference
count drops to 1. And then you probably need to be careful to use Lua-
based links rather than native links or you need to at least think
about potential cycles. This gets complicated and can take a while to
get right. If you can fit your work into the first case described in
this message, I would recommend doing so.
Mark