aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Framework/DoubleDictionaryThreadAbortSafe.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Framework/DoubleDictionaryThreadAbortSafe.cs')
-rw-r--r--OpenSim/Framework/DoubleDictionaryThreadAbortSafe.cs193
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;