Weak references and finalization

Tuesday, October 20, 2009
Although I don't yet have garbage collection implemented in Tart, I have some fairly well-formed ideas of how I plan to handle finalization: The base Object class has two methods, addFinalizer and removeFinalizer. The argument is a single function (which can be a closure or bound method) that accepts no arguments and returns no values.

Calling addFinalizer() registers the function with a global table of callbacks that are to be called *after* the object has been deleted. removeFinalizer() unregisters the function.

One important caveat is that the finalizer function is traced like any other object - which means that the finalizer function must not hold a reference to the object, otherwise the object will never be deleted. This avoids the problem of finalizers that make their objects live during finalization.

So how do you use it? A typical example is a file handle, which you want to auto-close when the object using the file is deleted. The way to do this is to create an outer object, which exposes the interface for working with the file handle, and a private, inner "resource" object that represents the file handle itself.

When the file is opened for the first time, you register a finalizer method for the outer object. This finalizer holds a reference to the inner object, but not the outer one. (In fact, the finalizer could be nothing more than the inner object's 'close' method as a bound method).

When the outer object is garbage collected, the finalizer will be called, which can then close the inner object. Since the finalizer is automatically de-registered after it is called, it is now garbage, as is the inner object it was referring to.

On the other hand, if you manually call 'close' on the outer object, you can remove the finalizer callback since you don't need it any more.

Something I just realized today is that implementing weak references on top of this system is fairly trivial: The weak reference is simply a small class which holds an Object value, and which registers a finalizer that the value to NULL. (There will need to be some way for the weak reference to tell the garbage collector not to trace its value, but that can just be a compile-time attribute.)

-- Talin


Post a Comment