diff options
Diffstat (limited to 'OpenSim/Framework/DoubleDictionaryThreadAbortSafe.cs')
-rw-r--r-- | OpenSim/Framework/DoubleDictionaryThreadAbortSafe.cs | 193 |
1 files changed, 101 insertions, 92 deletions
diff --git a/OpenSim/Framework/DoubleDictionaryThreadAbortSafe.cs b/OpenSim/Framework/DoubleDictionaryThreadAbortSafe.cs index 9056548..816523b 100644 --- a/OpenSim/Framework/DoubleDictionaryThreadAbortSafe.cs +++ b/OpenSim/Framework/DoubleDictionaryThreadAbortSafe.cs | |||
@@ -55,6 +55,11 @@ namespace OpenSim.Framework | |||
55 | Dictionary2 = new Dictionary<TKey2, TValue>(capacity); | 55 | Dictionary2 = new Dictionary<TKey2, TValue>(capacity); |
56 | } | 56 | } |
57 | 57 | ||
58 | ~DoubleDictionaryThreadAbortSafe() | ||
59 | { | ||
60 | rwLock.Dispose(); | ||
61 | } | ||
62 | |||
58 | public void Add(TKey1 key1, TKey2 key2, TValue value) | 63 | public void Add(TKey1 key1, TKey2 key2, TValue value) |
59 | { | 64 | { |
60 | bool gotLock = false; | 65 | bool gotLock = false; |
@@ -64,31 +69,29 @@ namespace OpenSim.Framework | |||
64 | // Avoid an asynchronous Thread.Abort() from possibly never existing an acquired lock by placing | 69 | // Avoid an asynchronous Thread.Abort() from possibly never existing an acquired lock by placing |
65 | // the acquision inside the main try. The inner finally block is needed because thread aborts cannot | 70 | // the acquision inside the main try. The inner finally block is needed because thread aborts cannot |
66 | // interrupt code in these blocks (hence gotLock is guaranteed to be set correctly). | 71 | // interrupt code in these blocks (hence gotLock is guaranteed to be set correctly). |
67 | try {} | 72 | try {} |
68 | finally | 73 | finally |
69 | { | 74 | { |
70 | rwLock.EnterWriteLock(); | 75 | rwLock.EnterWriteLock(); |
71 | gotLock = true; | 76 | gotLock = true; |
77 | if (Dictionary1.ContainsKey(key1)) | ||
78 | { | ||
79 | if (!Dictionary2.ContainsKey(key2)) | ||
80 | throw new ArgumentException("key1 exists in the dictionary but not key2"); | ||
81 | } | ||
82 | else if (Dictionary2.ContainsKey(key2)) | ||
83 | { | ||
84 | if (!Dictionary1.ContainsKey(key1)) | ||
85 | throw new ArgumentException("key2 exists in the dictionary but not key1"); | ||
86 | } | ||
87 | Dictionary1[key1] = value; | ||
88 | Dictionary2[key2] = value; | ||
72 | } | 89 | } |
73 | |||
74 | if (Dictionary1.ContainsKey(key1)) | ||
75 | { | ||
76 | if (!Dictionary2.ContainsKey(key2)) | ||
77 | throw new ArgumentException("key1 exists in the dictionary but not key2"); | ||
78 | } | ||
79 | else if (Dictionary2.ContainsKey(key2)) | ||
80 | { | ||
81 | if (!Dictionary1.ContainsKey(key1)) | ||
82 | throw new ArgumentException("key2 exists in the dictionary but not key1"); | ||
83 | } | ||
84 | |||
85 | Dictionary1[key1] = value; | ||
86 | Dictionary2[key2] = value; | ||
87 | } | 90 | } |
88 | finally | 91 | finally |
89 | { | 92 | { |
90 | if (gotLock) | 93 | if (gotLock) |
91 | rwLock.ExitWriteLock(); | 94 | rwLock.ExitWriteLock(); |
92 | } | 95 | } |
93 | } | 96 | } |
94 | 97 | ||
@@ -102,20 +105,19 @@ namespace OpenSim.Framework | |||
102 | // Avoid an asynchronous Thread.Abort() from possibly never existing an acquired lock by placing | 105 | // Avoid an asynchronous Thread.Abort() from possibly never existing an acquired lock by placing |
103 | // the acquision inside the main try. The inner finally block is needed because thread aborts cannot | 106 | // the acquision inside the main try. The inner finally block is needed because thread aborts cannot |
104 | // interrupt code in these blocks (hence gotLock is guaranteed to be set correctly). | 107 | // interrupt code in these blocks (hence gotLock is guaranteed to be set correctly). |
105 | try {} | 108 | try {} |
106 | finally | 109 | finally |
107 | { | 110 | { |
108 | rwLock.EnterWriteLock(); | 111 | rwLock.EnterWriteLock(); |
109 | gotLock = true; | 112 | gotLock = true; |
113 | Dictionary1.Remove(key1); | ||
114 | success = Dictionary2.Remove(key2); | ||
110 | } | 115 | } |
111 | |||
112 | Dictionary1.Remove(key1); | ||
113 | success = Dictionary2.Remove(key2); | ||
114 | } | 116 | } |
115 | finally | 117 | finally |
116 | { | 118 | { |
117 | if (gotLock) | 119 | if (gotLock) |
118 | rwLock.ExitWriteLock(); | 120 | rwLock.ExitWriteLock(); |
119 | } | 121 | } |
120 | 122 | ||
121 | return success; | 123 | return success; |
@@ -131,7 +133,7 @@ namespace OpenSim.Framework | |||
131 | // Avoid an asynchronous Thread.Abort() from possibly never existing an acquired lock by placing | 133 | // Avoid an asynchronous Thread.Abort() from possibly never existing an acquired lock by placing |
132 | // the acquision inside the main try. The inner finally block is needed because thread aborts cannot | 134 | // the acquision inside the main try. The inner finally block is needed because thread aborts cannot |
133 | // interrupt code in these blocks (hence gotLock is guaranteed to be set correctly). | 135 | // interrupt code in these blocks (hence gotLock is guaranteed to be set correctly). |
134 | try {} | 136 | try {} |
135 | finally | 137 | finally |
136 | { | 138 | { |
137 | rwLock.EnterWriteLock(); | 139 | rwLock.EnterWriteLock(); |
@@ -146,18 +148,22 @@ namespace OpenSim.Framework | |||
146 | { | 148 | { |
147 | if (kvp.Value.Equals(value)) | 149 | if (kvp.Value.Equals(value)) |
148 | { | 150 | { |
149 | Dictionary1.Remove(key1); | 151 | try { } |
150 | Dictionary2.Remove(kvp.Key); | 152 | finally |
153 | { | ||
154 | Dictionary1.Remove(key1); | ||
155 | Dictionary2.Remove(kvp.Key); | ||
156 | } | ||
151 | found = true; | 157 | found = true; |
152 | break; | 158 | break; |
153 | } | 159 | } |
154 | } | 160 | } |
155 | } | 161 | } |
156 | } | 162 | } |
157 | finally | 163 | finally |
158 | { | 164 | { |
159 | if (gotLock) | 165 | if (gotLock) |
160 | rwLock.ExitWriteLock(); | 166 | rwLock.ExitWriteLock(); |
161 | } | 167 | } |
162 | 168 | ||
163 | return found; | 169 | return found; |
@@ -173,7 +179,7 @@ namespace OpenSim.Framework | |||
173 | // Avoid an asynchronous Thread.Abort() from possibly never existing an acquired lock by placing | 179 | // Avoid an asynchronous Thread.Abort() from possibly never existing an acquired lock by placing |
174 | // the acquision inside the main try. The inner finally block is needed because thread aborts cannot | 180 | // the acquision inside the main try. The inner finally block is needed because thread aborts cannot |
175 | // interrupt code in these blocks (hence gotLock is guaranteed to be set correctly). | 181 | // interrupt code in these blocks (hence gotLock is guaranteed to be set correctly). |
176 | try {} | 182 | try {} |
177 | finally | 183 | finally |
178 | { | 184 | { |
179 | rwLock.EnterWriteLock(); | 185 | rwLock.EnterWriteLock(); |
@@ -188,18 +194,22 @@ namespace OpenSim.Framework | |||
188 | { | 194 | { |
189 | if (kvp.Value.Equals(value)) | 195 | if (kvp.Value.Equals(value)) |
190 | { | 196 | { |
191 | Dictionary2.Remove(key2); | 197 | try { } |
192 | Dictionary1.Remove(kvp.Key); | 198 | finally |
199 | { | ||
200 | Dictionary2.Remove(key2); | ||
201 | Dictionary1.Remove(kvp.Key); | ||
202 | } | ||
193 | found = true; | 203 | found = true; |
194 | break; | 204 | break; |
195 | } | 205 | } |
196 | } | 206 | } |
197 | } | 207 | } |
198 | } | 208 | } |
199 | finally | 209 | finally |
200 | { | 210 | { |
201 | if (gotLock) | 211 | if (gotLock) |
202 | rwLock.ExitWriteLock(); | 212 | rwLock.ExitWriteLock(); |
203 | } | 213 | } |
204 | 214 | ||
205 | return found; | 215 | return found; |
@@ -214,20 +224,19 @@ namespace OpenSim.Framework | |||
214 | // Avoid an asynchronous Thread.Abort() from possibly never existing an acquired lock by placing | 224 | // Avoid an asynchronous Thread.Abort() from possibly never existing an acquired lock by placing |
215 | // the acquision inside the main try. The inner finally block is needed because thread aborts cannot | 225 | // the acquision inside the main try. The inner finally block is needed because thread aborts cannot |
216 | // interrupt code in these blocks (hence gotLock is guaranteed to be set correctly). | 226 | // interrupt code in these blocks (hence gotLock is guaranteed to be set correctly). |
217 | try {} | 227 | try {} |
218 | finally | 228 | finally |
219 | { | 229 | { |
220 | rwLock.EnterWriteLock(); | 230 | rwLock.EnterWriteLock(); |
221 | gotLock = true; | 231 | gotLock = true; |
232 | Dictionary1.Clear(); | ||
233 | Dictionary2.Clear(); | ||
222 | } | 234 | } |
223 | |||
224 | Dictionary1.Clear(); | ||
225 | Dictionary2.Clear(); | ||
226 | } | 235 | } |
227 | finally | 236 | finally |
228 | { | 237 | { |
229 | if (gotLock) | 238 | if (gotLock) |
230 | rwLock.ExitWriteLock(); | 239 | rwLock.ExitWriteLock(); |
231 | } | 240 | } |
232 | } | 241 | } |
233 | 242 | ||
@@ -251,24 +260,24 @@ namespace OpenSim.Framework | |||
251 | bool success; | 260 | bool success; |
252 | bool gotLock = false; | 261 | bool gotLock = false; |
253 | 262 | ||
254 | try | 263 | try |
255 | { | 264 | { |
256 | // Avoid an asynchronous Thread.Abort() from possibly never existing an acquired lock by placing | 265 | // Avoid an asynchronous Thread.Abort() from possibly never existing an acquired lock by placing |
257 | // the acquision inside the main try. The inner finally block is needed because thread aborts cannot | 266 | // the acquision inside the main try. The inner finally block is needed because thread aborts cannot |
258 | // interrupt code in these blocks (hence gotLock is guaranteed to be set correctly). | 267 | // interrupt code in these blocks (hence gotLock is guaranteed to be set correctly). |
259 | try {} | 268 | try {} |
260 | finally | 269 | finally |
261 | { | 270 | { |
262 | rwLock.EnterReadLock(); | 271 | rwLock.EnterReadLock(); |
263 | gotLock = true; | 272 | gotLock = true; |
264 | } | 273 | } |
265 | 274 | ||
266 | success = Dictionary1.TryGetValue(key, out value); | 275 | success = Dictionary1.TryGetValue(key, out value); |
267 | } | 276 | } |
268 | finally | 277 | finally |
269 | { | 278 | { |
270 | if (gotLock) | 279 | if (gotLock) |
271 | rwLock.ExitReadLock(); | 280 | rwLock.ExitReadLock(); |
272 | } | 281 | } |
273 | 282 | ||
274 | return success; | 283 | return success; |
@@ -279,24 +288,24 @@ namespace OpenSim.Framework | |||
279 | bool success; | 288 | bool success; |
280 | bool gotLock = false; | 289 | bool gotLock = false; |
281 | 290 | ||
282 | try | 291 | try |
283 | { | 292 | { |
284 | // Avoid an asynchronous Thread.Abort() from possibly never existing an acquired lock by placing | 293 | // Avoid an asynchronous Thread.Abort() from possibly never existing an acquired lock by placing |
285 | // the acquision inside the main try. The inner finally block is needed because thread aborts cannot | 294 | // the acquision inside the main try. The inner finally block is needed because thread aborts cannot |
286 | // interrupt code in these blocks (hence gotLock is guaranteed to be set correctly). | 295 | // interrupt code in these blocks (hence gotLock is guaranteed to be set correctly). |
287 | try {} | 296 | try {} |
288 | finally | 297 | finally |
289 | { | 298 | { |
290 | rwLock.EnterReadLock(); | 299 | rwLock.EnterReadLock(); |
291 | gotLock = true; | 300 | gotLock = true; |
292 | } | 301 | } |
293 | 302 | ||
294 | success = Dictionary2.TryGetValue(key, out value); | 303 | success = Dictionary2.TryGetValue(key, out value); |
295 | } | 304 | } |
296 | finally | 305 | finally |
297 | { | 306 | { |
298 | if (gotLock) | 307 | if (gotLock) |
299 | rwLock.ExitReadLock(); | 308 | rwLock.ExitReadLock(); |
300 | } | 309 | } |
301 | 310 | ||
302 | return success; | 311 | return success; |
@@ -311,7 +320,7 @@ namespace OpenSim.Framework | |||
311 | // Avoid an asynchronous Thread.Abort() from possibly never existing an acquired lock by placing | 320 | // Avoid an asynchronous Thread.Abort() from possibly never existing an acquired lock by placing |
312 | // the acquision inside the main try. The inner finally block is needed because thread aborts cannot | 321 | // the acquision inside the main try. The inner finally block is needed because thread aborts cannot |
313 | // interrupt code in these blocks (hence gotLock is guaranteed to be set correctly). | 322 | // interrupt code in these blocks (hence gotLock is guaranteed to be set correctly). |
314 | try {} | 323 | try {} |
315 | finally | 324 | finally |
316 | { | 325 | { |
317 | rwLock.EnterReadLock(); | 326 | rwLock.EnterReadLock(); |
@@ -321,10 +330,10 @@ namespace OpenSim.Framework | |||
321 | foreach (TValue value in Dictionary1.Values) | 330 | foreach (TValue value in Dictionary1.Values) |
322 | action(value); | 331 | action(value); |
323 | } | 332 | } |
324 | finally | 333 | finally |
325 | { | 334 | { |
326 | if (gotLock) | 335 | if (gotLock) |
327 | rwLock.ExitReadLock(); | 336 | rwLock.ExitReadLock(); |
328 | } | 337 | } |
329 | } | 338 | } |
330 | 339 | ||
@@ -337,7 +346,7 @@ namespace OpenSim.Framework | |||
337 | // Avoid an asynchronous Thread.Abort() from possibly never existing an acquired lock by placing | 346 | // Avoid an asynchronous Thread.Abort() from possibly never existing an acquired lock by placing |
338 | // the acquision inside the main try. The inner finally block is needed because thread aborts cannot | 347 | // the acquision inside the main try. The inner finally block is needed because thread aborts cannot |
339 | // interrupt code in these blocks (hence gotLock is guaranteed to be set correctly). | 348 | // interrupt code in these blocks (hence gotLock is guaranteed to be set correctly). |
340 | try {} | 349 | try {} |
341 | finally | 350 | finally |
342 | { | 351 | { |
343 | rwLock.EnterReadLock(); | 352 | rwLock.EnterReadLock(); |
@@ -347,10 +356,10 @@ namespace OpenSim.Framework | |||
347 | foreach (KeyValuePair<TKey1, TValue> entry in Dictionary1) | 356 | foreach (KeyValuePair<TKey1, TValue> entry in Dictionary1) |
348 | action(entry); | 357 | action(entry); |
349 | } | 358 | } |
350 | finally | 359 | finally |
351 | { | 360 | { |
352 | if (gotLock) | 361 | if (gotLock) |
353 | rwLock.ExitReadLock(); | 362 | rwLock.ExitReadLock(); |
354 | } | 363 | } |
355 | } | 364 | } |
356 | 365 | ||
@@ -363,7 +372,7 @@ namespace OpenSim.Framework | |||
363 | // Avoid an asynchronous Thread.Abort() from possibly never existing an acquired lock by placing | 372 | // Avoid an asynchronous Thread.Abort() from possibly never existing an acquired lock by placing |
364 | // the acquision inside the main try. The inner finally block is needed because thread aborts cannot | 373 | // the acquision inside the main try. The inner finally block is needed because thread aborts cannot |
365 | // interrupt code in these blocks (hence gotLock is guaranteed to be set correctly). | 374 | // interrupt code in these blocks (hence gotLock is guaranteed to be set correctly). |
366 | try {} | 375 | try {} |
367 | finally | 376 | finally |
368 | { | 377 | { |
369 | rwLock.EnterReadLock(); | 378 | rwLock.EnterReadLock(); |
@@ -373,10 +382,10 @@ namespace OpenSim.Framework | |||
373 | foreach (KeyValuePair<TKey2, TValue> entry in Dictionary2) | 382 | foreach (KeyValuePair<TKey2, TValue> entry in Dictionary2) |
374 | action(entry); | 383 | action(entry); |
375 | } | 384 | } |
376 | finally | 385 | finally |
377 | { | 386 | { |
378 | if (gotLock) | 387 | if (gotLock) |
379 | rwLock.ExitReadLock(); | 388 | rwLock.ExitReadLock(); |
380 | } | 389 | } |
381 | } | 390 | } |
382 | 391 | ||
@@ -389,7 +398,7 @@ namespace OpenSim.Framework | |||
389 | // Avoid an asynchronous Thread.Abort() from possibly never existing an acquired lock by placing | 398 | // Avoid an asynchronous Thread.Abort() from possibly never existing an acquired lock by placing |
390 | // the acquision inside the main try. The inner finally block is needed because thread aborts cannot | 399 | // the acquision inside the main try. The inner finally block is needed because thread aborts cannot |
391 | // interrupt code in these blocks (hence gotLock is guaranteed to be set correctly). | 400 | // interrupt code in these blocks (hence gotLock is guaranteed to be set correctly). |
392 | try {} | 401 | try {} |
393 | finally | 402 | finally |
394 | { | 403 | { |
395 | rwLock.EnterReadLock(); | 404 | rwLock.EnterReadLock(); |
@@ -402,10 +411,10 @@ namespace OpenSim.Framework | |||
402 | return value; | 411 | return value; |
403 | } | 412 | } |
404 | } | 413 | } |
405 | finally | 414 | finally |
406 | { | 415 | { |
407 | if (gotLock) | 416 | if (gotLock) |
408 | rwLock.ExitReadLock(); | 417 | rwLock.ExitReadLock(); |
409 | } | 418 | } |
410 | 419 | ||
411 | return default(TValue); | 420 | return default(TValue); |
@@ -421,7 +430,7 @@ namespace OpenSim.Framework | |||
421 | // Avoid an asynchronous Thread.Abort() from possibly never existing an acquired lock by placing | 430 | // Avoid an asynchronous Thread.Abort() from possibly never existing an acquired lock by placing |
422 | // the acquision inside the main try. The inner finally block is needed because thread aborts cannot | 431 | // the acquision inside the main try. The inner finally block is needed because thread aborts cannot |
423 | // interrupt code in these blocks (hence gotLock is guaranteed to be set correctly). | 432 | // interrupt code in these blocks (hence gotLock is guaranteed to be set correctly). |
424 | try {} | 433 | try {} |
425 | finally | 434 | finally |
426 | { | 435 | { |
427 | rwLock.EnterReadLock(); | 436 | rwLock.EnterReadLock(); |
@@ -434,10 +443,10 @@ namespace OpenSim.Framework | |||
434 | list.Add(value); | 443 | list.Add(value); |
435 | } | 444 | } |
436 | } | 445 | } |
437 | finally | 446 | finally |
438 | { | 447 | { |
439 | if (gotLock) | 448 | if (gotLock) |
440 | rwLock.ExitReadLock(); | 449 | rwLock.ExitReadLock(); |
441 | } | 450 | } |
442 | 451 | ||
443 | return list; | 452 | return list; |
@@ -453,7 +462,7 @@ namespace OpenSim.Framework | |||
453 | // Avoid an asynchronous Thread.Abort() from possibly never existing an acquired lock by placing | 462 | // Avoid an asynchronous Thread.Abort() from possibly never existing an acquired lock by placing |
454 | // the acquision inside the main try. The inner finally block is needed because thread aborts cannot | 463 | // the acquision inside the main try. The inner finally block is needed because thread aborts cannot |
455 | // interrupt code in these blocks (hence gotLock is guaranteed to be set correctly). | 464 | // interrupt code in these blocks (hence gotLock is guaranteed to be set correctly). |
456 | try {} | 465 | try {} |
457 | finally | 466 | finally |
458 | { | 467 | { |
459 | rwLock.EnterUpgradeableReadLock(); | 468 | rwLock.EnterUpgradeableReadLock(); |
@@ -477,29 +486,29 @@ namespace OpenSim.Framework | |||
477 | 486 | ||
478 | try | 487 | try |
479 | { | 488 | { |
480 | try {} | 489 | try {} |
481 | finally | 490 | finally |
482 | { | 491 | { |
483 | rwLock.EnterUpgradeableReadLock(); | 492 | rwLock.EnterWriteLock(); |
484 | gotWriteLock = true; | 493 | gotWriteLock = true; |
485 | } | ||
486 | 494 | ||
487 | for (int i = 0; i < list.Count; i++) | 495 | for (int i = 0; i < list.Count; i++) |
488 | Dictionary1.Remove(list[i]); | 496 | Dictionary1.Remove(list[i]); |
489 | 497 | ||
490 | for (int i = 0; i < list2.Count; i++) | 498 | for (int i = 0; i < list2.Count; i++) |
491 | Dictionary2.Remove(list2[i]); | 499 | Dictionary2.Remove(list2[i]); |
500 | } | ||
492 | } | 501 | } |
493 | finally | 502 | finally |
494 | { | 503 | { |
495 | if (gotWriteLock) | 504 | if (gotWriteLock) |
496 | rwLock.ExitWriteLock(); | 505 | rwLock.ExitWriteLock(); |
497 | } | 506 | } |
498 | } | 507 | } |
499 | finally | 508 | finally |
500 | { | 509 | { |
501 | if (gotUpgradeableLock) | 510 | if (gotUpgradeableLock) |
502 | rwLock.ExitUpgradeableReadLock(); | 511 | rwLock.ExitUpgradeableReadLock(); |
503 | } | 512 | } |
504 | 513 | ||
505 | return list.Count; | 514 | return list.Count; |