WeakIdentityDictionary.st
changeset 2910 1a3e44b10f9b
parent 2741 7af858fd7296
child 2988 c6550b3e9b3c
equal deleted inserted replaced
2909:b4df6be2ed52 2910:1a3e44b10f9b
    55       removing the first element may fail, since the element may vanish inbetween.
    55       removing the first element may fail, since the element may vanish inbetween.
    56       In general, never trust the value as returned by the size/isEmpty messages.
    56       In general, never trust the value as returned by the size/isEmpty messages.
    57 
    57 
    58 
    58 
    59     [author:]
    59     [author:]
    60         Claus Gittinger
    60 	Claus Gittinger
    61 
    61 
    62     [See also:]
    62     [See also:]
    63         WeakArray WeakValueDictionary WeakIdentitySet
    63 	WeakArray WeakValueDictionary WeakIdentitySet
    64 "
    64 "
    65 ! !
    65 ! !
    66 
    66 
    67 !WeakIdentityDictionary methodsFor:'adding & removing'!
    67 !WeakIdentityDictionary methodsFor:'adding & removing'!
    68 
    68 
    71      (avoid change of the dictionary while accessing)"
    71      (avoid change of the dictionary while accessing)"
    72 
    72 
    73     |val|
    73     |val|
    74 
    74 
    75     (OperatingSystem blockInterrupts) ifTrue:[
    75     (OperatingSystem blockInterrupts) ifTrue:[
    76         "/ already blocked
    76 	"/ already blocked
    77         ^ super at:key.
    77 	^ super at:key.
    78     ].
    78     ].
    79 
    79 
    80     [
    80     [
    81         val := super at:key.
    81 	val := super at:key.
    82     ] valueNowOrOnUnwindDo:[
    82     ] valueNowOrOnUnwindDo:[
    83         OperatingSystem unblockInterrupts.
    83 	OperatingSystem unblockInterrupts.
    84     ].
    84     ].
    85     ^ val
    85     ^ val
    86 
    86 
    87     "Modified: 6.5.1996 / 12:22:26 / stefan"
    87     "Modified: 6.5.1996 / 12:22:26 / stefan"
    88     "Modified: 1.7.1997 / 10:45:42 / cg"
    88     "Modified: 1.7.1997 / 10:45:42 / cg"
    93      (avoid change of the dictionary while accessing)"
    93      (avoid change of the dictionary while accessing)"
    94 
    94 
    95     |val|
    95     |val|
    96 
    96 
    97     (OperatingSystem blockInterrupts) ifTrue:[
    97     (OperatingSystem blockInterrupts) ifTrue:[
    98         "/ already blocked
    98 	"/ already blocked
    99         ^ super at:key ifAbsent:exceptionBlock.
    99 	^ super at:key ifAbsent:exceptionBlock.
   100     ].
   100     ].
   101 
   101 
   102     [
   102     [
   103         val := super at:key ifAbsent:exceptionBlock.
   103 	val := super at:key ifAbsent:exceptionBlock.
   104     ] valueNowOrOnUnwindDo:[
   104     ] valueNowOrOnUnwindDo:[
   105         OperatingSystem unblockInterrupts.
   105 	OperatingSystem unblockInterrupts.
   106     ].
   106     ].
   107     ^ val
   107     ^ val
   108 
   108 
   109     "Modified: 6.5.1996 / 12:22:26 / stefan"
   109     "Modified: 6.5.1996 / 12:22:26 / stefan"
   110     "Modified: 1.7.1997 / 10:45:47 / cg"
   110     "Modified: 1.7.1997 / 10:45:47 / cg"
   117      are added within interrupting high prio processes."
   117      are added within interrupting high prio processes."
   118 
   118 
   119     |val|
   119     |val|
   120 
   120 
   121     (OperatingSystem blockInterrupts) ifTrue:[
   121     (OperatingSystem blockInterrupts) ifTrue:[
   122         "/ already blocked
   122 	"/ already blocked
   123         ^ super at:key put:anObject.
   123 	^ super at:key put:anObject.
   124     ].
   124     ].
   125 
   125 
   126     [
   126     [
   127         val := super at:key put:anObject.
   127 	val := super at:key put:anObject.
   128     ] valueNowOrOnUnwindDo:[
   128     ] valueNowOrOnUnwindDo:[
   129         OperatingSystem unblockInterrupts.
   129 	OperatingSystem unblockInterrupts.
   130     ].
   130     ].
   131     ^ val
   131     ^ val
   132 
   132 
   133     "Modified: 6.5.1996 / 12:22:26 / stefan"
   133     "Modified: 6.5.1996 / 12:22:26 / stefan"
   134     "Modified: 29.1.1997 / 15:08:45 / cg"
   134     "Modified: 29.1.1997 / 15:08:45 / cg"
   135 !
   135 !
   136 
   136 
   137 removeKey:aKey ifAbsent:aBlock
   137 removeKey:aKey ifAbsent:aBlock
   138     "remove the association under aKey from the collection,
   138     "remove the association under aKey from the collection,
   139      return the value previously stored there..
   139      return the value previously stored there.
   140      If it was not in the collection return the result 
   140      If it was not in the collection return the result 
   141      from evaluating aBlock.
   141      from evaluating aBlock.
   142 
   142 
   143     Redefined to avoid synchronization problems, in case
   143     Redefined to avoid synchronization problems, in case
   144     of interrupts (otherwise, there could be some other operation 
   144     of interrupts (otherwise, there could be some other operation 
   145     on the receiver done by another process, which garbles my contents)."
   145     on the receiver done by another process, which garbles my contents)."
   146 
   146 
   147     |ret|
   147     |ret|
   148 
   148 
   149     (OperatingSystem blockInterrupts) ifTrue:[
   149     (OperatingSystem blockInterrupts) ifTrue:[
   150         "/ already blocked
   150 	"/ already blocked
   151         ^ super removeKey:aKey ifAbsent:aBlock.
   151 	^ super removeKey:aKey ifAbsent:aBlock.
   152     ].
   152     ].
   153 
   153 
   154     [
   154     [
   155         ret := super removeKey:aKey ifAbsent:aBlock
   155 	ret := super removeKey:aKey ifAbsent:aBlock
   156     ] valueNowOrOnUnwindDo:[
   156     ] valueNowOrOnUnwindDo:[
   157         OperatingSystem unblockInterrupts
   157 	OperatingSystem unblockInterrupts
   158     ].
   158     ].
   159     ^ ret
   159     ^ ret
   160 
   160 
   161     "Modified: 6.5.1996 / 12:44:51 / stefan"
   161     "Modified: 6.5.1996 / 12:44:51 / stefan"
   162     "Modified: 29.1.1997 / 15:09:11 / cg"
   162     "Modified: 29.1.1997 / 15:09:11 / cg"
   167      (avoid change of the dictionary while accessing)"
   167      (avoid change of the dictionary while accessing)"
   168 
   168 
   169     |val|
   169     |val|
   170 
   170 
   171     (OperatingSystem blockInterrupts) ifTrue:[
   171     (OperatingSystem blockInterrupts) ifTrue:[
   172         "/ already blocked
   172 	"/ already blocked
   173         ^ super saveRemoveKey:key.
   173 	^ super saveRemoveKey:key.
   174     ].
   174     ].
   175 
   175 
   176     [
   176     [
   177         val := super saveRemoveKey:key.
   177 	val := super saveRemoveKey:key.
   178     ] valueNowOrOnUnwindDo:[
   178     ] valueNowOrOnUnwindDo:[
   179         OperatingSystem unblockInterrupts.
   179 	OperatingSystem unblockInterrupts.
   180     ].
   180     ].
   181     ^ val
   181     ^ val
   182 
   182 
   183     "Modified: 6.5.1996 / 12:22:26 / stefan"
   183     "Modified: 6.5.1996 / 12:22:26 / stefan"
   184     "Modified: 1.7.1997 / 10:45:52 / cg"
   184     "Modified: 1.7.1997 / 10:45:52 / cg"
   192      disposed keys."
   192      disposed keys."
   193 
   193 
   194     |wasBlocked|
   194     |wasBlocked|
   195 
   195 
   196     something == #ElementExpired ifTrue:[
   196     something == #ElementExpired ifTrue:[
   197         "
   197 	"
   198          have to block here - dispose may be done at a low priority
   198 	 have to block here - dispose may be done at a low priority
   199          from the background finalizer. If new items are added by a 
   199 	 from the background finalizer. If new items are added by a 
   200          higher prio process, the dictionary might get corrupted otherwise
   200 	 higher prio process, the dictionary might get corrupted otherwise
   201         "
   201 	"
   202         wasBlocked := OperatingSystem blockInterrupts.
   202 	wasBlocked := OperatingSystem blockInterrupts.
   203 
   203 
   204         keyArray 
   204 	keyArray 
   205             forAllDeadIndicesDo:[:idx | 
   205 	    forAllDeadIndicesDo:[:idx | 
   206                                     valueArray basicAt:idx put:nil.
   206 				    valueArray basicAt:idx put:nil.
   207                                     tally := tally - 1.
   207 				    tally := tally - 1.
   208                                 ]
   208 				]
   209             replacingCorpsesWith:DeletedEntry.
   209 	    replacingCorpsesWith:DeletedEntry.
   210 
   210 
   211         wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
   211 	wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
   212     ]
   212     ]
   213 
   213 
   214     "Created: 7.1.1997 / 16:59:30 / stefan"
   214     "Created: 7.1.1997 / 16:59:30 / stefan"
   215 ! !
   215 ! !
   216 
   216 
   221      If it is found, return return the index,
   221      If it is found, return return the index,
   222      otherwise the index of the first unused slot. 
   222      otherwise the index of the first unused slot. 
   223      Grow the receiver, if key was not found, and no unused slots were present.
   223      Grow the receiver, if key was not found, and no unused slots were present.
   224 
   224 
   225      Warning: an empty slot MUST be filled by the sender - it is only to be sent
   225      Warning: an empty slot MUST be filled by the sender - it is only to be sent
   226               by at:put: / add: - like methods."
   226 	      by at:put: / add: - like methods."
   227 
   227 
   228     |index  "{ Class:SmallInteger }"
   228     |index  "{ Class:SmallInteger }"
   229      length "{ Class:SmallInteger }"
   229      length "{ Class:SmallInteger }"
   230      startIndex probe 
   230      startIndex probe 
   231      delIndex "{ Class:SmallInteger }"|
   231      delIndex "{ Class:SmallInteger }"|
   232 
   232 
   233     (OperatingSystem blockInterrupts) ifFalse:[
   233     (OperatingSystem blockInterrupts) ifFalse:[
   234         "/
   234 	"/
   235         "/ may never be entered with interrupts enabled
   235 	"/ may never be entered with interrupts enabled
   236         "/
   236 	"/
   237         OperatingSystem unblockInterrupts.
   237 	OperatingSystem unblockInterrupts.
   238         self error:'oops - unblocked call of findKeyOrNil'.
   238 	self error:'oops - unblocked call of findKeyOrNil'.
   239         ^ nil "/ leads to another error, if proceeded
   239 	^ nil "/ leads to another error, if proceeded
   240     ].
   240     ].
   241 
   241 
   242     delIndex := 0.
   242     delIndex := 0.
   243 
   243 
   244     length := keyArray basicSize.
   244     length := keyArray basicSize.
   245     index := key identityHash.
   245     index := key identityHash.
   246     index < 16r1FFFFFFF ifTrue:[
   246     index < 16r1FFFFFFF ifTrue:[
   247         index := index * 2
   247 	index := index * 2
   248     ].
   248     ].
   249     index := index \\ length + 1.
   249     index := index \\ length + 1.
   250     startIndex := index.
   250     startIndex := index.
   251 
   251 
   252     [true] whileTrue:[
   252     [true] whileTrue:[
   253         probe := keyArray basicAt:index.
   253 	probe := keyArray basicAt:index.
   254         key == probe ifTrue:[^ index].
   254 	key == probe ifTrue:[^ index].
   255         probe isNil ifTrue:[
   255 	probe isNil ifTrue:[
   256             delIndex == 0 ifTrue:[^ index].
   256 	    delIndex == 0 ifTrue:[^ index].
   257             keyArray basicAt:delIndex put:nil.
   257 	    keyArray basicAt:delIndex put:nil.
   258             ^ delIndex
   258 	    ^ delIndex
   259         ].
   259 	].
   260 
   260 
   261         probe == 0 ifTrue:[
   261 	probe == 0 ifTrue:[
   262             probe := DeletedEntry.
   262 	    probe := DeletedEntry.
   263             keyArray basicAt:index put:probe.
   263 	    keyArray basicAt:index put:probe.
   264             valueArray basicAt:index put:nil.
   264 	    valueArray basicAt:index put:nil.
   265             tally := tally - 1.
   265 	    tally := tally - 1.
   266         ].
   266 	].
   267 
   267 
   268         delIndex == 0 ifTrue:[
   268 	delIndex == 0 ifTrue:[
   269             probe == DeletedEntry ifTrue:[
   269 	    probe == DeletedEntry ifTrue:[
   270                 delIndex := index
   270 		delIndex := index
   271             ]
   271 	    ]
   272         ].
   272 	].
   273 
   273 
   274         index == length ifTrue:[
   274 	index == length ifTrue:[
   275             index := 1
   275 	    index := 1
   276         ] ifFalse:[
   276 	] ifFalse:[
   277             index := index + 1
   277 	    index := index + 1
   278         ].
   278 	].
   279         index == startIndex ifTrue:[
   279 	index == startIndex ifTrue:[
   280             delIndex ~~ 0 ifTrue:[
   280 	    delIndex ~~ 0 ifTrue:[
   281                 keyArray basicAt:delIndex put:nil.
   281 		keyArray basicAt:delIndex put:nil.
   282                 ^ delIndex
   282 		^ delIndex
   283             ].
   283 	    ].
   284             ^ self grow findKeyOrNil:key
   284 	    ^ self grow findKeyOrNil:key
   285         ].
   285 	].
   286     ]
   286     ]
   287 
   287 
   288     "Modified: 30.1.1997 / 15:04:34 / cg"
   288     "Modified: 30.1.1997 / 15:04:34 / cg"
   289 !
   289 !
   290 
   290 
   294      are added within interrupting high prio processes."
   294      are added within interrupting high prio processes."
   295 
   295 
   296 "/ 'grow:' printCR.
   296 "/ 'grow:' printCR.
   297 
   297 
   298     (OperatingSystem blockInterrupts) ifTrue:[
   298     (OperatingSystem blockInterrupts) ifTrue:[
   299         "/ already blocked
   299 	"/ already blocked
   300         ^ super grow:newSize.
   300 	^ super grow:newSize.
   301     ].
   301     ].
   302 
   302 
   303     [
   303     [
   304         super grow:newSize
   304 	super grow:newSize
   305     ] valueNowOrOnUnwindDo:[
   305     ] valueNowOrOnUnwindDo:[
   306         OperatingSystem unblockInterrupts
   306 	OperatingSystem unblockInterrupts
   307     ].
   307     ].
   308 
   308 
   309     "Created: 28.1.1997 / 23:41:39 / cg"
   309     "Created: 28.1.1997 / 23:41:39 / cg"
   310     "Modified: 29.1.1997 / 15:10:12 / cg"
   310     "Modified: 29.1.1997 / 15:10:12 / cg"
   311 !
   311 !
   330      are added within interrupting high prio processes."
   330      are added within interrupting high prio processes."
   331 
   331 
   332 "/ 'rehash' printCR.
   332 "/ 'rehash' printCR.
   333 
   333 
   334     (OperatingSystem blockInterrupts) ifTrue:[
   334     (OperatingSystem blockInterrupts) ifTrue:[
   335         "/ already blocked
   335 	"/ already blocked
   336         ^ super rehash.
   336 	^ super rehash.
   337     ].
   337     ].
   338 
   338 
   339     [
   339     [
   340         super rehash
   340 	super rehash
   341     ] valueNowOrOnUnwindDo:[
   341     ] valueNowOrOnUnwindDo:[
   342         OperatingSystem unblockInterrupts
   342 	OperatingSystem unblockInterrupts
   343     ].
   343     ].
   344 
   344 
   345     "Created: 29.1.1997 / 11:39:42 / cg"
   345     "Created: 29.1.1997 / 11:39:42 / cg"
   346     "Modified: 29.1.1997 / 14:18:52 / cg"
   346     "Modified: 29.1.1997 / 14:18:52 / cg"
   347 !
   347 !
   352      are added within interrupting high prio processes."
   352      are added within interrupting high prio processes."
   353 
   353 
   354 "/ 'setTally:' printCR.
   354 "/ 'setTally:' printCR.
   355 
   355 
   356     (OperatingSystem blockInterrupts) ifTrue:[
   356     (OperatingSystem blockInterrupts) ifTrue:[
   357         "/ already blocked
   357 	"/ already blocked
   358         ^ super setTally:count.
   358 	^ super setTally:count.
   359     ].
   359     ].
   360 
   360 
   361     [
   361     [
   362         super setTally:count
   362 	super setTally:count
   363     ] valueNowOrOnUnwindDo:[
   363     ] valueNowOrOnUnwindDo:[
   364         OperatingSystem unblockInterrupts
   364 	OperatingSystem unblockInterrupts
   365     ].
   365     ].
   366 
   366 
   367     "Created: 29.1.1997 / 11:40:12 / cg"
   367     "Created: 29.1.1997 / 11:40:12 / cg"
   368     "Modified: 29.1.1997 / 15:11:11 / cg"
   368     "Modified: 29.1.1997 / 15:11:11 / cg"
   369 ! !
   369 ! !
   375      (avoid change of the dictionary while accessing)"
   375      (avoid change of the dictionary while accessing)"
   376 
   376 
   377     |val|
   377     |val|
   378 
   378 
   379     (OperatingSystem blockInterrupts) ifTrue:[
   379     (OperatingSystem blockInterrupts) ifTrue:[
   380         "/ already blocked
   380 	"/ already blocked
   381         ^ super includes:anObject.
   381 	^ super includes:anObject.
   382     ].
   382     ].
   383 
   383 
   384     [
   384     [
   385         val := super includes:anObject.
   385 	val := super includes:anObject.
   386     ] valueNowOrOnUnwindDo:[
   386     ] valueNowOrOnUnwindDo:[
   387         OperatingSystem unblockInterrupts.
   387 	OperatingSystem unblockInterrupts.
   388     ].
   388     ].
   389     ^ val
   389     ^ val
   390 
   390 
   391     "Modified: 6.5.1996 / 12:22:26 / stefan"
   391     "Modified: 6.5.1996 / 12:22:26 / stefan"
   392     "Modified: 1.7.1997 / 10:45:52 / cg"
   392     "Modified: 1.7.1997 / 10:45:52 / cg"
   398      (avoid change of the dictionary while accessing)"
   398      (avoid change of the dictionary while accessing)"
   399 
   399 
   400     |val|
   400     |val|
   401 
   401 
   402     (OperatingSystem blockInterrupts) ifTrue:[
   402     (OperatingSystem blockInterrupts) ifTrue:[
   403         "/ already blocked
   403 	"/ already blocked
   404         ^ super includesKey:key.
   404 	^ super includesKey:key.
   405     ].
   405     ].
   406 
   406 
   407     [
   407     [
   408         val := super includesKey:key.
   408 	val := super includesKey:key.
   409     ] valueNowOrOnUnwindDo:[
   409     ] valueNowOrOnUnwindDo:[
   410         OperatingSystem unblockInterrupts.
   410 	OperatingSystem unblockInterrupts.
   411     ].
   411     ].
   412     ^ val
   412     ^ val
   413 
   413 
   414     "Modified: 6.5.1996 / 12:22:26 / stefan"
   414     "Modified: 6.5.1996 / 12:22:26 / stefan"
   415     "Created: 1.7.1997 / 10:45:14 / cg"
   415     "Created: 1.7.1997 / 10:45:14 / cg"
   417 ! !
   417 ! !
   418 
   418 
   419 !WeakIdentityDictionary class methodsFor:'documentation'!
   419 !WeakIdentityDictionary class methodsFor:'documentation'!
   420 
   420 
   421 version
   421 version
   422     ^ '$Header: /cvs/stx/stx/libbasic/WeakIdentityDictionary.st,v 1.31 1997-07-01 17:21:21 cg Exp $'
   422     ^ '$Header: /cvs/stx/stx/libbasic/WeakIdentityDictionary.st,v 1.32 1997-09-09 17:31:56 cg Exp $'
   423 ! !
   423 ! !