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 ! |
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" |