lua-users home
lua-l archive

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


Another way: I think, though I could easily be wrong, that the memory created by lua_newuserdata() is never memmoved by Lua.  At least that used to be the case a long time ago.  If it's still the case, you can store the pointer address returned by lua_newuserdata in the C++ object, and have it's destructor go clear the pointer to itself in that userdata; and vice-versa in the Lua __gc metamethod for that userdata, go clear the C++ object's member of the userdata's location address.

Of course you'd have to make sure pushing the same object multiple times into Lua only creates one userdata, and the solution to that might yield a solution to the first problem.  For example, if you use luaL_ref() with the Registry to provide a unique reference to a created userdata to avoid creating multiples, by storing that reference integer in the C++ object, then you can use that instead of the raw userdata address to find it again from the Registry.  The C++ object's destructor would use it to find the userdata from the Registry, clear its own pointer from within the userdata, and remove the reference from the Registry (luaL_unref).  It sounds like that might work(?)

-hadriel


On Jan 14, 2013, at 10:49 PM, Ross Bencina <rossb-lists@audiomulch.com>
 wrote:

> On 15/01/2013 11:33 AM, Jay Carlson wrote:
>> The fix for this would involve C-side deallocation turning Lua-side
>> references into tombstones, and I don't see an obvious way to
>> implement tombstones other than something that works out to be Tim's
>> serial numbers.
> 
> How about this for an eager alternative to the counting thing. I haven't tried this. I don't think it's better (aside from avoiding the page fault issue). I'm mentioning it as a model to think about options:
> 
> Any pointer to a C object in Lua could be represented by a struct:
> 
> struct TrackedLuaCPointerNode{
> 	TrackedLuaCPointer *next;
> 	void *cobject; // pointer to c object
> }
> 
> In C/C++ wrap/intercept the allocator so that there is a TrackedLuaCPointerNode* stored just before the allocated C/C++ memory region. This pointer is used as the head of a linked list of TrackedLuaCPointerNodes that point to the region.
> 
> Use TrackedLuaCPointerNode to represent C/C++ pointers in Lua. Whenever you want to create a new Lua pointer, the object pointer goes in p.cobject and the TrackedLuaCPointerNode gets linked into the linked list.
> 
> When the C/C++ object memory region is beeing released, walk the linked list:
> - TrackedLuaCPointerNodes with non-NULL cobject fields are still referenced in Lua. set cobject to NULL.
> - TrackedLuaCPointerNodes with NULL cobject fields have already been finalised in Lua. In this case free the TrackedLuaCPointerNode.
> 
> When Lua finalises a TrackedLuaCPointerNode:
> - TrackedLuaCPointerNodes with non-NULL cobject fields are still allocated in C, set cobject field to NULL.
> - If cobject is NULL, free TrackedLuaCPointerNode.
> 
> 
> This scheme will work whenever you can intercept the memory allocator used for C/C++ objects (eg. overload operator new/delete). It assumes C/C++ pointers are to the start of the allocation region: objectPointer - sizeof(TrackedLuaCPointer*) will give a pointer to the linked list head -- that's good because it means you can cheaply make a TrackedLuaCPointerNode out of any pointer.
> 
> A similar scheme could be used intrusively with C++ objects or some kind of smart pointer thing.
> 
> It could also be made to work with embedded subobjects (since deleting the outer object deletes all fields, they could share a single linked list) but you'd need a way to get the list head when making a new TrackedLuaCPointerNode.
> 
> I've described it so that creating a pointer and finalising a pointer are constant time operations at the cost of keeping the nodes around until the C++ region is freed (and then an O(n) operation to free the nodes). I can think of a way to make the release O(1) too using a trampoline and an incremental reclamation list, but its more complicated.
> 
> Ross.
>