#BUGFIX by stefan
class: WeakValueDictionary
added:
#includesIdentical:
#removeIdentityValue:ifAbsent:
Check for ni or SmallIntger values
--- a/WeakValueDictionary.st Thu Jul 21 11:28:47 2016 +0200
+++ b/WeakValueDictionary.st Thu Jul 21 15:50:52 2016 +0200
@@ -1,3 +1,5 @@
+"{ Encoding: utf8 }"
+
"
COPYRIGHT (c) 1992 by Claus Gittinger
All Rights Reserved
@@ -105,7 +107,7 @@
].
].
- ret class == SmallInteger ifTrue:[
+ (ret isNil or:[ret class == SmallInteger]) ifTrue:[
ret := somethingRespondingToValue value
].
^ ret
@@ -134,7 +136,7 @@
].
].
- val class == SmallInteger ifTrue:[
+ (val isNil or:[val class == SmallInteger]) ifTrue:[
self error:'WeakValueDictionary: invalid value'.
].
@@ -149,7 +151,7 @@
|val|
- anObject class == SmallInteger ifTrue:[
+ (anObject isNil or:[anObject class == SmallInteger]) ifTrue:[
self error:'WeakValueDictionary: invalid value'.
].
@@ -169,6 +171,35 @@
"Modified: 29.1.1997 / 15:08:45 / cg"
!
+removeIdentityValue:aValue ifAbsent:aBlock
+ "remove the association under aValue from the collection,
+ return the key previously stored there.
+ If it was not in the collection return the result
+ from evaluating aBlock.
+
+ Redefined to avoid synchronization problems, in case
+ of interrupts (otherwise, there could be some other operation
+ on the receiver done by another process, which garbles my contents)."
+
+ |ret|
+
+ (aValue isNil or:[ aValue class == SmallInteger ]) ifTrue:[
+ ^ aBlock value.
+ ].
+ OperatingSystem blockInterrupts ifTrue:[
+ "/ already blocked
+ ret := super removeIdentityValue:aValue ifAbsent:aBlock
+ ] ifFalse:[
+ [
+ ret := super removeIdentityValue:aValue ifAbsent:aBlock
+ ] ensure:[ OperatingSystem unblockInterrupts. ].
+ ].
+ ^ ret.
+
+ "Created: 6.5.1996 / 14:47:37 / stefan"
+ "Modified: 8.5.1996 / 14:54:09 / stefan"
+!
+
removeKey:aKey ifAbsent:aBlock
"remove the association under aKey from the collection,
return the value previously stored there.
@@ -192,13 +223,17 @@
].
].
+ (ret isNil or:[ret class == SmallInteger]) ifTrue:[
+ ^ aBlock value.
+ ].
+
^ ret
"Modified: 6.5.1996 / 12:44:07 / stefan"
"Created: 6.5.1996 / 14:47:37 / stefan"
!
-removeValue:aKey ifAbsent:aBlock
+removeValue:aValue ifAbsent:aBlock
"remove the association under aValue from the collection,
return the key previously stored there.
If it was not in the collection return the result
@@ -210,12 +245,16 @@
|ret|
+ (aValue isNil or:[aValue class == SmallInteger]) ifTrue:[
+ ^ aBlock value.
+ ].
+
OperatingSystem blockInterrupts ifTrue:[
"/ already blocked
- ret := super removeValue:aKey ifAbsent:aBlock
+ ret := super removeValue:aValue ifAbsent:aBlock
] ifFalse:[
[
- ret := super removeValue:aKey ifAbsent:aBlock
+ ret := super removeValue:aValue ifAbsent:aBlock
] ensure:[
OperatingSystem unblockInterrupts.
].
@@ -246,8 +285,8 @@
do:aBlock
super do:[:eachValue|
- "garbage collected values will change to a SmallInteger"
- eachValue class ~~ SmallInteger ifTrue:[
+ "garbage collected values will change to nil or a SmallInteger"
+ (eachValue notNil and:[eachValue class ~~ SmallInteger]) ifTrue:[
aBlock value:eachValue.
].
].
@@ -319,7 +358,7 @@
|ret wasBlocked|
- anObject class == SmallInteger ifTrue:[
+ (anObject isNil or:[anObject class == SmallInteger]) ifTrue:[
"Integers cannot be stored into a WeakValueDictionary"
^ false.
].
@@ -334,6 +373,23 @@
"Created: 1.7.1997 / 15:41:14 / cg"
!
+includesIdentical:anObject
+ "redefined to block interrupts
+ (avoid change of the dictionary while accessing)"
+
+ |ret wasBlocked|
+
+ (anObject isNil or:[anObject class == SmallInteger]) ifTrue:[
+ "Integers cannot be stored into a WeakValueDictionary"
+ ^ false.
+ ].
+
+ wasBlocked := OperatingSystem blockInterrupts.
+ ret := super includesIdentical:anObject.
+ wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
+ ^ ret
+!
+
includesKey:key
"redefined to check for already collected values"