Appendix B: Dolphin Pattern Book > Object Lifetime Patterns >
Smalltalk is a garbage collected system, and Smalltalk objects are not normally notified before they are destroyed. In general such notifications are not required, because the memory occupied by garbage collected objects is automatically and 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 resources. Explicitly performing such clean-up operations may be very tricky to time correctly, because the lifetime of the objects is not always predictable.
What we need is mechanism whereby an object will be sent a message just before it is about to be garbage collected. How can this be achieved?
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).|
|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.|
For more information on finalization please refer to Weak References and Finalization.
|•||GraphicsTool is the superclass of most of the classes in Dolphin which encapsulate Windows drawing objects. GraphicsTool adds the finalization mark after creating an owned external resource:|
"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]
|•||GraphicsTool. Subclasses are wrappers for UI objects, finalization ensures the external resource is released..|
|•||File. Finalization is used to ensure the file is closed.|
|•||FileStream. Finalization is used to ensure that the streams buffers are flushed to the underlying medium.|
|•||Process. Finalization is used to ensure the process is correctly terminated so that any unwind blocks are run.|
|•||ExternalMemory. Finalization is used to ensure that memory allocated from external heaps is returned.|
|•||OLE COM. Finalization is used to manage the lifetime of interface objects (IUnknown and subclasses) so that explicit management of the reference count is not necessary.|
|1.||Finalization can only occur after a garbage collection cycle, and is a low priority operation, so clean-up operations performed this way are far from immediate, and may be delayed indefinitely if a CPU bound process is running.|
|2.||The objects referenced from finalizable objects cannot be garbage collected until the objects have been finalized.|
|3.||Finalization has considerable overhead relative to explicitly releasing resources.|
|4.||Using the finalization of objects to maintain other data structures breaks encapsulation, and may require process synchronization.|
|5.||Finalization is performed asynchronously at an unpredictable time after the last strong reference to an object has been removed. Furthermore finalization is performed after all weak references to an object have been removed by the garbage collector. This means that very little can be assumed about the state of the environment in the #finalize method, and successful rescue is difficult.|
|6.||Order of finalization may be significant, and may be difficult to guarantee where one finalizable object weakly references another since there is no notion of ownership.|