'From Squeak3.5 of ''11 April 2003'' [latest update: #5180] on 19 May 2003 at 8:23:11 pm'! "Change Set: EasyFinalization Date: 19 May 2003 Author: Andreas Raab Support for easier finalization. In order to finalize an object use: someObject toFinalizeSend: aSelector to: aFinalizer with: aResourceHandle. For example Object new toFinalizeSend: #show: to: Transcript with: 'bye bye'. Note that an object cannot finalize itself (as Squeak provides post-mortem finalization) so you need a third party to do it. Often, the class of the object you are finalizing is the right place to put this. In addition, neither the finalizer nor the resource handle may reference the object directly as this would prevent the object from being garbage collected. A more typical example would be along the lines of: StandardFileStream>>open ... open the file here ... self toFinalizeSend: #closeHandle: to: self class with: fileHandle. Note that we can also unregister the object, e.g., do something like StandardFileStream>>close ... close the file here ... self finalizationRegistry remove: self ifAbsent:[]. in order to prevent 'accidentally' closing the resource in finalization. "! Object subclass: #ObjectFinalizer instanceVariableNames: 'receiver selector arguments ' classVariableNames: '' poolDictionaries: '' category: 'System-Finalization'! Collection subclass: #WeakRegistry instanceVariableNames: 'valueDictionary accessLock ' classVariableNames: 'Default ' poolDictionaries: '' category: 'Collections-Weak'! !Object methodsFor: 'finalization' stamp: 'ar 5/19/2003 20:10'! finalizationRegistry "Answer the finalization registry associated with the receiver." ^WeakRegistry default! ! !Object methodsFor: 'finalization' stamp: 'ar 5/19/2003 20:14'! toFinalizeSend: aSelector to: aFinalizer with: aResourceHandle "When I am finalized (e.g., garbage collected) close the associated resource handle by sending aSelector to the appropriate finalizer (the guy who knows how to get rid of the resource). WARNING: Neither the finalizer nor the resource handle are allowed to reference me. If they do, then I will NEVER be garbage collected. Since this cannot be validated here, it is up to the client to make sure this invariant is not broken." self == aFinalizer ifTrue:[self error: 'I cannot finalize myself']. self == aResourceHandle ifTrue:[self error: 'I cannot finalize myself']. ^self finalizationRegistry add: self executor: (ObjectFinalizer new receiver: aFinalizer selector: aSelector argument: aResourceHandle)! ! !ObjectFinalizer methodsFor: 'initialize' stamp: 'ar 5/19/2003 20:12'! receiver: aReceiver selector: aSelector argument: anObject receiver := aReceiver. selector := aSelector. arguments := Array with: anObject! ! !ObjectFinalizer methodsFor: 'finalization' stamp: 'ar 5/19/2003 20:13'! finalize "Finalize the resource associated with the receiver. This message should only be sent during the finalization process. There is NO garantuee that the resource associated with the receiver hasn't been free'd before so take care that you don't run into trouble - this all may happen with interrupt priority." [receiver perform: selector withArguments: arguments] on: Error do:[:ex| ex return]. ! ! !WeakRegistry methodsFor: 'adding' stamp: 'ar 5/19/2003 20:08'! add: anObject executor: anExecutor "Add anObject to the receiver. Store the object as well as the associated executor." self protected:[ valueDictionary at: anObject put: anExecutor. ]. ^anObject! ! !WeakRegistry class methodsFor: 'accessing' stamp: 'ar 5/19/2003 20:10'! default ^Default ifNil:[Default := self new]! ! ObjectFinalizer removeSelector: #receiver:selector:!