[squeak-dev] Improving WeakKeyDictionary comment

Levente Uzonyi leves at caesar.elte.hu
Tue Jun 7 09:28:26 UTC 2022


Hi Jakob,

On Mon, 6 Jun 2022, Jakob Reschke wrote:

> Hi,
> So to sum up: if the WeakKeyDictionary gets new elements added frequently, causing it to consider growing every once in a while, it may not be necessary to register it with WeakArray. On the other hand, if the dictionary is

They don't need to grow. It's enough if they reach and go over their full 
capacity. They may even shrink afterwards as my example showed.

> seldom modified, one can register it with WeakArray to get stale associations collected "as soon as possible." Alternatively I should consider sending #finalizeValues by myself as regularly as it makes sense for
> my application. Is that right?

I would still refrain from registering a WeakKeyDictionary to be triggered 
by the finalization process, because #finalizeValues will be sent by a 
different process, and Dictionaries are not thread-safe, so race 
conditions may occur.
WeakRegistries are safe to register with the finalization rpocess, because 
they are thread-safe.

> 
> In my latest use case I wanted to use a WeakIdentityKeyDictionary to hold certain "on-demand inst vars" for other kinds of objects (like the DependentsFields dictionary in Object, which adds a list of dependents to any kind
> of object on demand). So in general I would like each on-demand value to be collected when the object to which it belongs gets collected. But I expect that new keys will be added only in rare circumstances (except during the
> unit tests), and that the keys will be garbage-collected only in rare circumstances as well. The keys are expected to be PackageInfos from the package organizer, so changes come only when the extra info is accessed for a
> package for the first time, or when a package gets removed from the system. I tried turning my dictionary from an IdentityDictionary to a WeakIdentityKeyDictionary (with #newFrom:) without registering, and it kept lots of
> garbage elements, which were previously added during repeated test runs. Soon after registering it with WeakArray, most elements were removed. On the other hand, now most of the invocations to #finalizeValues go to waste
> because as mentioned, packages do not disappear frequently under normal circumstances. Hmm...

Currently, the right thing to do is to use a WeakIdentityKeyDictionary
and register a finalizer for each key (into the global WeakRegistry).
Something like:

m := Mutex new.
w := WeakIdentityKeyDictionary new.
1 to: 100 do: [ :onDemandInstVars |
 	| pseudoPackage |
 	pseudoPackage := Object new.
 	m critical: [ w at: pseudoPackage put: onDemandInstVars ].
 	pseudoPackage
 		toFinalizeSend: #cull: "Must be cull: to ignore the argument nil"
 		to: [ m critical: [ w finalizeValues ] ]
 		with: nil ].
before := w array count: #notNil.
Smalltalk garbageCollectMost.
after := w array count: #notNil.
{ before. after }


Levente


More information about the Squeak-dev mailing list