<div dir="ltr">Argh!  This one:   :)<div><br></div><div>|d|<br>d:={('hello' copy) -> 'world'.  'hello2' copy -> 'there'} as: WeakKeyDictionary.<br>Smalltalk garbageCollect.<br>self assert: (d includesKey: 'hello') not.   "good"<br>self assert: d notEmpty.   "bad"<span style="color:rgb(80,0,80)"><br>self assert: d array asSet size > 1.   "bad"<br></span>d finalizeValues.   "required!"<span style="color:rgb(80,0,80)"><br>self assert: d array asSet size = 1.   "good"<br></span>self assert: d isEmpty.   "good"<br>self assert: (d reject: [ : each | each isNil ]) isEmpty.   "alternative to finalizeValues"<br><div><br></div></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Tue, May 31, 2022 at 7:12 PM Chris Muller <<a href="mailto:asqueaker@gmail.com" target="_blank">asqueaker@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div dir="ltr">Please replace the script in my prior email with this one.  Even though it still illustrates the problem, the previous script has a conceptual bug because I was playing around with Identity vs. regular and forgot to correct it back.</div><div><br></div><div>|d|<br>d:={('hello' copy) -> 'world'.  'hello2' copy -> 'there'} as: WeakKeyDictionary.<br>Smalltalk garbageCollect.<br>self assert: (d includesKey: obj1) not.<br>self assert: d notEmpty.<br>self assert: d array asSet size > 1.<br>d finalizeValues.<br>self assert: d array asSet size = 1.<br>self assert: d isEmpty.<br>self assert: (d reject: [ : each | each isNil ]) isEmpty.<br></div><div><br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Tue, May 31, 2022 at 7:04 PM Chris Muller <<a href="mailto:asqueaker@gmail.com" target="_blank">asqueaker@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div dir="ltr">Hi Jakob, hi Levente,</div><div dir="ltr"><br></div><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">> 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?<br>
> <br>
> - Must one ensure that #finalizeValues is sent to one's WeakKeyDictionary instance regularly?<br></blockquote><div><br></div><div>Yes.  Either that, or you need to otherwise somehow remove the garbage collected entries from its internal array.</div><div><br></div><div>Otherwise, the WeakKeyDictionary will only ever grow in size internally, with a bunch of nil keys.  Here's a short script showing the mechanics and assumptions of this:</div><div><br></div>|d|<br>d:={'hello' copy -> 'world'.  'hello' copy -> 'there'} as: WeakIdentityKeyDictionary.<br>Smalltalk garbageCollect.<br>self assert: (d includesKey: 'hello') not.   "good"<br>self assert: d notEmpty.    "bad"<br>self assert: d array asSet size > 1.   "bad"<br>d finalizeValues.   "required!"<br>self assert: d array asSet size = 1.   "good"<br>self assert: d isEmpty.    "good"<br><div> <br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Only if you are interested in finalization and want to do it your own way. <br>
And even then, only if you want to have your finalizer executed as soon as <br>
possible when a key of your dictionary has been garbage collected.<br>
So, if you just want a dictionary with weak keys, the answer is no.<br></blockquote><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><br>
> - Should one register the dictionary instance via WeakArray addWeakDependent:?<br>
<br>
Same as above. I'm not even sure it would work with <br>
WeakKeyDictionaries. It's intended to work with WeakRegistries, which are <br>
the main providers of finalization.<br></blockquote><div><br></div><div><div>I believe it would.  Check out WeakArray class>>#finalizationProcess and, perhaps doing so would allow those WeakKey dictionary's to clean themselves up automatically so you don't have to time sending #finalizeValues yourself.  But, I don't trust it, because it's hard to tell, because #finalizationProcess waits on FinalizationSemaphore, which is an opaque VM-controlled semaphore which I have no idea when it's signaled.</div><div>  </div></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">> - 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?<br>
<br>
One[1] that has never really been used in Squeak and has been <br>
obsoleted by ephemerons. Even though we do not use ephemerons for <br>
finalization yet.<br>
<br>
> - If the answers to the questions above do not give it away, what must one do to use a WeakKeyDictionary safely?<br>
<br>
The difference between a regular Dictionary and a WeakKeyDictionary is <br>
that the latter cannot hold nil as a key, and your associations may <br>
disappear when their keys are not referenced strongly.<br></blockquote><div><br></div><div>They only disappear from the perspective of using the object API (excluding #isEmpty and #notEmpty as demonstrated by the script above).  Internally, the former Association objects don't disappear, and still take up memory.</div><div><br></div><div>Igor made some alternative-implementation WeakKeyDictionary's for Magma back in 2007 which are faster than the one's built into Squeak to this day (last I checked, anyway).  If interested, load "MaBase" from SqueakMap and then see MaWeakIdentityKeyDictionary.</div><div><br></div><div>Regards,</div><div>  Chris</div></div></div>
</blockquote></div></div>
</blockquote></div>