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;
32 using System.Threading.Tasks;
35 namespace MonoTests.System.Threading
38 public class ReaderWriterLockSlimTests
41 public void DefaultValues ()
43 var v = new ReaderWriterLockSlim ();
44 Assert.AreEqual (0, v.CurrentReadCount, "1");
45 Assert.AreEqual (false, v.IsReadLockHeld, "2");
46 Assert.AreEqual (false, v.IsUpgradeableReadLockHeld, "3");
47 Assert.AreEqual (false, v.IsWriteLockHeld, "4");
48 Assert.AreEqual (LockRecursionPolicy.NoRecursion, v.RecursionPolicy, "5");
49 Assert.AreEqual (0, v.RecursiveReadCount, "6");
50 Assert.AreEqual (0, v.RecursiveUpgradeCount, "7");
51 Assert.AreEqual (0, v.RecursiveWriteCount, "8");
52 Assert.AreEqual (0, v.WaitingReadCount, "9");
53 Assert.AreEqual (0, v.WaitingUpgradeCount, "10");
54 Assert.AreEqual (0, v.WaitingWriteCount, "11");
58 public void Dispose_Errors ()
60 var v = new ReaderWriterLockSlim ();
64 v.EnterUpgradeableReadLock ();
66 } catch (ObjectDisposedException) {
72 } catch (ObjectDisposedException) {
78 } catch (ObjectDisposedException) {
83 public void TryEnterReadLock_OutOfRange ()
85 var v = new ReaderWriterLockSlim ();
87 v.TryEnterReadLock (-2);
89 } catch (ArgumentOutOfRangeException) {
93 v.TryEnterReadLock (TimeSpan.MaxValue);
95 } catch (ArgumentOutOfRangeException) {
99 v.TryEnterReadLock (TimeSpan.MinValue);
101 } catch (ArgumentOutOfRangeException) {
106 public void TryEnterUpgradeableReadLock_OutOfRange ()
108 var v = new ReaderWriterLockSlim ();
110 v.TryEnterUpgradeableReadLock (-2);
112 } catch (ArgumentOutOfRangeException) {
116 v.TryEnterUpgradeableReadLock (TimeSpan.MaxValue);
118 } catch (ArgumentOutOfRangeException) {
122 v.TryEnterUpgradeableReadLock (TimeSpan.MinValue);
124 } catch (ArgumentOutOfRangeException) {
129 public void TryEnterWriteLock_OutOfRange ()
131 var v = new ReaderWriterLockSlim ();
133 v.TryEnterWriteLock (-2);
135 } catch (ArgumentOutOfRangeException) {
139 v.TryEnterWriteLock (TimeSpan.MaxValue);
141 } catch (ArgumentOutOfRangeException) {
145 v.TryEnterWriteLock (TimeSpan.MinValue);
147 } catch (ArgumentOutOfRangeException) {
151 [Test, ExpectedException (typeof (SynchronizationLockException))]
152 public void ExitReadLock ()
154 var v = new ReaderWriterLockSlim ();
158 [Test, ExpectedException (typeof (SynchronizationLockException))]
159 public void ExitWriteLock ()
161 var v = new ReaderWriterLockSlim ();
166 public void EnterReadLock_NoRecursionError ()
168 var v = new ReaderWriterLockSlim ();
170 Assert.AreEqual (1, v.RecursiveReadCount);
175 } catch (LockRecursionException) {
181 } catch (LockRecursionException) {
186 public void EnterReadLock ()
188 var v = new ReaderWriterLockSlim ();
191 Assert.IsTrue (v.IsReadLockHeld, "A");
192 Assert.AreEqual (0, v.RecursiveWriteCount, "A1");
193 Assert.AreEqual (1, v.RecursiveReadCount, "A2");
194 Assert.AreEqual (0, v.RecursiveUpgradeCount, "A3");
195 Assert.AreEqual (0, v.WaitingReadCount, "A4");
196 Assert.AreEqual (0, v.WaitingUpgradeCount, "A5");
197 Assert.AreEqual (0, v.WaitingWriteCount, "A6");
201 Assert.IsTrue (v.IsReadLockHeld, "B");
202 Assert.AreEqual (0, v.RecursiveWriteCount, "B1");
203 Assert.AreEqual (1, v.RecursiveReadCount, "B2");
204 Assert.AreEqual (0, v.RecursiveUpgradeCount, "B3");
205 Assert.AreEqual (0, v.WaitingReadCount, "B4");
206 Assert.AreEqual (0, v.WaitingUpgradeCount, "B5");
207 Assert.AreEqual (0, v.WaitingWriteCount, "B6");
212 public void EnterWriteLock_NoRecursionError ()
214 var v = new ReaderWriterLockSlim ();
216 Assert.AreEqual (1, v.RecursiveWriteCount);
221 } catch (LockRecursionException) {
227 } catch (LockRecursionException) {
232 public void EnterWriteLock ()
234 var v = new ReaderWriterLockSlim ();
237 Assert.IsTrue (v.IsWriteLockHeld, "A");
238 Assert.AreEqual (1, v.RecursiveWriteCount, "A1");
239 Assert.AreEqual (0, v.RecursiveReadCount, "A2");
240 Assert.AreEqual (0, v.RecursiveUpgradeCount, "A3");
241 Assert.AreEqual (0, v.WaitingReadCount, "A4");
242 Assert.AreEqual (0, v.WaitingUpgradeCount, "A5");
243 Assert.AreEqual (0, v.WaitingWriteCount, "A6");
247 Assert.IsTrue (v.IsWriteLockHeld, "B");
248 Assert.AreEqual (1, v.RecursiveWriteCount, "B1");
249 Assert.AreEqual (0, v.RecursiveReadCount, "B2");
250 Assert.AreEqual (0, v.RecursiveUpgradeCount, "B3");
251 Assert.AreEqual (0, v.WaitingReadCount, "B4");
252 Assert.AreEqual (0, v.WaitingUpgradeCount, "B5");
253 Assert.AreEqual (0, v.WaitingWriteCount, "B6");
258 public void EnterUpgradeableReadLock_NoRecursionError ()
260 var v = new ReaderWriterLockSlim ();
261 v.EnterUpgradeableReadLock ();
262 Assert.AreEqual (1, v.RecursiveUpgradeCount);
265 v.EnterUpgradeableReadLock ();
267 } catch (LockRecursionException) {
272 public void EnterUpgradeableReadLock ()
274 var v = new ReaderWriterLockSlim ();
276 v.EnterUpgradeableReadLock ();
277 Assert.IsTrue (v.IsUpgradeableReadLockHeld, "A");
278 Assert.AreEqual (0, v.RecursiveWriteCount, "A1");
279 Assert.AreEqual (0, v.RecursiveReadCount, "A2");
280 Assert.AreEqual (1, v.RecursiveUpgradeCount, "A3");
281 Assert.AreEqual (0, v.WaitingReadCount, "A4");
282 Assert.AreEqual (0, v.WaitingUpgradeCount, "A5");
283 Assert.AreEqual (0, v.WaitingWriteCount, "A6");
284 v.ExitUpgradeableReadLock ();
286 v.EnterUpgradeableReadLock ();
287 Assert.IsTrue (v.IsUpgradeableReadLockHeld, "B");
288 Assert.AreEqual (0, v.RecursiveWriteCount, "B1");
289 Assert.AreEqual (0, v.RecursiveReadCount, "B2");
290 Assert.AreEqual (1, v.RecursiveUpgradeCount, "B3");
291 Assert.AreEqual (0, v.WaitingReadCount, "B4");
292 Assert.AreEqual (0, v.WaitingUpgradeCount, "B5");
293 Assert.AreEqual (0, v.WaitingWriteCount, "B6");
296 v.ExitUpgradeableReadLock ();
298 Assert.IsTrue (v.IsReadLockHeld, "C");
299 Assert.AreEqual (0, v.RecursiveWriteCount, "C1");
300 Assert.AreEqual (1, v.RecursiveReadCount, "C2");
301 Assert.AreEqual (0, v.RecursiveUpgradeCount, "C3");
302 Assert.AreEqual (0, v.WaitingReadCount, "C4");
303 Assert.AreEqual (0, v.WaitingUpgradeCount, "C5");
304 Assert.AreEqual (0, v.WaitingWriteCount, "C6");
310 public void EnterReadLock_MultiRead ()
312 var v = new ReaderWriterLockSlim ();
315 var r = from i in Enumerable.Range (1, 30) select new Thread (() => {
317 // Just to cause some contention
322 Assert.AreEqual (10, local);
325 var threads = r.ToList ();
327 foreach (var t in threads) {
331 foreach (var t in threads) {
332 // Console.WriteLine (t.ThreadState);
338 public void TryEnterWriteLock_WhileReading ()
340 var v = new ReaderWriterLockSlim ();
341 AutoResetEvent ev = new AutoResetEvent (false);
342 AutoResetEvent ev2 = new AutoResetEvent (false);
344 Thread t1 = new Thread (() => {
354 Assert.IsFalse (v.TryEnterWriteLock (100));
358 Assert.IsTrue (v.TryEnterWriteLock (100));
362 public void EnterWriteLock_MultiRead ()
364 var v = new ReaderWriterLockSlim ();
367 var r = from i in Enumerable.Range (1, 10) select new Thread (() => {
370 Assert.AreEqual (11, local);
375 var threads = r.ToList ();
376 foreach (var t in threads) {
383 // FIXME: Don't rely on Thread.Sleep (200)
384 Assert.AreEqual (0, v.WaitingWriteCount, "in waiting write");
385 Assert.AreEqual (10, v.WaitingReadCount, "in waiting read");
386 Assert.AreEqual (0, v.WaitingUpgradeCount, "in waiting upgrade");
389 foreach (var t in threads) {
390 // Console.WriteLine (t.ThreadState);
396 public void EnterWriteLock_After_ExitUpgradeableReadLock ()
398 var v = new ReaderWriterLockSlim ();
400 v.EnterUpgradeableReadLock ();
401 Assert.IsTrue (v.TryEnterWriteLock (100));
403 v.ExitUpgradeableReadLock ();
404 Assert.IsTrue (v.TryEnterWriteLock (100));
409 public void EnterWriteLockWhileInUpgradeAndOtherWaiting ()
411 var v = new ReaderWriterLockSlim ();
413 var task2 = new Task(() => {
418 var task1 = new Task(() =>
420 v.EnterUpgradeableReadLock ();
425 v.ExitUpgradeableReadLock ();
429 Assert.IsTrue (task1.Wait (500));
433 public void RecursiveReadLockTest ()
435 var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
437 Assert.IsTrue (v.TryEnterReadLock (100), "#1");
438 Assert.IsTrue (v.TryEnterReadLock (100), "#2");
439 Assert.IsTrue (v.TryEnterReadLock (100), "#3");
441 Assert.AreEqual (3, v.RecursiveReadCount);
445 public void RecursiveReadPlusWriteLockTest ()
447 var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
453 } catch (LockRecursionException ex) {
454 Assert.IsNotNull (ex, "#1");
459 public void RecursiveReadPlusUpgradeableLockTest ()
461 var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
465 v.EnterUpgradeableReadLock ();
467 } catch (LockRecursionException ex) {
468 Assert.IsNotNull (ex, "#1");
473 public void RecursiveWriteLockTest ()
475 var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
477 Assert.IsTrue (v.TryEnterWriteLock (100), "#1");
478 Assert.IsTrue (v.TryEnterWriteLock (100), "#2");
479 Assert.IsTrue (v.TryEnterWriteLock (100), "#3");
481 Assert.AreEqual (3, v.RecursiveWriteCount);
485 public void RecursiveWritePlusReadLockTest ()
487 var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
489 Assert.IsTrue (v.TryEnterWriteLock (100), "#1");
490 Assert.AreEqual (1, v.RecursiveWriteCount, "1b");
491 Assert.AreEqual (0, v.RecursiveReadCount, "1c");
493 Assert.IsTrue (v.TryEnterReadLock (100), "#2");
494 Assert.AreEqual (1, v.RecursiveWriteCount, "2b");
495 Assert.AreEqual (1, v.RecursiveReadCount, "2c");
497 Assert.IsTrue (v.TryEnterReadLock (100), "#3");
498 Assert.AreEqual (1, v.RecursiveWriteCount, "3b");
499 Assert.AreEqual (2, v.RecursiveReadCount, "3c");
502 Assert.AreEqual (1, v.RecursiveWriteCount, "4b");
503 Assert.AreEqual (1, v.RecursiveReadCount, "4c");
507 public void RecursiveUpgradeableReadLockTest ()
509 var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
511 Assert.IsTrue (v.TryEnterUpgradeableReadLock (100), "#1");
512 Assert.IsTrue (v.TryEnterUpgradeableReadLock (100), "#2");
513 Assert.IsTrue (v.TryEnterUpgradeableReadLock (100), "#3");
515 Assert.AreEqual (3, v.RecursiveUpgradeCount);
519 public void RecursiveReadPropertiesTest ()
521 var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
526 Assert.AreEqual (true, v.IsReadLockHeld, "#1a");
527 Assert.AreEqual (1, v.CurrentReadCount, "#2a");
528 Assert.AreEqual (2, v.RecursiveReadCount, "#3a");
531 int cReadCount = -1, rReadCount = -1;
533 Thread t = new Thread ((_) => {
534 rLock = v.IsReadLockHeld;
535 cReadCount = v.CurrentReadCount;
536 rReadCount = v.RecursiveReadCount;
542 Assert.AreEqual (false, rLock, "#1b");
543 Assert.AreEqual (1, cReadCount, "#2b");
544 Assert.AreEqual (0, rReadCount, "#3b");
548 public void RecursiveUpgradePropertiesTest ()
550 var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
552 v.EnterUpgradeableReadLock ();
553 v.EnterUpgradeableReadLock ();
555 Assert.AreEqual (true, v.IsUpgradeableReadLockHeld, "#1a");
556 Assert.AreEqual (false, v.IsReadLockHeld, "#11a");
557 Assert.AreEqual (0, v.CurrentReadCount, "#2a");
558 Assert.AreEqual (2, v.RecursiveUpgradeCount, "#3a");
560 bool upLock = false, rLock = false;
561 int rCount = -1, rUCount = -1;
563 Thread t = new Thread ((_) => {
564 upLock = v.IsUpgradeableReadLockHeld;
565 rLock = v.IsReadLockHeld;
566 rCount = v.CurrentReadCount;
567 rUCount = v.RecursiveUpgradeCount;
573 Assert.AreEqual (false, upLock, "#1b");
574 Assert.AreEqual (false, rLock, "#11b");
575 Assert.AreEqual (0, rCount, "#2b");
576 Assert.AreEqual (0, rUCount, "#3b");
580 public void RecursiveWritePropertiesTest ()
582 var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
587 Assert.AreEqual (true, v.IsWriteLockHeld, "#1a");
588 Assert.AreEqual (2, v.RecursiveWriteCount, "#3a");
593 Thread t = new Thread ((_) => {
594 wLock = v.IsWriteLockHeld;
595 rWrite = v.RecursiveWriteCount;
601 Assert.AreEqual (false, wLock, "#1b");
602 Assert.AreEqual (0, rWrite, "#3b");
606 public void RecursiveEnterExitReadTest ()
608 var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
614 Assert.IsTrue (v.IsReadLockHeld);
615 Assert.AreEqual (3, v.RecursiveReadCount);
619 Assert.IsTrue (v.IsReadLockHeld);
620 Assert.AreEqual (2, v.RecursiveReadCount);
624 public void RecursiveEnterExitWriteTest ()
626 var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
632 Assert.IsTrue (v.IsWriteLockHeld);
633 Assert.AreEqual (3, v.RecursiveWriteCount);
638 Assert.IsTrue (v.IsWriteLockHeld);
639 Assert.AreEqual (1, v.RecursiveWriteCount);
643 public void RecursiveEnterExitUpgradableTest ()
645 var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
647 v.EnterUpgradeableReadLock ();
648 v.EnterUpgradeableReadLock ();
649 v.EnterUpgradeableReadLock ();
651 Assert.IsTrue (v.IsUpgradeableReadLockHeld);
652 Assert.AreEqual (3, v.RecursiveUpgradeCount);
654 v.ExitUpgradeableReadLock ();
656 Assert.IsTrue (v.IsUpgradeableReadLockHeld);
657 Assert.AreEqual (2, v.RecursiveUpgradeCount);
661 public void RecursiveWriteUpgradeReadTest ()
663 var rwlock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
665 rwlock.EnterWriteLock ();
666 Assert.IsTrue (rwlock.IsWriteLockHeld);
667 rwlock.EnterUpgradeableReadLock ();
668 Assert.IsTrue (rwlock.IsUpgradeableReadLockHeld);
669 rwlock.EnterReadLock ();
670 Assert.IsTrue (rwlock.IsReadLockHeld);
671 rwlock.ExitUpgradeableReadLock();
672 Assert.IsFalse (rwlock.IsUpgradeableReadLockHeld);
673 Assert.IsTrue (rwlock.IsReadLockHeld);
674 Assert.IsTrue (rwlock.IsWriteLockHeld);
676 rwlock.ExitReadLock ();
677 Assert.IsTrue (rwlock.IsWriteLockHeld);
681 public void RecursiveWriteUpgradeTest ()
683 ReaderWriterLockSlim rwlock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
685 rwlock.EnterWriteLock ();
686 Assert.IsTrue (rwlock.IsWriteLockHeld);
687 rwlock.EnterUpgradeableReadLock ();
688 Assert.IsTrue (rwlock.IsUpgradeableReadLockHeld);
689 rwlock.ExitUpgradeableReadLock ();
690 Assert.IsFalse (rwlock.IsUpgradeableReadLockHeld);
691 Assert.IsTrue (rwlock.IsWriteLockHeld);
692 rwlock.ExitWriteLock ();
693 Assert.IsFalse (rwlock.IsWriteLockHeld);
694 rwlock.EnterWriteLock ();
695 Assert.IsTrue (rwlock.IsWriteLockHeld);
699 public void RecursiveWriteReadAcquisitionInterleaving ()
701 var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
704 Assert.IsTrue (v.IsWriteLockHeld, "#1");
707 var t = new Thread (delegate () {
708 result = v.TryEnterReadLock (100);
712 Assert.IsFalse (result, "#2");
715 t = new Thread (delegate () {
716 result = v.TryEnterReadLock (100);
720 Assert.IsTrue (result, "#3");