lua-users home
lua-l archive

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

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.