[Pharo-project] 1.1 -- Inconsistent enumeration behavior of WeakKeyDictionary and subclasses
If you run this in 1.1: | dict | dict := WeakKeyDictionary new. dict at: 'foo' copy put: 'bar'. Smalltalk garbageCollect. dict associationsDo: [:assoc | self halt]. dict do: [:val | self halt] It stops in the second halt, but not the first. This is because #associationsDo: does not include associations whose keys have been GCed, but #do: *does* include values whose corresponding keys have been GCed. This behavior seems inconsistent, and not particularly useful, and also seems to contradict the comments by the author in the Squeak bug from 2007, from which I'd think that #do: would not include the value which it currently does. So I *think* this is an oversight, and is easy to fix by defining WeakKeyDictionary>>do: in terms of self associationsDo:. But then there's the question of #size. The collection above answers 1 to #size, which also seems wrong. Comments? Regards, -Martin
2009/12/31 Martin McClure <martin@hand2mouse.com>:
If you run this in 1.1:
| dict | dict := WeakKeyDictionary new. dict at: 'foo' copy put: 'bar'. Smalltalk garbageCollect. dict associationsDo: [:assoc | self halt]. dict do: [:val | self halt]
It stops in the second halt, but not the first.
This is because #associationsDo: does not include associations whose keys have been GCed, but #do: *does* include values whose corresponding keys have been GCed.
This behavior seems inconsistent, and not particularly useful, and also seems to contradict the comments by the author in the Squeak bug from 2007, from which I'd think that #do: would not include the value which it currently does.
It is useful in terms, that sometimes you don't want to see the objects which GCed, but sometimes do. See how WeakRegistry using this. The lack of ephemerons support in VM, forcing us to deal with such things manually.
So I *think* this is an oversight, and is easy to fix by defining WeakKeyDictionary>>do: in terms of self associationsDo:.
But then there's the question of #size. The collection above answers 1 to #size, which also seems wrong.
#size for weak key dict is non-deterministic. Because even if you want to know the exact number of elements, you will need to iterate over the collection, but then, iteration can trigger GC, and you have a big chances to answer wrong value.
Comments?
Regards,
-Martin
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
-- Best regards, Igor Stasenko AKA sig.
Igor Stasenko wrote:
2009/12/31 Martin McClure <martin@hand2mouse.com>:
If you run this in 1.1:
| dict | dict := WeakKeyDictionary new. dict at: 'foo' copy put: 'bar'. Smalltalk garbageCollect. dict associationsDo: [:assoc | self halt]. dict do: [:val | self halt]
It stops in the second halt, but not the first.
This is because #associationsDo: does not include associations whose keys have been GCed, but #do: *does* include values whose corresponding keys have been GCed.
This behavior seems inconsistent, and not particularly useful, and also seems to contradict the comments by the author in the Squeak bug from 2007, from which I'd think that #do: would not include the value which it currently does.
It is useful in terms, that sometimes you don't want to see the objects which GCed, but sometimes do. See how WeakRegistry using this. The lack of ephemerons support in VM, forcing us to deal with such things manually.
I see the value in being able to choose both. WeakRegistry uses #allAssociationsDo:, not #associationsDo:. Seems like it would be more consistent to also have an #allDo: that includes values of collected keys, and a #do: that does not.
So I *think* this is an oversight, and is easy to fix by defining WeakKeyDictionary>>do: in terms of self associationsDo:.
But then there's the question of #size. The collection above answers 1 to #size, which also seems wrong.
#size for weak key dict is non-deterministic. Because even if you want to know the exact number of elements, you will need to iterate over the collection, but then, iteration can trigger GC, and you have a big chances to answer wrong value.
That seems reasonable, though there's no effort to even come close in size. -Martin
2009/12/31 Martin McClure <martin@hand2mouse.com>:
Igor Stasenko wrote:
2009/12/31 Martin McClure <martin@hand2mouse.com>:
If you run this in 1.1:
| dict | dict := WeakKeyDictionary new. dict at: 'foo' copy put: 'bar'. Smalltalk garbageCollect. dict associationsDo: [:assoc | self halt]. dict do: [:val | self halt]
It stops in the second halt, but not the first.
This is because #associationsDo: does not include associations whose keys have been GCed, but #do: *does* include values whose corresponding keys have been GCed.
This behavior seems inconsistent, and not particularly useful, and also seems to contradict the comments by the author in the Squeak bug from 2007, from which I'd think that #do: would not include the value which it currently does.
It is useful in terms, that sometimes you don't want to see the objects which GCed, but sometimes do. See how WeakRegistry using this. The lack of ephemerons support in VM, forcing us to deal with such things manually.
I see the value in being able to choose both. WeakRegistry uses #allAssociationsDo:, not #associationsDo:. Seems like it would be more consistent to also have an #allDo: that includes values of collected keys, and a #do: that does not.
Well, let first take in account that Dictionary is not well consistent with Collection protocol. For instance, if #add: expects association, then one could say, that Dictionary is a Collection of associations. But if you try pass association to #includes: , or observe what objects iterated in #do: you'll find out that its not. And so, if you treat a dictionary as a collection of values, indexed by associated keys, then from this POV, a #do: behavior in weak dict is consistent with Collection protocol. But #associationsDo: will not report same number of entries, since some of them having invalid (nil) keys.
So I *think* this is an oversight, and is easy to fix by defining WeakKeyDictionary>>do: in terms of self associationsDo:.
But then there's the question of #size. The collection above answers 1 to #size, which also seems wrong.
#size for weak key dict is non-deterministic. Because even if you want to know the exact number of elements, you will need to iterate over the collection, but then, iteration can trigger GC, and you have a big chances to answer wrong value.
That seems reasonable, though there's no effort to even come close in size.
I don't think that #size having any value for weak key dicts at all, since there is no strict guarantees at any point of time, that collection will have same number of elements as few cycles before. So, measuring size of weak dict is pointless, and existing simply to conform with Collection protocol.
-Martin
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
-- Best regards, Igor Stasenko AKA sig.
I see the value in being able to choose both. WeakRegistry uses #allAssociationsDo:, not #associationsDo:. Seems like it would be more consistent to also have an #allDo: that includes values of collected keys, and a #do: that does not.
yes and a good method comment
So I *think* this is an oversight, and is easy to fix by defining WeakKeyDictionary>>do: in terms of self associationsDo:.
But then there's the question of #size. The collection above answers 1 to #size, which also seems wrong.
#size for weak key dict is non-deterministic. Because even if you want to know the exact number of elements, you will need to iterate over the collection, but then, iteration can trigger GC, and you have a big chances to answer wrong value.
That seems reasonable, though there's no effort to even come close in size.
-Martin
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
participants (3)
-
Igor Stasenko -
Martin McClure -
Stéphane Ducasse