--- a/WeakValueDictionary.st Fri Jul 29 21:39:49 2016 +0100
+++ b/WeakValueDictionary.st Fri Jul 29 21:40:03 2016 +0100
@@ -81,7 +81,7 @@
].
].
- ret class == SmallInteger ifTrue:[
+ (ret isNil or:[ret class == SmallInteger]) ifTrue:[
ret := somethingRespondingToValue value
].
^ ret
@@ -110,7 +110,7 @@
].
].
- val class == SmallInteger ifTrue:[
+ (val isNil or:[val class == SmallInteger]) ifTrue:[
self error:'WeakValueDictionary: invalid value'.
].
@@ -125,7 +125,7 @@
|val|
- anObject class == SmallInteger ifTrue:[
+ (anObject isNil or:[anObject class == SmallInteger]) ifTrue:[
self error:'WeakValueDictionary: invalid value'.
].
@@ -145,6 +145,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.
@@ -157,16 +186,28 @@
|ret|
- [
- ret := super removeKey:aKey ifAbsent:aBlock
- ] valueUninterruptably.
+ OperatingSystem blockInterrupts ifTrue:[
+ "/ already blocked
+ ret := super removeKey:aKey ifAbsent:aBlock
+ ] ifFalse:[
+ [
+ ret := super removeKey:aKey ifAbsent:aBlock
+ ] ensure:[
+ OperatingSystem unblockInterrupts.
+ ].
+ ].
+
+ (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
@@ -178,9 +219,21 @@
|ret|
- [
- ret := super removeValue:aKey ifAbsent:aBlock
- ] valueUninterruptably.
+ (aValue isNil or:[aValue class == SmallInteger]) ifTrue:[
+ ^ aBlock value.
+ ].
+
+ OperatingSystem blockInterrupts ifTrue:[
+ "/ already blocked
+ ret := super removeValue:aValue ifAbsent:aBlock
+ ] ifFalse:[
+ [
+ ret := super removeValue:aValue ifAbsent:aBlock
+ ] ensure:[
+ OperatingSystem unblockInterrupts.
+ ].
+ ].
+
^ ret.
"Created: 6.5.1996 / 14:47:37 / stefan"
@@ -202,6 +255,26 @@
"Created: 7.1.1997 / 16:59:30 / stefan"
! !
+!WeakValueDictionary methodsFor:'enumerating'!
+
+do:aBlock
+ super do:[:eachValue|
+ "garbage collected values will change to nil or a SmallInteger"
+ (eachValue notNil and:[eachValue class ~~ SmallInteger]) ifTrue:[
+ aBlock value:eachValue.
+ ].
+ ].
+!
+
+keysAndValuesDo:aBlock
+ super keysAndValuesDo:[:eachKey :eachValue|
+ "garbage collected values will change to a SmallInteger"
+ eachValue class ~~ SmallInteger ifTrue:[
+ aBlock value:eachKey value:eachValue.
+ ].
+ ].
+! !
+
!WeakValueDictionary methodsFor:'private'!
clearDeadSlots
@@ -232,8 +305,10 @@
and shrink if it makes sense.
Definition of 'too empty' is: 'filled less than 12.5% (i.e. 1/8th)'"
- self clearDeadSlots.
- super possiblyShrink
+ keyArray basicSize > 56 ifTrue:[
+ self clearDeadSlots.
+ super possiblyShrink.
+ ].
!
valueContainerOfSize:n
@@ -255,28 +330,44 @@
"redefined to block interrupts
(avoid change of the dictionary while accessing)"
- |val|
+ |ret wasBlocked|
- [
- val := super includes:anObject.
- ] valueUninterruptably.
- ^ val
+ (anObject isNil or:[anObject class == SmallInteger]) ifTrue:[
+ "Integers cannot be stored into a WeakValueDictionary"
+ ^ false.
+ ].
+
+ wasBlocked := OperatingSystem blockInterrupts.
+ ret := super includes:anObject.
+ wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
+ ^ ret
"Modified: 6.5.1996 / 12:22:26 / stefan"
"Modified: 1.7.1997 / 10:45:52 / cg"
"Created: 1.7.1997 / 15:41:14 / cg"
!
-includesKey:key
+includesIdentical:anObject
"redefined to block interrupts
(avoid change of the dictionary while accessing)"
- |val|
+ |ret wasBlocked|
+
+ (anObject isNil or:[anObject class == SmallInteger]) ifTrue:[
+ "Integers cannot be stored into a WeakValueDictionary"
+ ^ false.
+ ].
- [
- val := super includesKey:key.
- ] valueUninterruptably.
- ^ val
+ wasBlocked := OperatingSystem blockInterrupts.
+ ret := super includesIdentical:anObject.
+ wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
+ ^ ret
+!
+
+includesKey:key
+ "redefined to check for already collected values"
+
+ ^ (self at:key ifAbsent:DeletedEntry) ~~ DeletedEntry.
"Modified: 6.5.1996 / 12:22:26 / stefan"
"Modified: 1.7.1997 / 10:45:52 / cg"