I don't think that anyone has mentioned this yet, but I guess you mean something like this: * put B in A's uservalue table to keep it alive as long as A is alive * put a weak back reference to A in B's uservalue table * in A's finalizer free A if it hasn't been freed before by someone else * in B's finalizer first free A if the weak back reference still exists and A hasn't been freed before, and then free B itself if it hasn't been freed before
But this (if it actually works) relies on undocumented order of clearing objects from weak tables in relation to calling finalizers of other objects in the same gc cycle. (In Lua 5.2 you can use weak values which have the necessary guarantees, and in Lua 5.1 you can probably use strong back references with some degradation of lifetime granularity.) And of course my `SDL_Quit` finalizer would store references to all SDL objects ever created, but this approach could still be an option for the OP ...
Note quite. You can have STRONG references from A to B and B to A. This won’t stop the GC doing it’s job since as soon as both A and B are unreachable they will be collected (the circular references don’t impact the ability of the GC to identify A and B as garbage). It’s then a simple matter to have A call B’s finalizer before it does its own finalization, ensuring B is always done first, assuming of course that’s B’s finalizer is idempotent. This pattern will always work regardless of the behavior of the GC. This can even be generalized by having A maintain a table of references to many B’s.
—Tim
|