Finalization

David Shaffer cdshaffer at acm.org
Mon Mar 27 15:42:57 UTC 2006


I've started to make an attempt at this but I didn't get far....I've got
a class which mimics WeakValueAssociation but has nextLink and executor
ivars.

Andreas Raab wrote:

> signalFinalization: oop
>   (self fetchClassOf: oop) == self classFinalizer ifTrue:[
>     self addLastLink: oop toList: self finalizerList.
>     self forceInterruptCheck.
>     pendingFinalizationSignals _ pendingFinalizationSignals + 1.
>   ].
>
>
addLastLink:toList: is defined in Interpreter but the current
finalization code resides in ObjectMemory.  Should I

a) just send it anyway...yuk?
b) move it up?
c) duplicate it (with different name?) in ObjectMemory?

Also, how do I safely unlink elements from the "ReadyForFinalization"
list in Smalltalk?  We will always be removing from the front of the
list.  I looked at Process which simply sends #remove: but this seems
dangerous if a GC should occur during execution of this method (there is
a race condition related to the "firstLink"):

remove: aLink ifAbsent: aBlock 
    "Remove aLink from the receiver. If it is not there, answer the
result of
    evaluating aBlock."

    | tempLink |
    aLink == firstLink
        ifTrue: [firstLink _ aLink nextLink.      "if GC happens here
then lastLink is invalid..."
                aLink == lastLink
                    ifTrue: [lastLink _ nil]]
        ifFalse: [tempLink _ firstLink.
                [tempLink == nil ifTrue: [^aBlock value].
                 tempLink nextLink == aLink]
                    whileFalse: [tempLink _ tempLink nextLink].
                tempLink nextLink: aLink nextLink.
                aLink == lastLink
                    ifTrue: [lastLink _ tempLink]].
    aLink nextLink: nil.
    ^aLink

> WeakRegistry and other users would be fairly straighforward to deal
> with - they'd just store (strong references to) Finalizer's instead of
> (weak) object references and the finalizer would remove itself from
> the registry. No big deal, really.


While _some_ users of "Weak" structures won't care about finalization,
it looks like many will.  The "dictionary-like" objects all rehash
whenever one of their keys is collected.  Seaside, in particular, does this:

    dict _ WeakIdentityKeyDictionary new: aNumber.
    WeakArray addWeakDependent: dict.

so that dict gets rehashed whenever needed.  All that we're doing now is
providing a hint as to who was affected (so we'll only rehash
dictionaries which had values reclaimed) but suppose, for example, that
the same dictionary had multiple collected keys, now instead of
rehashing once we'll have to be a bit cleaver or we're going to consider
rehashing for each reclaimed object.  That is, we'll run
WeakKeyDictionary>>finalizeValues for each collected object that
corresponds to a key in this dictionary. 

Old Scheme
---------------------
Loops over all WeakArray's FinalizationDependents sending finalizeValues
since it doesn't know who cares about that object

New Scheme
-----------------------
Loops removing elements from Finalizable list running the executor for
each (these executors presumably send #finalizeValues to dictionary if
they correspond to a dictionary entry)

Since almost all of the of the elements of FinalizationDependents (in a
Seaside image) are WeakIdentityKeyDictionaries there will be some
savings but not as much as I had hoped and I think this method would be
particularly wasteful if there isn't some way to coalesce sends of
#finalizeValues.


David




More information about the Squeak-dev mailing list