Some objects represent external resources. It is important that these external resources are released when the associated object is garbage collected.
There are a number of methods associated with the termination of objects:
The #basicFree method should free (de-allocate) external resources owned by the receiver. The receiver is left in an invalid state and, as such, #basicFree can only be called once.
The #free method should free external resources (typically by sending #basicFree) and also nil the instance variables referencing those external resources. These objects can recreate their valid state (often using Lazy Initialisation) from the information contained in the receiver. Because the appropriate instance variables are nilled, #free can be sent to an object more than once.
Finalizable objects receive the #finalize message (once only) just before certain death. Objects can be marked as finalizable by sending them the #beFinalizable message. #finalize should generally call #basicFree (there is no need to call #free as the object is about to die).
The #release method should remove (from the receiver) circular references and dependents. It is not necessary to remove circular references which involve a weak reference. The introduction of Weak Collections has meant that #release is less useful.
GraphicsTool is an abstract class which defines behaviour common to GDI objects (pens, brushes etc).
GraphicsTool uses Lazy Initialisation to create the external resource, and Object Liberation Strategy to free it.
GraphicsTool>>handle "Answer the receiver's handle. If unrealized then attempt to realize it first." handle isNil ifTrue: [self realize]. ^handle GraphicsTool>>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] GraphicsTool>>basicRealize "Private - Realize (create) the external resource associated with the receiver, sent from the public method, #realize, if not already realized." ^self subclassResponsibility
GraphicsTool>>free "Free external resources held by the receiver, and leave in a state such that the receiver will be re-realized the next time it is accessed." (self isRealized and: [self ownsHandle]) ifTrue: [ self beUnfinalizable. self basicFree. handle := nil]
GraphicsTool>>basicFree "Private - Free up external resources held by the receiver." GDILibrary default deleteObject: handle
finalize "Private - The receiver is about to expire, so free any external resources. We use #free rather than #basicFree just in case the receiver has been explicitly freed whilst it was waiting in the finalize queue." self free
Brush is the GraphicsTool subclass which represents Win32 GDI brushes:
Brush>>basicRealize "Private - Create the external brush resource associated with the receiver." self ownsHandle ifTrue: [self ownedHandle: self createHandle]
Brush>>createHandle "Private - Answer an external handle to a new brush as described by the logbrush structure." ^GDILibrary default createBrushIndirect: logbrush