#BUGFIX by stefan
authorStefan Vogel <sv@exept.de>
Thu, 21 Jul 2016 15:50:52 +0200
changeset 20165 529ce6e78617
parent 20164 7333519ac040
child 20166 40f9f1f07a68
#BUGFIX by stefan class: WeakValueDictionary added: #includesIdentical: #removeIdentityValue:ifAbsent: Check for ni or SmallIntger values
WeakValueDictionary.st
--- 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"