Finalization

Andreas Raab andreas.raab at gmx.de
Tue Mar 28 01:32:07 UTC 2006


David Shaffer wrote:
> 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?

a) Send it anyway.

ObjectMemory and Interpreter are always run together - the distinction 
between them (while useful on a conceptual level) is irrelevant in practice.

> 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"):

I think we'll need a primitive for that, since primitives are run 
atomically (so there isn't a GC issue unless you create one ;-)

>> 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. 

Hell, no! What we'll do is instead of just sending #finalize is that 
we'll send #finalize: with the finalizer as an argument (which by 
default just invokes #finalize on the receiver) so that registries can 
remove just the entry that was finalized. Something like here:

Object>>finalize: aFinalizer
    "The receiver, being the executor for the value stored in aFinalizer 
is being asked to perform finalization. By default, we ignore the 
argument and simply call #finalize; but subclasses can use that 
information for good purpose."
   ^self finalize

WeakArray>>finalize: aFinalizer
     self removeEntry: aFinalizer. "you get the idea"

In the (absolute worst and unlikely) case that passing the finalizer 
along isn't enough we can add an extra slot for an object receiving 
notifications about the finalization (but it's probably unnecessary).

> 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.

Nope. It'll be something like a #removeKey: per finalized entry. I can 
guarantee that - if it were different I wouldn't be interested at all ;-)

Cheers,
   - Andreas




More information about the Squeak-dev mailing list