WeakValueIdentityDictionary.st
changeset 4347 b7e45eadd0e0
child 4350 5aa2a3b9fd5b
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/WeakValueIdentityDictionary.st	Wed Jul 07 18:41:09 1999 +0200
@@ -0,0 +1,243 @@
+"
+ COPYRIGHT (c) 1999 by eXept Software AG
+              All Rights Reserved
+
+ This software is furnished under a license and may be used
+ only in accordance with the terms of that license and with the
+ inclusion of the above copyright notice.   This software may not
+ be provided or otherwise made available to, or used by, any
+ other person.  No title to or ownership of the software is
+ hereby transferred.
+"
+
+IdentityDictionary subclass:#WeakValueIdentityDictionary
+	instanceVariableNames:''
+	classVariableNames:''
+	poolDictionaries:''
+	category:'Collections-Unordered'
+!
+
+!WeakValueIdentityDictionary class methodsFor:'documentation'!
+
+copyright
+"
+ COPYRIGHT (c) 1999 by eXept Software AG
+              All Rights Reserved
+
+ This software is furnished under a license and may be used
+ only in accordance with the terms of that license and with the
+ inclusion of the above copyright notice.   This software may not
+ be provided or otherwise made available to, or used by, any
+ other person.  No title to or ownership of the software is
+ hereby transferred.
+"
+!
+
+documentation
+"
+    WeakValueIdentityDictionaries behave like IdentityDictionaries, 
+    as long as the values are still referenced by some 
+    other (non-weak) object.
+    However, once the last non-weak reference ceases to exist,
+    the Dictionary will return nil for the value at position key.
+    (with some delay: it will be removed after the next garbage collect).
+
+    [Warning:]
+      If you use this, be very careful since the collections size changes
+      'magically' - for example, testing for being nonEmpty and then
+      removing the first element may fail, since the element may vanish inbetween.
+      In general, never trust the value as returned by the size/isEmpty messages.
+
+
+    [author:]
+        Claus (stolen from Stefans WeakValueDictionary)
+
+    [See also:]
+        WeakArray WeakIdentityDictionary WeakIdentitySet WeakValueDictionary
+"
+! !
+
+!WeakValueIdentityDictionary methodsFor:'adding & removing'!
+
+at:key put:anObject
+    "add the argument anObject under key, aKey to the receiver.
+     Return anObject (sigh).
+     Redefined to block interrupts, to avoid trouble when dependencies
+     are added within interrupting high prio processes."
+
+    |ret|
+
+    (OperatingSystem blockInterrupts) ifTrue:[
+	"/ already blocked
+	^ super at:key put:anObject
+    ].
+
+    [
+	ret := super at:key put:anObject.
+    ] valueNowOrOnUnwindDo:[
+	OperatingSystem unblockInterrupts
+    ].
+    ^ ret
+
+    "Modified: 6.5.1996 / 12:22:26 / stefan"
+    "Created: 6.5.1996 / 14:47:37 / stefan"
+    "Modified: 20.10.1996 / 14:05:04 / cg"
+!
+
+removeKey:aKey ifAbsent:aBlock
+    "remove the association under aKey from the collection,
+     return the value 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|
+
+    (OperatingSystem blockInterrupts) ifTrue:[
+	"/ already blocked
+	^ super removeKey:aKey ifAbsent:aBlock
+    ].
+
+    [
+	ret := super removeKey:aKey ifAbsent:aBlock
+    ] valueNowOrOnUnwindDo:[
+	OperatingSystem unblockInterrupts
+    ].
+    ^ ret
+
+    "Modified: 6.5.1996 / 12:44:07 / stefan"
+    "Created: 6.5.1996 / 14:47:37 / stefan"
+!
+
+removeValue:aKey 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|
+
+    (OperatingSystem blockInterrupts) ifTrue:[
+	"/ already blocked
+	^ super removeValue:aKey ifAbsent:aBlock
+    ].
+
+    [
+	ret := super removeValue:aKey ifAbsent:aBlock
+    ] valueNowOrOnUnwindDo:[
+	OperatingSystem unblockInterrupts
+    ].
+    ^ ret.
+
+    "Created: 6.5.1996 / 14:47:37 / stefan"
+    "Modified: 8.5.1996 / 14:54:09 / stefan"
+! !
+
+!WeakValueIdentityDictionary methodsFor:'element disposal'!
+
+update:something with:aParameter from:changedObject
+    "an element (either key or value) died - clear out slots for
+     disposed keys."
+
+    |wasBlocked|
+
+    something == #ElementExpired ifTrue:[
+        "
+         have to block here - dispose may be done at a low priority
+         from the background finalizer. If new items are added by a 
+         higher prio process, the dictionary might get corrupted otherwise
+        "
+        wasBlocked := OperatingSystem blockInterrupts.
+
+        keyArray 
+            forAllDeadIndicesDo:[:idx | 
+                                    valueArray basicAt:idx put:nil.
+                                    tally := tally - 1.
+                                ]
+            replacingCorpsesWith:DeletedEntry.
+
+        wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
+    ]
+
+    "Created: 7.1.1997 / 16:59:30 / stefan"
+
+
+
+
+! !
+
+!WeakValueIdentityDictionary methodsFor:'private'!
+
+valueContainerOfSize:n
+    "return a container for values of size n.
+     use WeakArrays here."
+
+    |a|
+
+    a := WeakArray new:n.
+    a addDependent:self.
+    ^ a
+
+    "Created: 6.5.1996 / 14:47:37 / stefan"
+! !
+
+!WeakValueIdentityDictionary methodsFor:'testing'!
+
+includes:anObject
+    "redefined to block interrupts 
+     (avoid change of the dictionary while accessing)"
+
+    |val|
+
+    (OperatingSystem blockInterrupts) ifTrue:[
+	"/ already blocked
+	^ super includes:anObject.
+    ].
+
+    [
+	val := super includes:anObject.
+    ] valueNowOrOnUnwindDo:[
+	OperatingSystem unblockInterrupts.
+    ].
+    ^ val
+
+    "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
+    "redefined to block interrupts 
+     (avoid change of the dictionary while accessing)"
+
+    |val|
+
+    (OperatingSystem blockInterrupts) ifTrue:[
+	"/ already blocked
+	^ super includesKey:key.
+    ].
+
+    [
+	val := super includesKey:key.
+    ] valueNowOrOnUnwindDo:[
+	OperatingSystem unblockInterrupts.
+    ].
+    ^ val
+
+    "Modified: 6.5.1996 / 12:22:26 / stefan"
+    "Modified: 1.7.1997 / 10:45:52 / cg"
+    "Created: 1.7.1997 / 15:41:32 / cg"
+! !
+
+!WeakValueIdentityDictionary class methodsFor:'documentation'!
+
+version
+    ^ '$Header: /cvs/stx/stx/libbasic/WeakValueIdentityDictionary.st,v 1.1 1999-07-07 16:41:09 cg Exp $'
+! !