WeakIdentityDictionary.st
branchjv
changeset 18630 a74d669db937
parent 18335 165360a15be3
parent 18620 b4e9f25d6ce6
child 19226 470475a1734e
equal deleted inserted replaced
18617:fbfd2d411738 18630:a74d669db937
    38 "
    38 "
    39 !
    39 !
    40 
    40 
    41 documentation
    41 documentation
    42 "
    42 "
    43     WeakIdentityDictionaries behave like IdentityDictionaries, 
    43     WeakIdentityDictionaries behave like IdentityDictionaries,
    44     as long as the keys are still referenced by some 
    44     as long as the keys are still referenced by some
    45     other (non-weak) object.
    45     other (non-weak) object.
    46     However, once the last non-weak reference ceases to exist,
    46     However, once the last non-weak reference ceases to exist,
    47     the object will be automatically removed from the Weakcollection
    47     the object will be automatically removed from the Weakcollection
    48     (with some delay: it will be removed after the next garbage collect).
    48     (with some delay: it will be removed after the next garbage collect).
    49 
    49 
    70 ! !
    70 ! !
    71 
    71 
    72 !WeakIdentityDictionary methodsFor:'adding & removing'!
    72 !WeakIdentityDictionary methodsFor:'adding & removing'!
    73 
    73 
    74 at:key ifAbsent:exceptionBlock
    74 at:key ifAbsent:exceptionBlock
    75     "redefined to block interrupts 
    75     "redefined to block interrupts
    76      (avoid change of the dictionary while accessing)"
    76      (avoid change of the dictionary while accessing)"
    77 
    77 
    78     |val|
    78     |val|
    79 
    79 
    80     (OperatingSystem blockInterrupts) ifTrue:[
    80     (OperatingSystem blockInterrupts) ifTrue:[
    81         "/ already blocked
    81 	"/ already blocked
    82         ^ super at:key ifAbsent:exceptionBlock.
    82 	^ super at:key ifAbsent:exceptionBlock.
    83     ].
    83     ].
    84 
    84 
    85     [
    85     [
    86         val := super at:key ifAbsent:exceptionBlock.
    86 	val := super at:key ifAbsent:exceptionBlock.
    87     ] ensure:[
    87     ] ensure:[
    88         OperatingSystem unblockInterrupts.
    88 	OperatingSystem unblockInterrupts.
    89     ].
    89     ].
    90     ^ val
    90     ^ val
    91 
    91 
    92     "Modified: 6.5.1996 / 12:22:26 / stefan"
    92     "Modified: 6.5.1996 / 12:22:26 / stefan"
    93     "Modified: 1.7.1997 / 10:45:47 / cg"
    93     "Modified: 1.7.1997 / 10:45:47 / cg"
   100      are added within interrupting high prio processes."
   100      are added within interrupting high prio processes."
   101 
   101 
   102     |val|
   102     |val|
   103 
   103 
   104     (OperatingSystem blockInterrupts) ifTrue:[
   104     (OperatingSystem blockInterrupts) ifTrue:[
   105         "/ already blocked
   105 	"/ already blocked
   106         ^ super at:key put:anObject.
   106 	^ super at:key put:anObject.
   107     ].
   107     ].
   108 
   108 
   109     [
   109     [
   110         val := super at:key put:anObject.
   110 	val := super at:key put:anObject.
   111     ] ensure:[
   111     ] ensure:[
   112         OperatingSystem unblockInterrupts.
   112 	OperatingSystem unblockInterrupts.
   113     ].
   113     ].
   114     ^ val
   114     ^ val
   115 
   115 
   116     "Modified: 6.5.1996 / 12:22:26 / stefan"
   116     "Modified: 6.5.1996 / 12:22:26 / stefan"
   117     "Modified: 29.1.1997 / 15:08:45 / cg"
   117     "Modified: 29.1.1997 / 15:08:45 / cg"
   118 !
   118 !
   119 
   119 
   120 removeKey:aKey ifAbsent:aBlock
   120 removeKey:aKey ifAbsent:aBlock
   121     "remove the association under aKey from the collection,
   121     "remove the association under aKey from the collection,
   122      return the value previously stored there.
   122      return the value previously stored there.
   123      If it was not in the collection return the result 
   123      If it was not in the collection return the result
   124      from evaluating aBlock.
   124      from evaluating aBlock.
   125 
   125 
   126     Redefined to avoid synchronization problems, in case
   126     Redefined to avoid synchronization problems, in case
   127     of interrupts (otherwise, there could be some other operation 
   127     of interrupts (otherwise, there could be some other operation
   128     on the receiver done by another process, which garbles my contents)."
   128     on the receiver done by another process, which garbles my contents)."
   129 
   129 
   130     |ret|
   130     |ret|
   131 
   131 
   132     (OperatingSystem blockInterrupts) ifTrue:[
   132     (OperatingSystem blockInterrupts) ifTrue:[
   133         "/ already blocked
   133 	"/ already blocked
   134         ^ super removeKey:aKey ifAbsent:aBlock.
   134 	^ super removeKey:aKey ifAbsent:aBlock.
   135     ].
   135     ].
   136 
   136 
   137     [
   137     [
   138         ret := super removeKey:aKey ifAbsent:aBlock
   138 	ret := super removeKey:aKey ifAbsent:aBlock
   139     ] ensure:[
   139     ] ensure:[
   140         OperatingSystem unblockInterrupts
   140 	OperatingSystem unblockInterrupts
   141     ].
   141     ].
   142     ^ ret
   142     ^ ret
   143 
   143 
   144     "Modified: 6.5.1996 / 12:44:51 / stefan"
   144     "Modified: 6.5.1996 / 12:44:51 / stefan"
   145     "Modified: 29.1.1997 / 15:09:11 / cg"
   145     "Modified: 29.1.1997 / 15:09:11 / cg"
   146 !
   146 !
   147 
   147 
   148 safeRemoveKey:key
   148 safeRemoveKey:key
   149     "redefined to block interrupts 
   149     "redefined to block interrupts
   150      (avoid change of the dictionary while accessing)"
   150      (avoid change of the dictionary while accessing)"
   151 
   151 
   152     |val|
   152     |val|
   153 
   153 
   154     (OperatingSystem blockInterrupts) ifTrue:[
   154     (OperatingSystem blockInterrupts) ifTrue:[
   155         "/ already blocked
   155 	"/ already blocked
   156         ^ super safeRemoveKey:key.
   156 	^ super safeRemoveKey:key.
   157     ].
   157     ].
   158 
   158 
   159     [
   159     [
   160         val := super safeRemoveKey:key.
   160 	val := super safeRemoveKey:key.
   161     ] ensure:[
   161     ] ensure:[
   162         OperatingSystem unblockInterrupts.
   162 	OperatingSystem unblockInterrupts.
   163     ].
   163     ].
   164     ^ val
   164     ^ val
   165 
   165 
   166     "Modified: 6.5.1996 / 12:22:26 / stefan"
   166     "Modified: 6.5.1996 / 12:22:26 / stefan"
   167     "Modified: 1.7.1997 / 10:45:52 / cg"
   167     "Modified: 1.7.1997 / 10:45:52 / cg"
   173 clearDeadSlots
   173 clearDeadSlots
   174     |wasBlocked|
   174     |wasBlocked|
   175 
   175 
   176     "
   176     "
   177      have to block here - dispose may be done at a low priority
   177      have to block here - dispose may be done at a low priority
   178      from the background finalizer. If new items are added by a 
   178      from the background finalizer. If new items are added by a
   179      higher prio process, the dictionary might get corrupted otherwise
   179      higher prio process, the dictionary might get corrupted otherwise
   180     "
   180     "
   181     wasBlocked := OperatingSystem blockInterrupts.
   181     wasBlocked := OperatingSystem blockInterrupts.
   182     [
   182     [
   183         keyArray 
   183 	keyArray
   184             forAllDeadIndicesDo:[:idx | 
   184 	    forAllDeadIndicesDo:[:idx |
   185                                     valueArray basicAt:idx put:nil.
   185 				    valueArray basicAt:idx put:nil.
   186                                     tally := tally - 1.
   186 				    tally := tally - 1.
   187                                 ]
   187 				]
   188             replacingCorpsesWith:DeletedEntry.
   188 	    replacingCorpsesWith:DeletedEntry.
   189     ] ensure:[
   189     ] ensure:[
   190         wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
   190 	wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
   191     ].
   191     ].
   192 
   192 
   193     "Modified: / 13.12.2001 / 14:18:17 / martin"
   193     "Modified: / 13.12.2001 / 14:18:17 / martin"
   194 !
   194 !
   195 
   195 
   196 update:something with:aParameter from:changedObject
   196 update:something with:aParameter from:changedObject
   197     "an element (either key or value) died - clear out slots for
   197     "an element (either key or value) died - clear out slots for
   198      disposed keys."
   198      disposed keys."
   199 
   199 
   200     something == #ElementExpired ifTrue:[
   200     something == #ElementExpired ifTrue:[
   201         self clearDeadSlots.
   201 	self clearDeadSlots.
   202     ]
   202     ]
   203 
   203 
   204     "Created: / 7.1.1997 / 16:59:30 / stefan"
   204     "Created: / 7.1.1997 / 16:59:30 / stefan"
   205     "Modified: / 13.12.2001 / 14:17:58 / martin"
   205     "Modified: / 13.12.2001 / 14:17:58 / martin"
   206 ! !
   206 ! !
   207 
   207 
   208 !WeakIdentityDictionary methodsFor:'private'!
   208 !WeakIdentityDictionary methodsFor:'private'!
   209 
   209 
   210 findKeyOrNil:key
   210 findKeyOrNil:key
   211     "Look for the key in the receiver.  
   211     "Look for the key in the receiver.
   212      If it is found, return the index,
   212      If it is found, return the index,
   213      otherwise the index of the first unused slot. 
   213      otherwise the index of the first unused slot.
   214      Grow the receiver, if key was not found, and no unused slots were present.
   214      Grow the receiver, if key was not found, and no unused slots were present.
   215 
   215 
   216      Warning: an empty slot MUST be filled by the sender - it is only to be sent
   216      Warning: an empty slot MUST be filled by the sender - it is only to be sent
   217               by at:put: / add: - like methods."
   217 	      by at:put: / add: - like methods."
   218 
   218 
   219     |index  "{ Class:SmallInteger }"
   219     |index  "{ Class:SmallInteger }"
   220      length "{ Class:SmallInteger }"
   220      length "{ Class:SmallInteger }"
   221      startIndex probe 
   221      startIndex probe
   222      delIndex "{ Class:SmallInteger }"|
   222      delIndex "{ Class:SmallInteger }"|
   223 
   223 
   224     (OperatingSystem blockInterrupts) ifFalse:[
   224     (OperatingSystem blockInterrupts) ifFalse:[
   225         "/
   225 	"/
   226         "/ may never be entered with interrupts enabled
   226 	"/ may never be entered with interrupts enabled
   227         "/
   227 	"/
   228         OperatingSystem unblockInterrupts.
   228 	OperatingSystem unblockInterrupts.
   229         self error:'unblocked call of findKeyOrNil'.
   229 	self error:'unblocked call of findKeyOrNil'.
   230     ].
   230     ].
   231 
   231 
   232     delIndex := 0.
   232     delIndex := 0.
   233 
   233 
   234     length := keyArray basicSize.
   234     length := keyArray basicSize.
   235     startIndex := index := self initialIndexForKey:key.
   235     startIndex := index := self initialIndexForKey:key.
   236 
   236 
   237     [
   237     [
   238         probe := keyArray basicAt:index.
   238 	probe := keyArray basicAt:index.
   239         key == probe ifTrue:[^ index].
   239 	key == probe ifTrue:[^ index].
   240         probe isNil ifTrue:[
   240 	probe isNil ifTrue:[
   241             delIndex == 0 ifTrue:[^ index].
   241 	    delIndex == 0 ifTrue:[^ index].
   242             keyArray basicAt:delIndex put:nil.
   242 	    keyArray basicAt:delIndex put:nil.
   243             ^ delIndex
   243 	    ^ delIndex
   244         ].
   244 	].
   245 
   245 
   246         probe == 0 ifTrue:[
   246 	probe class == SmallInteger ifTrue:[
   247             probe := DeletedEntry.
   247 	    probe := DeletedEntry.
   248             keyArray basicAt:index put:probe.
   248 	    keyArray basicAt:index put:probe.
   249             valueArray basicAt:index put:nil.
   249 	    valueArray basicAt:index put:nil.
   250             tally := tally - 1.
   250 	    tally := tally - 1.
   251         ].
   251 	].
   252 
   252 
   253         delIndex == 0 ifTrue:[
   253 	delIndex == 0 ifTrue:[
   254             probe == DeletedEntry ifTrue:[
   254 	    probe == DeletedEntry ifTrue:[
   255                 delIndex := index
   255 		delIndex := index
   256             ]
   256 	    ]
   257         ].
   257 	].
   258 
   258 
   259         index == length ifTrue:[
   259 	index == length ifTrue:[
   260             index := 1
   260 	    index := 1
   261         ] ifFalse:[
   261 	] ifFalse:[
   262             index := index + 1
   262 	    index := index + 1
   263         ].
   263 	].
   264         index == startIndex ifTrue:[
   264 	index == startIndex ifTrue:[
   265             delIndex ~~ 0 ifTrue:[
   265 	    delIndex ~~ 0 ifTrue:[
   266                 keyArray basicAt:delIndex put:nil.
   266 		keyArray basicAt:delIndex put:nil.
   267                 ^ delIndex
   267 		^ delIndex
   268             ].
   268 	    ].
   269             ^ self grow findKeyOrNil:key
   269 	    ^ self grow findKeyOrNil:key
   270         ].
   270 	].
   271     ] loop.
   271     ] loop.
   272 
   272 
   273     "Modified: 30.1.1997 / 15:04:34 / cg"
   273     "Modified: 30.1.1997 / 15:04:34 / cg"
   274     "Modified: 1.10.1997 / 11:25:32 / stefan"
   274     "Modified: 1.10.1997 / 11:25:32 / stefan"
   275 !
   275 !
   280      are added within interrupting high prio processes."
   280      are added within interrupting high prio processes."
   281 
   281 
   282 "/ 'grow:' printCR.
   282 "/ 'grow:' printCR.
   283 
   283 
   284     (OperatingSystem blockInterrupts) ifTrue:[
   284     (OperatingSystem blockInterrupts) ifTrue:[
   285         "/ already blocked
   285 	"/ already blocked
   286         ^ super grow:newSize.
   286 	^ super grow:newSize.
   287     ].
   287     ].
   288 
   288 
   289     [
   289     [
   290         super grow:newSize
   290 	super grow:newSize
   291     ] ensure:[
   291     ] ensure:[
   292         OperatingSystem unblockInterrupts
   292 	OperatingSystem unblockInterrupts
   293     ].
   293     ].
   294 
   294 
   295     "Created: 28.1.1997 / 23:41:39 / cg"
   295     "Created: 28.1.1997 / 23:41:39 / cg"
   296     "Modified: 29.1.1997 / 15:10:12 / cg"
   296     "Modified: 29.1.1997 / 15:10:12 / cg"
   297 !
   297 !
   302      are added within interrupting high prio processes."
   302      are added within interrupting high prio processes."
   303 
   303 
   304 "/ 'setTally:' printCR.
   304 "/ 'setTally:' printCR.
   305 
   305 
   306     (OperatingSystem blockInterrupts) ifTrue:[
   306     (OperatingSystem blockInterrupts) ifTrue:[
   307         "/ already blocked
   307 	"/ already blocked
   308         super initializeForCapacity:minSize.
   308 	super initializeForCapacity:minSize.
   309         ^ self.
   309 	^ self.
   310     ].
   310     ].
   311 
   311 
   312     [
   312     [
   313         super initializeForCapacity:minSize
   313 	super initializeForCapacity:minSize
   314     ] ensure:[
   314     ] ensure:[
   315         OperatingSystem unblockInterrupts
   315 	OperatingSystem unblockInterrupts
   316     ].
   316     ].
   317 
   317 
   318     "Created: 29.1.1997 / 11:40:12 / cg"
   318     "Created: 29.1.1997 / 11:40:12 / cg"
   319     "Modified: 29.1.1997 / 15:11:11 / cg"
   319     "Modified: 29.1.1997 / 15:11:11 / cg"
   320 !
   320 !
   339      are added within interrupting high prio processes."
   339      are added within interrupting high prio processes."
   340 
   340 
   341 "/ 'rehash' printCR.
   341 "/ 'rehash' printCR.
   342 
   342 
   343     (OperatingSystem blockInterrupts) ifTrue:[
   343     (OperatingSystem blockInterrupts) ifTrue:[
   344         "/ already blocked
   344 	"/ already blocked
   345         super rehash.
   345 	super rehash.
   346         ^ self.
   346 	^ self.
   347     ].
   347     ].
   348 
   348 
   349     [
   349     [
   350         super rehash
   350 	super rehash
   351     ] ensure:[
   351     ] ensure:[
   352         OperatingSystem unblockInterrupts
   352 	OperatingSystem unblockInterrupts
   353     ].
   353     ].
   354 
   354 
   355     "Created: 29.1.1997 / 11:39:42 / cg"
   355     "Created: 29.1.1997 / 11:39:42 / cg"
   356     "Modified: 29.1.1997 / 14:18:52 / cg"
   356     "Modified: 29.1.1997 / 14:18:52 / cg"
   357 ! !
   357 ! !
   358 
   358 
   359 !WeakIdentityDictionary methodsFor:'testing'!
   359 !WeakIdentityDictionary methodsFor:'testing'!
   360 
   360 
   361 includes:anObject
   361 includes:anObject
   362     "redefined to block interrupts 
   362     "redefined to block interrupts
   363      (avoid change of the dictionary while accessing)"
   363      (avoid change of the dictionary while accessing)"
   364 
   364 
   365     |val|
   365     |val|
   366 
   366 
   367     (OperatingSystem blockInterrupts) ifTrue:[
   367     (OperatingSystem blockInterrupts) ifTrue:[
   368         "/ already blocked
   368 	"/ already blocked
   369         ^ super includes:anObject.
   369 	^ super includes:anObject.
   370     ].
   370     ].
   371 
   371 
   372     [
   372     [
   373         val := super includes:anObject.
   373 	val := super includes:anObject.
   374     ] ensure:[
   374     ] ensure:[
   375         OperatingSystem unblockInterrupts.
   375 	OperatingSystem unblockInterrupts.
   376     ].
   376     ].
   377     ^ val
   377     ^ val
   378 
   378 
   379     "Modified: 6.5.1996 / 12:22:26 / stefan"
   379     "Modified: 6.5.1996 / 12:22:26 / stefan"
   380     "Modified: 1.7.1997 / 10:45:52 / cg"
   380     "Modified: 1.7.1997 / 10:45:52 / cg"
   381     "Created: 1.7.1997 / 10:47:13 / cg"
   381     "Created: 1.7.1997 / 10:47:13 / cg"
   382 !
   382 !
   383 
   383 
   384 includesKey:key
   384 includesKey:key
   385     "redefined to block interrupts 
   385     "redefined to block interrupts
   386      (avoid change of the dictionary while accessing)"
   386      (avoid change of the dictionary while accessing)"
   387 
   387 
   388     |val|
   388     |val|
   389 
   389 
   390     (OperatingSystem blockInterrupts) ifTrue:[
   390     (OperatingSystem blockInterrupts) ifTrue:[
   391         "/ already blocked
   391 	"/ already blocked
   392         ^ super includesKey:key.
   392 	^ super includesKey:key.
   393     ].
   393     ].
   394 
   394 
   395     [
   395     [
   396         val := super includesKey:key.
   396 	val := super includesKey:key.
   397     ] ensure:[
   397     ] ensure:[
   398         OperatingSystem unblockInterrupts.
   398 	OperatingSystem unblockInterrupts.
   399     ].
   399     ].
   400     ^ val
   400     ^ val
   401 
   401 
   402     "Modified: 6.5.1996 / 12:22:26 / stefan"
   402     "Modified: 6.5.1996 / 12:22:26 / stefan"
   403     "Created: 1.7.1997 / 10:45:14 / cg"
   403     "Created: 1.7.1997 / 10:45:14 / cg"
   411 ! !
   411 ! !
   412 
   412 
   413 !WeakIdentityDictionary class methodsFor:'documentation'!
   413 !WeakIdentityDictionary class methodsFor:'documentation'!
   414 
   414 
   415 version
   415 version
   416     ^ '$Header: /cvs/stx/stx/libbasic/WeakIdentityDictionary.st,v 1.46 2015-05-09 11:58:44 cg Exp $'
   416     ^ '$Header$'
   417 ! !
   417 ! !
   418 
   418