[squeak-dev] Improving WeakKeyDictionary comment

Jakob Reschke forums.jakob at resfarm.de
Fri May 27 19:28:40 UTC 2022

Dear Squeakers,

Whenever I read the class comment of WeakKeyDictionary, I know that I have
to take care of something, but I do not know what. Can we improve the
comment please to tell the readers more directly what is expected of them?

- Must one ensure that #finalizeValues is sent to one's WeakKeyDictionary
instance regularly?
- Should one register the dictionary instance via WeakArray
- Which VM feature is the WeakRegistry class comment referring to; is it
the semaphore used on the class side of WeakArray; and is it relevant to
the use of WeakKeyDictionary?
- If the answers to the questions above do not give it away, what must one
do to use a WeakKeyDictionary safely?

I volunteer to submit the results as comments in WeakKeyDictionary,
WeakArray, and WeakRegistry to the Inbox.

The following is just a transcript of the cynical voice in my head while
trying to find some answers today. You do not need to read it. If you can
answer the questions above, I would be more than happy. ;-)


WeakKeyDictionary class comment:
"I am a dictionary holding only weakly on my keys. This is a bit dangerous
since at any time my keys can go away. Clients are responsible to register
my instances by WeakArray such that the appropriate actions can be taken
upon loss of any keys.

See WeakRegistry for an example of use."

So I look at WeakArray and WeakRegistry. WeakArray has only three methods,
none of which seem to deal with garbage collection, finalization, or
elements vanishing. On the class side there is #addWeakDependent:, which
deals with class variables that have Finalization in their name. Is this
what is meant by "register my instances by WeakArray"...? There is no
method comment, so I do not know whether I should call that with my new
WeakKeyDictionary or not, or what the effect would be. The class comment of
WeakArray also does not tell me anything about finalization or registration.

Looking at WeakRegistry, it associates the registered objects with an
executor, and "When the object is garbage collected, the executor can take
the appropriate action for any resources associated with the object." Not
sure whether I need anything like this for my WeakKeyDictionary instance...
It also says that it uses a "new VM feature" (the comment is from 2010),
but does not say which one or how it works. In WeakRegistry, the
'valueDictionary' is a Weak(Identity)KeyDictionary. It is used in 10
methods, which takes some time to read. I can see that the dictionary
stores WeakFinalizerItems, which holds the executors for an object. In
#finalizeValues, the same is sent to the dictionary and to all objects in
the 'executors' inst var, which is then set to nil. In the
WeakKeyDictionary, #finalizeValues drops elements whose keys have become
nil. Ah ha, so do I need to take care of sending #finalizeValues to my
WeakKeyDictionary regularly...? In #installFinalizer a finalizer block is
attached to the dictionary. This finalizer block adds its argument to the
'executors'. Taking a detour back to WeakKeyDictionary to find out when
that block is evaluated... So when the dictionary receives #finalizeValues,
fixes hash collisions, or grows, and notices keys that are gone, the values
(WeakFinalizerItems) will be added to the 'executors', so that back in
#finalizeValues of WeakRegistry, #finalizeValues will eventually be sent to
all WeakFinalizerItems of garbage collected elements. But I still do not
know what sends #finalizeValues to the WeakRegistry in the first place. The
rest of the WeakRegistry methods do not seem to do anything fancy with the
dictionary. Collision fixing or growing is unlikely to happen to the
WeakKeyDictionary if it is not modified for a while, all the same while the
keys may be garbage collected.

For another chance, I read the class side methods of WeakRegistry. The #new
constructor of WeakRegistry uses the previously discovered
#addWeakDependent: method of WeakArray, hear hear. Reading further about
the finalizationProcess in WeakArray, a FinalizationSemaphore is kept in
the SpecialObjectsArray, which means that the VM is supposed to use this
semaphore. The finalizationProcess sends #finalizeValues---bingo---to the
dependents when the semaphore is signalled. Combining the clues I guess
that this semaphore is singalled after the garbage collection has run. Is
that the mysterious "new VM feature"  to which the comment of
WeakRegistry---at which I am not looking right now---was referring...?
Since it is not spelled out in a comment, and since I am not willing to
look at the VM sources now, my guess remains an assumption. Under this
assumption, I could register my WeakKeyDictionary as a weak dependent in
WeakArray class, so that after each GC #finalizeValues would be sent to my
dictionary, which would clean up stale entries, which is likely the thing I
was expected to care about. But maybe I missed another piece of the puzzle.

Frankly, I do not wish to reverse engineer how the WeakRegistry works
before I can use a WeakKeyDictionary. For that, the workings of
WeakRegistry are not simple or well-described enough and it apparently
needs some VM knowledge.

Kind regards,
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20220527/1c041c19/attachment.html>

More information about the Squeak-dev mailing list