On Fri, Jun 7, 2013 at 2:34 AM, Camille Teruel
<camille.teruel@gmail.com> wrote:
�On 7 juin 2013, at 11:19, Pharo Issue Tracker wrote:
A FogBugz case was edited by Stephane Ducasse.
Case ID: �����10840
Title: �������WeakSet>>#size utterly broken
Status: ������Resolved (Fix Review Needed)
Category: ����Bug
Project: �����Collection
Area: ��������Misc
Priority: ����3 - Must Fix
Milestone: ���Pharo3.0: 30/03/2014
Assigned To: �Camille Teruel
URL: ���������
https://pharo.fogbugz.com/f/cases/10840Last message:
Please can you send a mail to the mailing-list so that we all discuss this problems.
Hello everyone,
WeakSet>>#size is broken as demonstrated by the following snippet:
set := WeakSet new.
set add: Object new.
Smalltalk garbageCollect.
set size. "answers 1 instead of 0"
That is because a WeakSet has no mean to know when its items get garbage collected, and thus the tally cannot be updated.
So we need to override #size in Weak, I propose:
size
| counter |
counter := 0.
self do: [ :e | counter := counter + 1 ].
^ counter
But that it rather inefficient for such a simple query.
One way is to add WeakSets to FInalizationDependents and implement finalizeValues to update the size. �But that's making work. �A lazy solution might be better.
You *could*, I suppose, use the VM's count of the number of incremental and full GCs (alas there's no single count). �I think this is too ugly and one would need something neater, but it would work like this:
size
� � � | newGCCount |
� � � newGCCount := self getGCCount.
� � � newGCCount == existingGCCount ifTrue:
� � � � � [^tally].
� � � tally := self computeActualSIze.
� � � existingGCCount := newGCCount
where
� � getGCCount
� � � � ^(Smalltalk vmParameterAt: 7) + (Smalltalk vmParameterAt: 9)
� � ��
There are obviously thread-safety issues here, but there are issues with the existing code and your suggestion too ;)
The most useful single count here would be a count that was incremented once in each GC that finalized one or more references.
Note also that for this to be reliable instances' record of the count would have to be invalidated on snapshot or start-up, which could entail an expensive allInstancesDo:.
Perhaps the class WeakSet should maintain its instances in (of course) a WeakSet and then add only itself to FinalizationDependents and enumerate the set on finalization?
I note that in the VisualWorks VM, objects that have references finalized are added to a queue so every instance that loses a reference gets sent finalize, instead of only dependents as in Squeak. �This has its won problems (the VM must cope with a potentially large list) but I think it provides more convenient control.
�