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 Dispose_WithReadLock ()
87 var rwl = new ReaderWriterLockSlim ();
92 } catch (SynchronizationLockException) {
97 public void Dispose_WithWriteLock ()
99 var rwl = new ReaderWriterLockSlim ();
100 rwl.EnterWriteLock ();
104 } catch (SynchronizationLockException) {
109 public void Dispose_UpgradeableReadLock ()
111 var rwl = new ReaderWriterLockSlim ();
112 rwl.EnterUpgradeableReadLock ();
116 } catch (SynchronizationLockException) {
121 public void TryEnterReadLock_OutOfRange ()
123 var v = new ReaderWriterLockSlim ();
125 v.TryEnterReadLock (-2);
127 } catch (ArgumentOutOfRangeException) {
131 v.TryEnterReadLock (TimeSpan.MaxValue);
133 } catch (ArgumentOutOfRangeException) {
137 v.TryEnterReadLock (TimeSpan.MinValue);
139 } catch (ArgumentOutOfRangeException) {
144 public void TryEnterUpgradeableReadLock_OutOfRange ()
146 var v = new ReaderWriterLockSlim ();
148 v.TryEnterUpgradeableReadLock (-2);
150 } catch (ArgumentOutOfRangeException) {
154 v.TryEnterUpgradeableReadLock (TimeSpan.MaxValue);
156 } catch (ArgumentOutOfRangeException) {
160 v.TryEnterUpgradeableReadLock (TimeSpan.MinValue);
162 } catch (ArgumentOutOfRangeException) {
167 public void TryEnterWriteLock_OutOfRange ()
169 var v = new ReaderWriterLockSlim ();
171 v.TryEnterWriteLock (-2);
173 } catch (ArgumentOutOfRangeException) {
177 v.TryEnterWriteLock (TimeSpan.MaxValue);
179 } catch (ArgumentOutOfRangeException) {
183 v.TryEnterWriteLock (TimeSpan.MinValue);
185 } catch (ArgumentOutOfRangeException) {
189 [Test, ExpectedException (typeof (SynchronizationLockException))]
190 public void ExitReadLock ()
192 var v = new ReaderWriterLockSlim ();
196 [Test, ExpectedException (typeof (SynchronizationLockException))]
197 public void ExitWriteLock ()
199 var v = new ReaderWriterLockSlim ();
204 public void EnterReadLock_NoRecursionError ()
206 var v = new ReaderWriterLockSlim ();
208 Assert.AreEqual (1, v.RecursiveReadCount);
213 } catch (LockRecursionException) {
219 } catch (LockRecursionException) {
224 public void EnterReadLock ()
226 var v = new ReaderWriterLockSlim ();
229 Assert.IsTrue (v.IsReadLockHeld, "A");
230 Assert.AreEqual (0, v.RecursiveWriteCount, "A1");
231 Assert.AreEqual (1, v.RecursiveReadCount, "A2");
232 Assert.AreEqual (0, v.RecursiveUpgradeCount, "A3");
233 Assert.AreEqual (0, v.WaitingReadCount, "A4");
234 Assert.AreEqual (0, v.WaitingUpgradeCount, "A5");
235 Assert.AreEqual (0, v.WaitingWriteCount, "A6");
239 Assert.IsTrue (v.IsReadLockHeld, "B");
240 Assert.AreEqual (0, v.RecursiveWriteCount, "B1");
241 Assert.AreEqual (1, v.RecursiveReadCount, "B2");
242 Assert.AreEqual (0, v.RecursiveUpgradeCount, "B3");
243 Assert.AreEqual (0, v.WaitingReadCount, "B4");
244 Assert.AreEqual (0, v.WaitingUpgradeCount, "B5");
245 Assert.AreEqual (0, v.WaitingWriteCount, "B6");
250 public void EnterWriteLock_NoRecursionError ()
252 var v = new ReaderWriterLockSlim ();
254 Assert.AreEqual (1, v.RecursiveWriteCount);
259 } catch (LockRecursionException) {
265 } catch (LockRecursionException) {
270 public void EnterWriteLock ()
272 var v = new ReaderWriterLockSlim ();
275 Assert.IsTrue (v.IsWriteLockHeld, "A");
276 Assert.AreEqual (1, v.RecursiveWriteCount, "A1");
277 Assert.AreEqual (0, v.RecursiveReadCount, "A2");
278 Assert.AreEqual (0, v.RecursiveUpgradeCount, "A3");
279 Assert.AreEqual (0, v.WaitingReadCount, "A4");
280 Assert.AreEqual (0, v.WaitingUpgradeCount, "A5");
281 Assert.AreEqual (0, v.WaitingWriteCount, "A6");
285 Assert.IsTrue (v.IsWriteLockHeld, "B");
286 Assert.AreEqual (1, v.RecursiveWriteCount, "B1");
287 Assert.AreEqual (0, v.RecursiveReadCount, "B2");
288 Assert.AreEqual (0, v.RecursiveUpgradeCount, "B3");
289 Assert.AreEqual (0, v.WaitingReadCount, "B4");
290 Assert.AreEqual (0, v.WaitingUpgradeCount, "B5");
291 Assert.AreEqual (0, v.WaitingWriteCount, "B6");
296 public void EnterUpgradeableReadLock_NoRecursionError ()
298 var v = new ReaderWriterLockSlim ();
299 v.EnterUpgradeableReadLock ();
300 Assert.AreEqual (1, v.RecursiveUpgradeCount);
303 v.EnterUpgradeableReadLock ();
305 } catch (LockRecursionException) {
310 public void EnterUpgradeableReadLock ()
312 var v = new ReaderWriterLockSlim ();
314 v.EnterUpgradeableReadLock ();
315 Assert.IsTrue (v.IsUpgradeableReadLockHeld, "A");
316 Assert.AreEqual (0, v.RecursiveWriteCount, "A1");
317 Assert.AreEqual (0, v.RecursiveReadCount, "A2");
318 Assert.AreEqual (1, v.RecursiveUpgradeCount, "A3");
319 Assert.AreEqual (0, v.WaitingReadCount, "A4");
320 Assert.AreEqual (0, v.WaitingUpgradeCount, "A5");
321 Assert.AreEqual (0, v.WaitingWriteCount, "A6");
322 v.ExitUpgradeableReadLock ();
324 v.EnterUpgradeableReadLock ();
325 Assert.IsTrue (v.IsUpgradeableReadLockHeld, "B");
326 Assert.AreEqual (0, v.RecursiveWriteCount, "B1");
327 Assert.AreEqual (0, v.RecursiveReadCount, "B2");
328 Assert.AreEqual (1, v.RecursiveUpgradeCount, "B3");
329 Assert.AreEqual (0, v.WaitingReadCount, "B4");
330 Assert.AreEqual (0, v.WaitingUpgradeCount, "B5");
331 Assert.AreEqual (0, v.WaitingWriteCount, "B6");
334 v.ExitUpgradeableReadLock ();
336 Assert.IsTrue (v.IsReadLockHeld, "C");
337 Assert.AreEqual (0, v.RecursiveWriteCount, "C1");
338 Assert.AreEqual (1, v.RecursiveReadCount, "C2");
339 Assert.AreEqual (0, v.RecursiveUpgradeCount, "C3");
340 Assert.AreEqual (0, v.WaitingReadCount, "C4");
341 Assert.AreEqual (0, v.WaitingUpgradeCount, "C5");
342 Assert.AreEqual (0, v.WaitingWriteCount, "C6");
348 public void EnterReadLock_MultiRead ()
350 var v = new ReaderWriterLockSlim ();
353 var r = from i in Enumerable.Range (1, 30) select new Thread (() => {
355 // Just to cause some contention
360 Assert.AreEqual (10, local);
363 var threads = r.ToList ();
365 foreach (var t in threads) {
369 foreach (var t in threads) {
370 // Console.WriteLine (t.ThreadState);
376 public void TryEnterWriteLock_WhileReading ()
378 var v = new ReaderWriterLockSlim ();
379 AutoResetEvent ev = new AutoResetEvent (false);
380 AutoResetEvent ev2 = new AutoResetEvent (false);
382 Thread t1 = new Thread (() => {
392 Assert.IsFalse (v.TryEnterWriteLock (100));
396 Assert.IsTrue (v.TryEnterWriteLock (100));
400 public void EnterWriteLock_MultiRead ()
402 var v = new ReaderWriterLockSlim ();
405 var r = from i in Enumerable.Range (1, 10) select new Thread (() => {
408 Assert.AreEqual (11, local);
413 var threads = r.ToList ();
414 foreach (var t in threads) {
421 // FIXME: Don't rely on Thread.Sleep (200)
422 Assert.AreEqual (0, v.WaitingWriteCount, "in waiting write");
423 Assert.AreEqual (10, v.WaitingReadCount, "in waiting read");
424 Assert.AreEqual (0, v.WaitingUpgradeCount, "in waiting upgrade");
427 foreach (var t in threads) {
428 // Console.WriteLine (t.ThreadState);
434 public void EnterWriteLock_After_ExitUpgradeableReadLock ()
436 var v = new ReaderWriterLockSlim ();
438 v.EnterUpgradeableReadLock ();
439 Assert.IsTrue (v.TryEnterWriteLock (100));
441 v.ExitUpgradeableReadLock ();
442 Assert.IsTrue (v.TryEnterWriteLock (100));
447 public void EnterWriteLockWhileInUpgradeAndOtherWaiting ()
449 var v = new ReaderWriterLockSlim ();
451 var task2 = new Task(() => {
456 var task1 = new Task(() =>
458 v.EnterUpgradeableReadLock ();
463 v.ExitUpgradeableReadLock ();
467 Assert.IsTrue (task1.Wait (500));
471 public void RecursiveReadLockTest ()
473 var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
475 Assert.IsTrue (v.TryEnterReadLock (100), "#1");
476 Assert.IsTrue (v.TryEnterReadLock (100), "#2");
477 Assert.IsTrue (v.TryEnterReadLock (100), "#3");
479 Assert.AreEqual (3, v.RecursiveReadCount);
483 public void RecursiveReadPlusWriteLockTest ()
485 var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
491 } catch (LockRecursionException ex) {
492 Assert.IsNotNull (ex, "#1");
497 public void RecursiveReadPlusUpgradeableLockTest ()
499 var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
503 v.EnterUpgradeableReadLock ();
505 } catch (LockRecursionException ex) {
506 Assert.IsNotNull (ex, "#1");
511 public void RecursiveWriteLockTest ()
513 var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
515 Assert.IsTrue (v.TryEnterWriteLock (100), "#1");
516 Assert.IsTrue (v.TryEnterWriteLock (100), "#2");
517 Assert.IsTrue (v.TryEnterWriteLock (100), "#3");
519 Assert.AreEqual (3, v.RecursiveWriteCount);
523 public void RecursiveWritePlusReadLockTest ()
525 var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
527 Assert.IsTrue (v.TryEnterWriteLock (100), "#1");
528 Assert.AreEqual (1, v.RecursiveWriteCount, "1b");
529 Assert.AreEqual (0, v.RecursiveReadCount, "1c");
531 Assert.IsTrue (v.TryEnterReadLock (100), "#2");
532 Assert.AreEqual (1, v.RecursiveWriteCount, "2b");
533 Assert.AreEqual (1, v.RecursiveReadCount, "2c");
535 Assert.IsTrue (v.TryEnterReadLock (100), "#3");
536 Assert.AreEqual (1, v.RecursiveWriteCount, "3b");
537 Assert.AreEqual (2, v.RecursiveReadCount, "3c");
540 Assert.AreEqual (1, v.RecursiveWriteCount, "4b");
541 Assert.AreEqual (1, v.RecursiveReadCount, "4c");
545 public void RecursiveUpgradeableReadLockTest ()
547 var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
549 Assert.IsTrue (v.TryEnterUpgradeableReadLock (100), "#1");
550 Assert.IsTrue (v.TryEnterUpgradeableReadLock (100), "#2");
551 Assert.IsTrue (v.TryEnterUpgradeableReadLock (100), "#3");
553 Assert.AreEqual (3, v.RecursiveUpgradeCount);
557 public void RecursiveReadPropertiesTest ()
559 var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
564 Assert.AreEqual (true, v.IsReadLockHeld, "#1a");
565 Assert.AreEqual (1, v.CurrentReadCount, "#2a");
566 Assert.AreEqual (2, v.RecursiveReadCount, "#3a");
569 int cReadCount = -1, rReadCount = -1;
571 Thread t = new Thread ((_) => {
572 rLock = v.IsReadLockHeld;
573 cReadCount = v.CurrentReadCount;
574 rReadCount = v.RecursiveReadCount;
580 Assert.AreEqual (false, rLock, "#1b");
581 Assert.AreEqual (1, cReadCount, "#2b");
582 Assert.AreEqual (0, rReadCount, "#3b");
586 public void RecursiveUpgradePropertiesTest ()
588 var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
590 v.EnterUpgradeableReadLock ();
591 v.EnterUpgradeableReadLock ();
593 Assert.AreEqual (true, v.IsUpgradeableReadLockHeld, "#1a");
594 Assert.AreEqual (false, v.IsReadLockHeld, "#11a");
595 Assert.AreEqual (0, v.CurrentReadCount, "#2a");
596 Assert.AreEqual (2, v.RecursiveUpgradeCount, "#3a");
598 bool upLock = false, rLock = false;
599 int rCount = -1, rUCount = -1;
601 Thread t = new Thread ((_) => {
602 upLock = v.IsUpgradeableReadLockHeld;
603 rLock = v.IsReadLockHeld;
604 rCount = v.CurrentReadCount;
605 rUCount = v.RecursiveUpgradeCount;
611 Assert.AreEqual (false, upLock, "#1b");
612 Assert.AreEqual (false, rLock, "#11b");
613 Assert.AreEqual (0, rCount, "#2b");
614 Assert.AreEqual (0, rUCount, "#3b");
618 public void RecursiveWritePropertiesTest ()
620 var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
625 Assert.AreEqual (true, v.IsWriteLockHeld, "#1a");
626 Assert.AreEqual (2, v.RecursiveWriteCount, "#3a");
631 Thread t = new Thread ((_) => {
632 wLock = v.IsWriteLockHeld;
633 rWrite = v.RecursiveWriteCount;
639 Assert.AreEqual (false, wLock, "#1b");
640 Assert.AreEqual (0, rWrite, "#3b");
644 public void RecursiveEnterExitReadTest ()
646 var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
652 Assert.IsTrue (v.IsReadLockHeld);
653 Assert.AreEqual (3, v.RecursiveReadCount);
657 Assert.IsTrue (v.IsReadLockHeld);
658 Assert.AreEqual (2, v.RecursiveReadCount);
662 public void RecursiveEnterExitWriteTest ()
664 var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
670 Assert.IsTrue (v.IsWriteLockHeld);
671 Assert.AreEqual (3, v.RecursiveWriteCount);
676 Assert.IsTrue (v.IsWriteLockHeld);
677 Assert.AreEqual (1, v.RecursiveWriteCount);
681 public void RecursiveEnterExitUpgradableTest ()
683 var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
685 v.EnterUpgradeableReadLock ();
686 v.EnterUpgradeableReadLock ();
687 v.EnterUpgradeableReadLock ();
689 Assert.IsTrue (v.IsUpgradeableReadLockHeld);
690 Assert.AreEqual (3, v.RecursiveUpgradeCount);
692 v.ExitUpgradeableReadLock ();
694 Assert.IsTrue (v.IsUpgradeableReadLockHeld);
695 Assert.AreEqual (2, v.RecursiveUpgradeCount);
699 public void RecursiveWriteUpgradeReadTest ()
701 var rwlock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
703 rwlock.EnterWriteLock ();
704 Assert.IsTrue (rwlock.IsWriteLockHeld);
705 rwlock.EnterUpgradeableReadLock ();
706 Assert.IsTrue (rwlock.IsUpgradeableReadLockHeld);
707 rwlock.EnterReadLock ();
708 Assert.IsTrue (rwlock.IsReadLockHeld);
709 rwlock.ExitUpgradeableReadLock();
710 Assert.IsFalse (rwlock.IsUpgradeableReadLockHeld);
711 Assert.IsTrue (rwlock.IsReadLockHeld);
712 Assert.IsTrue (rwlock.IsWriteLockHeld);
714 rwlock.ExitReadLock ();
715 Assert.IsTrue (rwlock.IsWriteLockHeld);
719 public void RecursiveWriteUpgradeTest ()
721 ReaderWriterLockSlim rwlock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
723 rwlock.EnterWriteLock ();
724 Assert.IsTrue (rwlock.IsWriteLockHeld);
725 rwlock.EnterUpgradeableReadLock ();
726 Assert.IsTrue (rwlock.IsUpgradeableReadLockHeld);
727 rwlock.ExitUpgradeableReadLock ();
728 Assert.IsFalse (rwlock.IsUpgradeableReadLockHeld);
729 Assert.IsTrue (rwlock.IsWriteLockHeld);
730 rwlock.ExitWriteLock ();
731 Assert.IsFalse (rwlock.IsWriteLockHeld);
732 rwlock.EnterWriteLock ();
733 Assert.IsTrue (rwlock.IsWriteLockHeld);
737 public void RecursiveWriteReadAcquisitionInterleaving ()
739 var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
742 Assert.IsTrue (v.IsWriteLockHeld, "#1");
745 var t = new Thread (delegate () {
746 result = v.TryEnterReadLock (100);
750 Assert.IsFalse (result, "#2");
753 t = new Thread (delegate () {
754 result = v.TryEnterReadLock (100);
758 Assert.IsTrue (result, "#3");