Pattern: Finalization


Context

Smalltalk is a garbage collected system, and Smalltalk objects do are not normally notified before they are destroyed. In general such messages are not required, because the memory occuppied by garbage collected objects is recursively recovered. On occasion, however, there is a need to perform additional clean-up operations when an object is no longer needed, particularly if the object owns some external resource. Explicitly performing such clean-up operations may be very tricky to time correctly, because the lifetime of the objects is not always predictable.

Solution

Mark specific object instances as requiring finalization. Such objects receive a death-bed notification from the memory manager, and can perform whatever tidying is necessary.

  1. Mark an object as requiring finalization by sending it the #beFinalizable message at an appropriate point. This is either done in the instance #initialize method, or preferably after the object has acquired its external resource(s) (see example).
  2. Implement a #finalize method to perform the required finalization. There is no need to remove the finalization mark as the VM will already have done so.
  3. If the object has a method for explicitly freeing its external resource(s) programmatically (which will be the case if you've followed the Object Liberation Strategy), then remove the finalization mark immediately after freeing the resource, by sending the #beUnfinalizable message. This reduces finalization overhead and allows objects to die sooner.
  4. You can remove an object's finalization mark at any other time that you wish, and that object will not then receive a #finalize message.

Example

GraphicsTool is the superclass of most of the classes in Dolphin which encapsulate Windows™ drawing objects.

GraphicsTool adds the finalize mark after creating an owned external resource:

realize
	"Realize (create) the external resource associated with the receiver,
	but only if not already realized. Subclasses must implement #basicRealize"

	^self isRealized
		ifFalse: [
			self
				basicRealize;
				beFinalizable]

Consequences

Known Uses

Related Patterns