2 // ReaderWriterLockSlimTest.cs
5 // Marek Safar (marek.safar@gmail.com)
7 // Copyright (C) 2009 Novell, Inc (http://www.novell.com)
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 using NUnit.Framework;
31 using System.Threading;
34 using System.Threading.Tasks;
37 namespace MonoTests.System.Threading
40 public class ReaderWriterLockSlimTests
43 public void DefaultValues ()
45 var v = new ReaderWriterLockSlim ();
46 Assert.AreEqual (0, v.CurrentReadCount, "1");
47 Assert.AreEqual (false, v.IsReadLockHeld, "2");
48 Assert.AreEqual (false, v.IsUpgradeableReadLockHeld, "3");
49 Assert.AreEqual (false, v.IsWriteLockHeld, "4");
50 Assert.AreEqual (LockRecursionPolicy.NoRecursion, v.RecursionPolicy, "5");
51 Assert.AreEqual (0, v.RecursiveReadCount, "6");
52 Assert.AreEqual (0, v.RecursiveUpgradeCount, "7");
53 Assert.AreEqual (0, v.RecursiveWriteCount, "8");
54 Assert.AreEqual (0, v.WaitingReadCount, "9");
55 Assert.AreEqual (0, v.WaitingUpgradeCount, "10");
56 Assert.AreEqual (0, v.WaitingWriteCount, "11");
60 public void Dispose_Errors ()
62 var v = new ReaderWriterLockSlim ();
66 v.EnterUpgradeableReadLock ();
68 } catch (ObjectDisposedException) {
74 } catch (ObjectDisposedException) {
80 } catch (ObjectDisposedException) {
85 public void TryEnterReadLock_OutOfRange ()
87 var v = new ReaderWriterLockSlim ();
89 v.TryEnterReadLock (-2);
91 } catch (ArgumentOutOfRangeException) {
95 v.TryEnterReadLock (TimeSpan.MaxValue);
97 } catch (ArgumentOutOfRangeException) {
101 v.TryEnterReadLock (TimeSpan.MinValue);
103 } catch (ArgumentOutOfRangeException) {
108 public void TryEnterUpgradeableReadLock_OutOfRange ()
110 var v = new ReaderWriterLockSlim ();
112 v.TryEnterUpgradeableReadLock (-2);
114 } catch (ArgumentOutOfRangeException) {
118 v.TryEnterUpgradeableReadLock (TimeSpan.MaxValue);
120 } catch (ArgumentOutOfRangeException) {
124 v.TryEnterUpgradeableReadLock (TimeSpan.MinValue);
126 } catch (ArgumentOutOfRangeException) {
131 public void TryEnterWriteLock_OutOfRange ()
133 var v = new ReaderWriterLockSlim ();
135 v.TryEnterWriteLock (-2);
137 } catch (ArgumentOutOfRangeException) {
141 v.TryEnterWriteLock (TimeSpan.MaxValue);
143 } catch (ArgumentOutOfRangeException) {
147 v.TryEnterWriteLock (TimeSpan.MinValue);
149 } catch (ArgumentOutOfRangeException) {
153 [Test, ExpectedException (typeof (SynchronizationLockException))]
154 public void ExitReadLock ()
156 var v = new ReaderWriterLockSlim ();
160 [Test, ExpectedException (typeof (SynchronizationLockException))]
161 public void ExitWriteLock ()
163 var v = new ReaderWriterLockSlim ();
168 public void EnterReadLock_NoRecursionError ()
170 var v = new ReaderWriterLockSlim ();
172 Assert.AreEqual (1, v.RecursiveReadCount);
177 } catch (LockRecursionException) {
183 } catch (LockRecursionException) {
188 public void EnterReadLock ()
190 var v = new ReaderWriterLockSlim ();
193 Assert.IsTrue (v.IsReadLockHeld, "A");
194 Assert.AreEqual (0, v.RecursiveWriteCount, "A1");
195 Assert.AreEqual (1, v.RecursiveReadCount, "A2");
196 Assert.AreEqual (0, v.RecursiveUpgradeCount, "A3");
197 Assert.AreEqual (0, v.WaitingReadCount, "A4");
198 Assert.AreEqual (0, v.WaitingUpgradeCount, "A5");
199 Assert.AreEqual (0, v.WaitingWriteCount, "A6");
203 Assert.IsTrue (v.IsReadLockHeld, "B");
204 Assert.AreEqual (0, v.RecursiveWriteCount, "B1");
205 Assert.AreEqual (1, v.RecursiveReadCount, "B2");
206 Assert.AreEqual (0, v.RecursiveUpgradeCount, "B3");
207 Assert.AreEqual (0, v.WaitingReadCount, "B4");
208 Assert.AreEqual (0, v.WaitingUpgradeCount, "B5");
209 Assert.AreEqual (0, v.WaitingWriteCount, "B6");
214 public void EnterWriteLock_NoRecursionError ()
216 var v = new ReaderWriterLockSlim ();
218 Assert.AreEqual (1, v.RecursiveWriteCount);
223 } catch (LockRecursionException) {
229 } catch (LockRecursionException) {
234 public void EnterWriteLock ()
236 var v = new ReaderWriterLockSlim ();
239 Assert.IsTrue (v.IsWriteLockHeld, "A");
240 Assert.AreEqual (1, v.RecursiveWriteCount, "A1");
241 Assert.AreEqual (0, v.RecursiveReadCount, "A2");
242 Assert.AreEqual (0, v.RecursiveUpgradeCount, "A3");
243 Assert.AreEqual (0, v.WaitingReadCount, "A4");
244 Assert.AreEqual (0, v.WaitingUpgradeCount, "A5");
245 Assert.AreEqual (0, v.WaitingWriteCount, "A6");
249 Assert.IsTrue (v.IsWriteLockHeld, "B");
250 Assert.AreEqual (1, v.RecursiveWriteCount, "B1");
251 Assert.AreEqual (0, v.RecursiveReadCount, "B2");
252 Assert.AreEqual (0, v.RecursiveUpgradeCount, "B3");
253 Assert.AreEqual (0, v.WaitingReadCount, "B4");
254 Assert.AreEqual (0, v.WaitingUpgradeCount, "B5");
255 Assert.AreEqual (0, v.WaitingWriteCount, "B6");
260 public void EnterUpgradeableReadLock_NoRecursionError ()
262 var v = new ReaderWriterLockSlim ();
263 v.EnterUpgradeableReadLock ();
264 Assert.AreEqual (1, v.RecursiveUpgradeCount);
267 v.EnterUpgradeableReadLock ();
269 } catch (LockRecursionException) {
274 public void EnterUpgradeableReadLock ()
276 var v = new ReaderWriterLockSlim ();
278 v.EnterUpgradeableReadLock ();
279 Assert.IsTrue (v.IsUpgradeableReadLockHeld, "A");
280 Assert.AreEqual (0, v.RecursiveWriteCount, "A1");
281 Assert.AreEqual (0, v.RecursiveReadCount, "A2");
282 Assert.AreEqual (1, v.RecursiveUpgradeCount, "A3");
283 Assert.AreEqual (0, v.WaitingReadCount, "A4");
284 Assert.AreEqual (0, v.WaitingUpgradeCount, "A5");
285 Assert.AreEqual (0, v.WaitingWriteCount, "A6");
286 v.ExitUpgradeableReadLock ();
288 v.EnterUpgradeableReadLock ();
289 Assert.IsTrue (v.IsUpgradeableReadLockHeld, "B");
290 Assert.AreEqual (0, v.RecursiveWriteCount, "B1");
291 Assert.AreEqual (0, v.RecursiveReadCount, "B2");
292 Assert.AreEqual (1, v.RecursiveUpgradeCount, "B3");
293 Assert.AreEqual (0, v.WaitingReadCount, "B4");
294 Assert.AreEqual (0, v.WaitingUpgradeCount, "B5");
295 Assert.AreEqual (0, v.WaitingWriteCount, "B6");
298 v.ExitUpgradeableReadLock ();
300 Assert.IsTrue (v.IsReadLockHeld, "C");
301 Assert.AreEqual (0, v.RecursiveWriteCount, "C1");
302 Assert.AreEqual (1, v.RecursiveReadCount, "C2");
303 Assert.AreEqual (0, v.RecursiveUpgradeCount, "C3");
304 Assert.AreEqual (0, v.WaitingReadCount, "C4");
305 Assert.AreEqual (0, v.WaitingUpgradeCount, "C5");
306 Assert.AreEqual (0, v.WaitingWriteCount, "C6");
312 public void EnterReadLock_MultiRead ()
314 var v = new ReaderWriterLockSlim ();
317 var r = from i in Enumerable.Range (1, 30) select new Thread (() => {
319 // Just to cause some contention
324 Assert.AreEqual (10, local);
327 var threads = r.ToList ();
329 foreach (var t in threads) {
333 foreach (var t in threads) {
334 // Console.WriteLine (t.ThreadState);
340 public void TryEnterWriteLock_WhileReading ()
342 var v = new ReaderWriterLockSlim ();
343 AutoResetEvent ev = new AutoResetEvent (false);
344 AutoResetEvent ev2 = new AutoResetEvent (false);
346 Thread t1 = new Thread (() => {
356 Assert.IsFalse (v.TryEnterWriteLock (100));
360 Assert.IsTrue (v.TryEnterWriteLock (100));
364 public void EnterWriteLock_MultiRead ()
366 var v = new ReaderWriterLockSlim ();
369 var r = from i in Enumerable.Range (1, 10) select new Thread (() => {
372 Assert.AreEqual (11, local);
377 var threads = r.ToList ();
378 foreach (var t in threads) {
385 // FIXME: Don't rely on Thread.Sleep (200)
386 Assert.AreEqual (0, v.WaitingWriteCount, "in waiting write");
387 Assert.AreEqual (10, v.WaitingReadCount, "in waiting read");
388 Assert.AreEqual (0, v.WaitingUpgradeCount, "in waiting upgrade");
391 foreach (var t in threads) {
392 // Console.WriteLine (t.ThreadState);
398 public void EnterWriteLock_After_ExitUpgradeableReadLock ()
400 var v = new ReaderWriterLockSlim ();
402 v.EnterUpgradeableReadLock ();
403 Assert.IsTrue (v.TryEnterWriteLock (100));
405 v.ExitUpgradeableReadLock ();
406 Assert.IsTrue (v.TryEnterWriteLock (100));
411 public void EnterWriteLockWhileInUpgradeAndOtherWaiting ()
413 var v = new ReaderWriterLockSlim ();
415 var task2 = new Task(() => {
420 var task1 = new Task(() =>
422 v.EnterUpgradeableReadLock ();
427 v.ExitUpgradeableReadLock ();
431 Assert.IsTrue (task1.Wait (500));
435 public void RecursiveReadLockTest ()
437 var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
439 Assert.IsTrue (v.TryEnterReadLock (100), "#1");
440 Assert.IsTrue (v.TryEnterReadLock (100), "#2");
441 Assert.IsTrue (v.TryEnterReadLock (100), "#3");
443 Assert.AreEqual (3, v.RecursiveReadCount);
447 public void RecursiveReadPlusWriteLockTest ()
449 var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
455 } catch (LockRecursionException ex) {
456 Assert.IsNotNull (ex, "#1");
461 public void RecursiveReadPlusUpgradeableLockTest ()
463 var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
467 v.EnterUpgradeableReadLock ();
469 } catch (LockRecursionException ex) {
470 Assert.IsNotNull (ex, "#1");
475 public void RecursiveWriteLockTest ()
477 var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
479 Assert.IsTrue (v.TryEnterWriteLock (100), "#1");
480 Assert.IsTrue (v.TryEnterWriteLock (100), "#2");
481 Assert.IsTrue (v.TryEnterWriteLock (100), "#3");
483 Assert.AreEqual (3, v.RecursiveWriteCount);
487 public void RecursiveWritePlusReadLockTest ()
489 var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
491 Assert.IsTrue (v.TryEnterWriteLock (100), "#1");
492 Assert.AreEqual (1, v.RecursiveWriteCount, "1b");
493 Assert.AreEqual (0, v.RecursiveReadCount, "1c");
495 Assert.IsTrue (v.TryEnterReadLock (100), "#2");
496 Assert.AreEqual (1, v.RecursiveWriteCount, "2b");
497 Assert.AreEqual (1, v.RecursiveReadCount, "2c");
499 Assert.IsTrue (v.TryEnterReadLock (100), "#3");
500 Assert.AreEqual (1, v.RecursiveWriteCount, "3b");
501 Assert.AreEqual (2, v.RecursiveReadCount, "3c");
504 Assert.AreEqual (1, v.RecursiveWriteCount, "4b");
505 Assert.AreEqual (1, v.RecursiveReadCount, "4c");
509 public void RecursiveUpgradeableReadLockTest ()
511 var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
513 Assert.IsTrue (v.TryEnterUpgradeableReadLock (100), "#1");
514 Assert.IsTrue (v.TryEnterUpgradeableReadLock (100), "#2");
515 Assert.IsTrue (v.TryEnterUpgradeableReadLock (100), "#3");
517 Assert.AreEqual (3, v.RecursiveUpgradeCount);
521 public void RecursiveReadPropertiesTest ()
523 var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
528 Assert.AreEqual (true, v.IsReadLockHeld, "#1a");
529 Assert.AreEqual (1, v.CurrentReadCount, "#2a");
530 Assert.AreEqual (2, v.RecursiveReadCount, "#3a");
533 int cReadCount = -1, rReadCount = -1;
535 Thread t = new Thread ((_) => {
536 rLock = v.IsReadLockHeld;
537 cReadCount = v.CurrentReadCount;
538 rReadCount = v.RecursiveReadCount;
544 Assert.AreEqual (false, rLock, "#1b");
545 Assert.AreEqual (1, cReadCount, "#2b");
546 Assert.AreEqual (0, rReadCount, "#3b");
550 public void RecursiveUpgradePropertiesTest ()
552 var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
554 v.EnterUpgradeableReadLock ();
555 v.EnterUpgradeableReadLock ();
557 Assert.AreEqual (true, v.IsUpgradeableReadLockHeld, "#1a");
558 Assert.AreEqual (false, v.IsReadLockHeld, "#11a");
559 Assert.AreEqual (0, v.CurrentReadCount, "#2a");
560 Assert.AreEqual (2, v.RecursiveUpgradeCount, "#3a");
562 bool upLock = false, rLock = false;
563 int rCount = -1, rUCount = -1;
565 Thread t = new Thread ((_) => {
566 upLock = v.IsUpgradeableReadLockHeld;
567 rLock = v.IsReadLockHeld;
568 rCount = v.CurrentReadCount;
569 rUCount = v.RecursiveUpgradeCount;
575 Assert.AreEqual (false, upLock, "#1b");
576 Assert.AreEqual (false, rLock, "#11b");
577 Assert.AreEqual (0, rCount, "#2b");
578 Assert.AreEqual (0, rUCount, "#3b");
582 public void RecursiveWritePropertiesTest ()
584 var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
589 Assert.AreEqual (true, v.IsWriteLockHeld, "#1a");
590 Assert.AreEqual (2, v.RecursiveWriteCount, "#3a");
595 Thread t = new Thread ((_) => {
596 wLock = v.IsWriteLockHeld;
597 rWrite = v.RecursiveWriteCount;
603 Assert.AreEqual (false, wLock, "#1b");
604 Assert.AreEqual (0, rWrite, "#3b");
608 public void RecursiveEnterExitReadTest ()
610 var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
616 Assert.IsTrue (v.IsReadLockHeld);
617 Assert.AreEqual (3, v.RecursiveReadCount);
621 Assert.IsTrue (v.IsReadLockHeld);
622 Assert.AreEqual (2, v.RecursiveReadCount);
626 public void RecursiveEnterExitWriteTest ()
628 var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
634 Assert.IsTrue (v.IsWriteLockHeld);
635 Assert.AreEqual (3, v.RecursiveWriteCount);
640 Assert.IsTrue (v.IsWriteLockHeld);
641 Assert.AreEqual (1, v.RecursiveWriteCount);
645 public void RecursiveEnterExitUpgradableTest ()
647 var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
649 v.EnterUpgradeableReadLock ();
650 v.EnterUpgradeableReadLock ();
651 v.EnterUpgradeableReadLock ();
653 Assert.IsTrue (v.IsUpgradeableReadLockHeld);
654 Assert.AreEqual (3, v.RecursiveUpgradeCount);
656 v.ExitUpgradeableReadLock ();
658 Assert.IsTrue (v.IsUpgradeableReadLockHeld);
659 Assert.AreEqual (2, v.RecursiveUpgradeCount);
663 public void RecursiveWriteUpgradeReadTest ()
665 var rwlock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
667 rwlock.EnterWriteLock ();
668 Assert.IsTrue (rwlock.IsWriteLockHeld);
669 rwlock.EnterUpgradeableReadLock ();
670 Assert.IsTrue (rwlock.IsUpgradeableReadLockHeld);
671 rwlock.EnterReadLock ();
672 Assert.IsTrue (rwlock.IsReadLockHeld);
673 rwlock.ExitUpgradeableReadLock();
674 Assert.IsFalse (rwlock.IsUpgradeableReadLockHeld);
675 Assert.IsTrue (rwlock.IsReadLockHeld);
676 Assert.IsTrue (rwlock.IsWriteLockHeld);
678 rwlock.ExitReadLock ();
679 Assert.IsTrue (rwlock.IsWriteLockHeld);
683 public void RecursiveWriteUpgradeTest ()
685 ReaderWriterLockSlim rwlock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
687 rwlock.EnterWriteLock ();
688 Assert.IsTrue (rwlock.IsWriteLockHeld);
689 rwlock.EnterUpgradeableReadLock ();
690 Assert.IsTrue (rwlock.IsUpgradeableReadLockHeld);
691 rwlock.ExitUpgradeableReadLock ();
692 Assert.IsFalse (rwlock.IsUpgradeableReadLockHeld);
693 Assert.IsTrue (rwlock.IsWriteLockHeld);
694 rwlock.ExitWriteLock ();
695 Assert.IsFalse (rwlock.IsWriteLockHeld);
696 rwlock.EnterWriteLock ();
697 Assert.IsTrue (rwlock.IsWriteLockHeld);
701 public void RecursiveWriteReadAcquisitionInterleaving ()
703 var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
706 Assert.IsTrue (v.IsWriteLockHeld, "#1");
709 var t = new Thread (delegate () {
710 result = v.TryEnterReadLock (100);
714 Assert.IsFalse (result, "#2");
717 t = new Thread (delegate () {
718 result = v.TryEnterReadLock (100);
722 Assert.IsTrue (result, "#3");