Wednesday, July 2, 2008

Destructors and Finalizers

As Hans Boehm argues in a recent paper, finalizers should run asynchronously to the client code. I will support this in my memory manager by queuing up finalization-ready objects and leave it to the client to actually run the finalizers through the API mm_run_pending_finalizer.

Lush "OO objects" may have a destructor method. For stack-allocated objects, the destructor method should be invoked when the object goes out of scope. For heap-allocated objects, the destructor method should invoked after the object becomes unreachable. In other words, "OO objects" need a finalizer, and one of its jobs is to call the object's destructor method. This makes clear that, when there are several finalization-ready objects, the order of finalizer invocation is important.

Current Lush has a facility for registering "finalizers" with individual objects. These are used to notify other objects that hold a weak reference to an object. For instance, a hash table may hold weak references to key objects, and events in the event queue hold a weak reference to an event handler object. The "finalizers" registered by the hash table and by the event queue do not look at the object, but only need to know an object's identity to update the hash table, or event queue, respectively. I would call them "notifiers" rather than "finalizers".

To support this mechanism for maintaining weak references I am extending the memory manager API by a new function mm_notify. This function will just mark a managed object. When the object has become unreachable and when it is about to be reclaimed by the memory manager, a notification function is called with the object's address as argument. The notification function is not specific to an individual object or an object's type and it needs to be given to mm_init when the system is initialized.

No comments: