lua-users home
lua-l archive

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


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.