FileStreams
, Sockets
etc.
Color
, Font
,
View
For the programmer, it is much easier (and less error prone) to use the finalization mechanism, instead of doing the housekeeping herself. Just think of a bitmap image with a local colormap; how would you know who else in the system uses those colors and when they can be freed without danger ?
To support object finalization, Smalltalk/X includes
the WeakArray
class, which provides a low level
mechanism and Registry
which offers a more
programmer friendly higher level interface.
WeakArray
are arrays which do not prevent their elements from being garbage
collected. This means that the reference from the weakArray to an object does not
count as a reference with respect to garbage collection.
Using this basic mechanism for object finalization is straightforward:
keep the relevant information (such as fileDescriptor, window handle etc.) in another array,
and references to the corresponding smalltalk object in a weakArray.
Whenever the weakArray gets informed about some object being reclaimed, scan it for nil entries and free the corresponding resource as stored in the other array (i.e. close the file, free the window handle etc.).
Another use of weakArrays is with caching, for example, you can keep some recently used data in a weakArray, reusing it if present. The cache will be automatically 'flushed' by the garbage collector in regular intervals.
Registry
is provided.
Registries internally perform the above operations to keep track of
reclaimed objects. However, instead of storing some device handles
in the other array, they keep shallow copies of the original
objects there, and send a notification to this copy.
The object which wants to do some finalization actions should be registered in a registry, and will later (at finalization time) receive aTechnically, we cannot send messages to the original object, since that object is already gone at that time. Instead, the shallow copy created by the registry will receive thedisposed
-message.
In thise method, perform cleanup as required. For example, close an underlying file by doing "self closeFile
".
disposed
message.
Since the copy has the same contents as the original
(especially: fileDescriptors
and window handles), its disposed
method can be written as if it
was the original.
Lets summarize what is needed for proper finalization:
initialize
method)
disposed
method for cleanup.
dispose
message is a shallow copy, not the original.
Although in most cases, this is transparent, there are situations where it does
make a difference: when keeping objects in
identitySets or identityDictionaries, which compare for identity instead
of equality. The shallow copy will of course never be identical,
but can be made equal to the original.
Since creating a shallow copy may be expensive (especially for big or
heavily used objects), the copy is created using a slighly different
copy method: shallowCopyForFinalization
.
The default implementation for this (in Object
)
simply recalls shallowCopy
.
You may want to redefine this method in your class - especially
if you do not need all instance variables at finalization time.
For example, the Cursor
classes disposed
method
will only need the cursors resource-id - therefore, a special
shallowCopyForFinalization
has been defined, which creates an
empty copy with only the id being copied.
See example uses in Form
, Cursor
, Color
,
Font
or ExternalStream
for how
registries are used,
and the implementation of Registry
for more protocol information.
Copyright © Claus Gittinger Development & Consulting, all rights reserved
(cg@ssw.de)