[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: Inverted _gc
- From: RLake@...
- Date: Thu, 10 Jul 2003 17:40:27 -0500
> Suppose I have an object that is allocated (created) in Delphi (or C++
ro whatever). I don't (can't) want to give Lua full control on the
object's life, I just want to give access to its properties via properly
set callback functions in metatable of a heavy user data, that I wrap this
object into for Lua.
> Now the object gets destroyed (in Delphi), that brings the possibility
of calling property access function with a pointer to already freed
object if I have some heavydata references to this object left in Lua.
> Any ideas if I can somehow avoid this? Ideally would be me being able
to track down all userdata that points to this object and nil them out in
Lua, but I can't think of the way how to make it automatically, without
thorough keeping track of references by hand. Or maybe I can do it some
other way around?
If I'm not mistaken, there has been quite a lot of discussion of this
issue lately.
My favorite solution: Keep a table in the registry keyed by the address of
the Delphi object, whose values are the heavy-user data. You can use this
table to ensure that there is only a single Lua reference to each Delphi
object. When you delete the object in Delphi, set a flag in the relevant
userdata, using the address of the Delphi object to lookup the Lua object
in the registry table [1] or alternatively, set the userdata's contents to
NULL. This does not cause the Lua object to become nil, but it makes it
possible for Lua to check the object for validity. Once you have flagged
the userdata, *remove the key from the registry table*. (This is
important, both to allow the Lua userdata to be garbage collected, and
because the object's address may be assigned to a new object.)
The userdata will have a metatable; you can use this to identify the
object's class. This is handy because it allows you to check the class of
an object from C as well, simply by looking the address of the object up
in the registry table and then getting the metatable out of the resulting
userdata. So you get a form of run-time inspection without having to
modify the C definition of the object.
You still have a problem if there is some mechanism by which objects can
be deleted from the Delphi environment without you being informed of that;
this might be the issue for an object which has a non-Lua garbage
collection method, such as reference counting. That is more difficult to
solve; garbage collection methodologies don't easily co-operate with each
other. Hopefully if this is the case, the C-side memory management system
will also provide you with a finalisation method.
[1] Use lightuserdata for the keys; a lightuserdata is guaranteed to be
big enough for a pointer. Also, you do not technically need a separate
table; you can simply use the registry as long as you follow the
convention (followed by the Lua libraries) that a lightuserdata used as a
key in the registry is always the address of allocated storage.