System.Drawing: added email to icon and test file headers
[mono.git] / mcs / class / System.Core / Test / System.Threading / ReaderWriterLockSlimTest.cs
1 //
2 // ReaderWriterLockSlimTest.cs
3 //
4 // Authors:
5 //      Marek Safar (marek.safar@gmail.com)
6 //
7 // Copyright (C) 2009 Novell, Inc (http://www.novell.com)
8 //
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:
16 //
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 //
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.
27 //
28
29 using System;
30 using NUnit.Framework;
31 using System.Threading;
32 using System.Threading.Tasks;
33 using System.Linq;
34
35 namespace MonoTests.System.Threading
36 {
37         [TestFixture]
38         public class ReaderWriterLockSlimTests
39         {
40                 [Test]
41                 public void DefaultValues ()
42                 {
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");
55                 }
56
57                 [Test]
58                 public void Dispose_Errors ()
59                 {
60                         var v = new ReaderWriterLockSlim ();
61                         v.Dispose ();
62
63                         try {
64                                 v.EnterUpgradeableReadLock ();
65                                 Assert.Fail ("1");
66                         } catch (ObjectDisposedException) {
67                         }
68
69                         try {
70                                 v.EnterReadLock ();
71                                 Assert.Fail ("2");
72                         } catch (ObjectDisposedException) {
73                         }
74
75                         try {
76                                 v.EnterWriteLock ();
77                                 Assert.Fail ("3");
78                         } catch (ObjectDisposedException) {
79                         }
80                 }
81
82                 [Test]
83                 public void TryEnterReadLock_OutOfRange ()
84                 {
85                         var v = new ReaderWriterLockSlim ();
86                         try {
87                                 v.TryEnterReadLock (-2);
88                                 Assert.Fail ("1");
89                         } catch (ArgumentOutOfRangeException) {
90                         }
91
92                         try {
93                                 v.TryEnterReadLock (TimeSpan.MaxValue);
94                                 Assert.Fail ("2");
95                         } catch (ArgumentOutOfRangeException) {
96                         }
97
98                         try {
99                                 v.TryEnterReadLock (TimeSpan.MinValue);
100                                 Assert.Fail ("3");
101                         } catch (ArgumentOutOfRangeException) {
102                         }
103                 }
104
105                 [Test]
106                 public void TryEnterUpgradeableReadLock_OutOfRange ()
107                 {
108                         var v = new ReaderWriterLockSlim ();
109                         try {
110                                 v.TryEnterUpgradeableReadLock (-2);
111                                 Assert.Fail ("1");
112                         } catch (ArgumentOutOfRangeException) {
113                         }
114
115                         try {
116                                 v.TryEnterUpgradeableReadLock (TimeSpan.MaxValue);
117                                 Assert.Fail ("2");
118                         } catch (ArgumentOutOfRangeException) {
119                         }
120
121                         try {
122                                 v.TryEnterUpgradeableReadLock (TimeSpan.MinValue);
123                                 Assert.Fail ("3");
124                         } catch (ArgumentOutOfRangeException) {
125                         }
126                 }
127
128                 [Test]
129                 public void TryEnterWriteLock_OutOfRange ()
130                 {
131                         var v = new ReaderWriterLockSlim ();
132                         try {
133                                 v.TryEnterWriteLock (-2);
134                                 Assert.Fail ("1");
135                         } catch (ArgumentOutOfRangeException) {
136                         }
137
138                         try {
139                                 v.TryEnterWriteLock (TimeSpan.MaxValue);
140                                 Assert.Fail ("2");
141                         } catch (ArgumentOutOfRangeException) {
142                         }
143
144                         try {
145                                 v.TryEnterWriteLock (TimeSpan.MinValue);
146                                 Assert.Fail ("3");
147                         } catch (ArgumentOutOfRangeException) {
148                         }
149                 }
150
151                 [Test, ExpectedException (typeof (SynchronizationLockException))]
152                 public void ExitReadLock ()
153                 {
154                         var v = new ReaderWriterLockSlim ();
155                         v.ExitReadLock ();
156                 }
157
158                 [Test, ExpectedException (typeof (SynchronizationLockException))]
159                 public void ExitWriteLock ()
160                 {
161                         var v = new ReaderWriterLockSlim ();
162                         v.ExitWriteLock ();
163                 }
164
165                 [Test]
166                 public void EnterReadLock_NoRecursionError ()
167                 {
168                         var v = new ReaderWriterLockSlim ();
169                         v.EnterReadLock ();
170                         Assert.AreEqual (1, v.RecursiveReadCount);
171
172                         try {
173                                 v.EnterReadLock ();
174                                 Assert.Fail ("1");
175                         } catch (LockRecursionException) {
176                         }
177
178                         try {
179                                 v.EnterWriteLock ();
180                                 Assert.Fail ("2");
181                         } catch (LockRecursionException) {
182                         }
183                 }
184
185                 [Test]
186                 public void EnterReadLock ()
187                 {
188                         var v = new ReaderWriterLockSlim ();
189
190                         v.EnterReadLock ();
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");
198                         v.ExitReadLock ();
199
200                         v.EnterReadLock ();
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");
208                         v.ExitReadLock ();
209                 }
210
211                 [Test]
212                 public void EnterWriteLock_NoRecursionError ()
213                 {
214                         var v = new ReaderWriterLockSlim ();
215                         v.EnterWriteLock ();
216                         Assert.AreEqual (1, v.RecursiveWriteCount);
217
218                         try {
219                                 v.EnterWriteLock ();
220                                 Assert.Fail ("1");
221                         } catch (LockRecursionException) {
222                         }
223
224                         try {
225                                 v.EnterReadLock ();
226                                 Assert.Fail ("2");
227                         } catch (LockRecursionException) {
228                         }
229                 }
230
231                 [Test]
232                 public void EnterWriteLock ()
233                 {
234                         var v = new ReaderWriterLockSlim ();
235
236                         v.EnterWriteLock ();
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");
244                         v.ExitWriteLock ();
245
246                         v.EnterWriteLock ();
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");
254                         v.ExitWriteLock ();
255                 }
256
257                 [Test]
258                 public void EnterUpgradeableReadLock_NoRecursionError ()
259                 {
260                         var v = new ReaderWriterLockSlim ();
261                         v.EnterUpgradeableReadLock ();
262                         Assert.AreEqual (1, v.RecursiveUpgradeCount);
263
264                         try {
265                                 v.EnterUpgradeableReadLock ();
266                                 Assert.Fail ("2");
267                         } catch (LockRecursionException) {
268                         }
269                 }
270
271                 [Test]
272                 public void EnterUpgradeableReadLock ()
273                 {
274                         var v = new ReaderWriterLockSlim ();
275
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 ();
285
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");
294
295                         v.EnterReadLock ();
296                         v.ExitUpgradeableReadLock ();
297
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");
305
306                         v.ExitReadLock ();
307                 }
308
309                 [Test]
310                 public void EnterReadLock_MultiRead ()
311                 {
312                         var v = new ReaderWriterLockSlim ();
313                         int local = 10;
314
315                         var r = from i in Enumerable.Range (1, 30) select new Thread (() => {
316
317                                 // Just to cause some contention
318                                 Thread.Sleep (100);
319
320                                 v.EnterReadLock ();
321
322                                 Assert.AreEqual (10, local);
323                         });
324
325                         var threads = r.ToList ();
326
327                         foreach (var t in threads) {
328                                 t.Start ();
329                         }
330
331                         foreach (var t in threads) {
332                                 // Console.WriteLine (t.ThreadState);
333                                 t.Join ();
334                         }
335                 }
336
337                 [Test]
338                 public void TryEnterWriteLock_WhileReading ()
339                 {
340                         var v = new ReaderWriterLockSlim ();
341                         AutoResetEvent ev = new AutoResetEvent (false);
342                         AutoResetEvent ev2 = new AutoResetEvent (false);
343
344                         Thread t1 = new Thread (() => {
345                                 v.EnterReadLock ();
346                                 ev2.Set ();
347                                 ev.WaitOne ();
348                                 v.ExitReadLock ();
349                         });
350
351                         t1.Start ();
352                         ev2.WaitOne ();
353
354                         Assert.IsFalse (v.TryEnterWriteLock (100));
355                         ev.Set ();
356                         t1.Join ();
357
358                         Assert.IsTrue (v.TryEnterWriteLock (100));
359                 }
360
361                 [Test]
362                 public void EnterWriteLock_MultiRead ()
363                 {
364                         var v = new ReaderWriterLockSlim ();
365                         int local = 10;
366
367                         var r = from i in Enumerable.Range (1, 10) select new Thread (() => {
368                                 v.EnterReadLock ();
369
370                                 Assert.AreEqual (11, local);
371                         });
372
373                         v.EnterWriteLock ();
374
375                         var threads = r.ToList ();
376                         foreach (var t in threads) {
377                                 t.Start ();
378                         }
379
380                         Thread.Sleep (200);
381                         local = 11;
382
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");
387                         v.ExitWriteLock ();
388
389                         foreach (var t in threads) {
390                                 // Console.WriteLine (t.ThreadState);
391                                 t.Join ();
392                         }
393                 }
394
395                 [Test]
396                 public void EnterWriteLock_After_ExitUpgradeableReadLock ()
397                 {
398                         var v = new ReaderWriterLockSlim ();
399
400                         v.EnterUpgradeableReadLock ();
401                         Assert.IsTrue (v.TryEnterWriteLock (100));
402                         v.ExitWriteLock ();
403                         v.ExitUpgradeableReadLock ();
404                         Assert.IsTrue (v.TryEnterWriteLock (100));
405                         v.ExitWriteLock ();
406                 }
407 #if NET_4_0
408                 [Test]
409                 public void EnterWriteLockWhileInUpgradeAndOtherWaiting ()
410                 {
411                         var v = new ReaderWriterLockSlim ();
412
413                         var task2 = new Task(() => {
414                 v.EnterWriteLock();
415                 v.ExitWriteLock();
416             });
417
418             var task1 = new Task(() =>
419             {
420                 v.EnterUpgradeableReadLock ();
421                 task2.Start ();
422                 Thread.Sleep (100);
423                 v.EnterWriteLock ();
424                 v.ExitWriteLock ();
425                 v.ExitUpgradeableReadLock ();
426             });
427             task1.Start ();
428
429             Assert.IsTrue (task1.Wait (500));
430                 }
431 #endif
432                 [Test]
433                 public void RecursiveReadLockTest ()
434                 {
435                         var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
436
437                         Assert.IsTrue (v.TryEnterReadLock (100), "#1");
438                         Assert.IsTrue (v.TryEnterReadLock (100), "#2");
439                         Assert.IsTrue (v.TryEnterReadLock (100), "#3");
440
441                         Assert.AreEqual (3, v.RecursiveReadCount);
442                 }
443
444                 [Test]
445                 public void RecursiveReadPlusWriteLockTest ()
446                 {
447                         var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
448
449                         try {
450                                 v.EnterReadLock ();
451                                 v.EnterWriteLock ();
452                                 Assert.Fail ("1");
453                         } catch (LockRecursionException ex) {
454                                 Assert.IsNotNull (ex, "#1");
455                         }
456                 }
457
458                 [Test]
459                 public void RecursiveReadPlusUpgradeableLockTest ()
460                 {
461                         var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
462
463                         try {
464                                 v.EnterReadLock ();
465                                 v.EnterUpgradeableReadLock ();
466                                 Assert.Fail ("1");
467                         } catch (LockRecursionException ex) {
468                                 Assert.IsNotNull (ex, "#1");
469                         }
470                 }
471
472                 [Test]
473                 public void RecursiveWriteLockTest ()
474                 {
475                         var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
476
477                         Assert.IsTrue (v.TryEnterWriteLock (100), "#1");
478                         Assert.IsTrue (v.TryEnterWriteLock (100), "#2");
479                         Assert.IsTrue (v.TryEnterWriteLock (100), "#3");
480
481                         Assert.AreEqual (3, v.RecursiveWriteCount);
482                 }
483
484                 [Test]
485                 public void RecursiveWritePlusReadLockTest ()
486                 {
487                         var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
488
489                         Assert.IsTrue (v.TryEnterWriteLock (100), "#1");
490                         Assert.AreEqual (1, v.RecursiveWriteCount, "1b");
491                         Assert.AreEqual (0, v.RecursiveReadCount, "1c");
492
493                         Assert.IsTrue (v.TryEnterReadLock (100), "#2");
494                         Assert.AreEqual (1, v.RecursiveWriteCount, "2b");
495                         Assert.AreEqual (1, v.RecursiveReadCount, "2c");
496
497                         Assert.IsTrue (v.TryEnterReadLock (100), "#3");
498                         Assert.AreEqual (1, v.RecursiveWriteCount, "3b");
499                         Assert.AreEqual (2, v.RecursiveReadCount, "3c");
500
501                         v.ExitReadLock ();
502                         Assert.AreEqual (1, v.RecursiveWriteCount, "4b");
503                         Assert.AreEqual (1, v.RecursiveReadCount, "4c");
504                 }
505
506                 [Test]
507                 public void RecursiveUpgradeableReadLockTest ()
508                 {
509                         var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
510
511                         Assert.IsTrue (v.TryEnterUpgradeableReadLock (100), "#1");
512                         Assert.IsTrue (v.TryEnterUpgradeableReadLock (100), "#2");
513                         Assert.IsTrue (v.TryEnterUpgradeableReadLock (100), "#3");
514
515                         Assert.AreEqual (3, v.RecursiveUpgradeCount);
516                 }
517
518                 [Test]
519                 public void RecursiveReadPropertiesTest ()
520                 {
521                         var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
522
523                         v.EnterReadLock ();
524                         v.EnterReadLock ();
525
526                         Assert.AreEqual (true, v.IsReadLockHeld, "#1a");
527                         Assert.AreEqual (1, v.CurrentReadCount, "#2a");
528                         Assert.AreEqual (2, v.RecursiveReadCount, "#3a");
529
530                         bool rLock = true;
531                         int cReadCount = -1, rReadCount = -1;
532
533                         Thread t = new Thread ((_) => {
534                                         rLock = v.IsReadLockHeld;
535                                         cReadCount = v.CurrentReadCount;
536                                         rReadCount = v.RecursiveReadCount;
537                                 });
538
539                         t.Start ();
540                         t.Join ();
541
542                         Assert.AreEqual (false, rLock, "#1b");
543                         Assert.AreEqual (1, cReadCount, "#2b");
544                         Assert.AreEqual (0, rReadCount, "#3b");
545                 }
546
547                 [Test]
548                 public void RecursiveUpgradePropertiesTest ()
549                 {
550                         var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
551
552                         v.EnterUpgradeableReadLock ();
553                         v.EnterUpgradeableReadLock ();
554
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");
559
560                         bool upLock = false, rLock = false;
561                         int rCount = -1, rUCount = -1;
562
563                         Thread t = new Thread ((_) => {
564                                         upLock = v.IsUpgradeableReadLockHeld;
565                                         rLock = v.IsReadLockHeld;
566                                         rCount = v.CurrentReadCount;
567                                         rUCount = v.RecursiveUpgradeCount;
568                                 });
569
570                         t.Start ();
571                         t.Join ();
572
573                         Assert.AreEqual (false, upLock, "#1b");
574                         Assert.AreEqual (false, rLock, "#11b");
575                         Assert.AreEqual (0, rCount, "#2b");
576                         Assert.AreEqual (0, rUCount, "#3b");
577                 }
578
579                 [Test]
580                 public void RecursiveWritePropertiesTest ()
581                 {
582                         var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
583
584                         v.EnterWriteLock ();
585                         v.EnterWriteLock ();
586
587                         Assert.AreEqual (true, v.IsWriteLockHeld, "#1a");
588                         Assert.AreEqual (2, v.RecursiveWriteCount, "#3a");
589
590                         bool wLock = false;
591                         int rWrite = -1;
592
593                         Thread t = new Thread ((_) => {
594                                         wLock = v.IsWriteLockHeld;
595                                         rWrite = v.RecursiveWriteCount;
596                                 });
597
598                         t.Start ();
599                         t.Join ();
600
601                         Assert.AreEqual (false, wLock, "#1b");
602                         Assert.AreEqual (0, rWrite, "#3b");
603                 }
604
605                 [Test]
606                 public void RecursiveEnterExitReadTest ()
607                 {
608                         var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
609
610                         v.EnterReadLock ();
611                         v.EnterReadLock ();
612                         v.EnterReadLock ();
613
614                         Assert.IsTrue (v.IsReadLockHeld);
615                         Assert.AreEqual (3, v.RecursiveReadCount);
616
617                         v.ExitReadLock ();
618
619                         Assert.IsTrue (v.IsReadLockHeld);
620                         Assert.AreEqual (2, v.RecursiveReadCount);
621                 }
622
623                 [Test]
624                 public void RecursiveEnterExitWriteTest ()
625                 {
626                         var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
627
628                         v.EnterWriteLock ();
629                         v.EnterWriteLock ();
630                         v.EnterWriteLock ();
631
632                         Assert.IsTrue (v.IsWriteLockHeld);
633                         Assert.AreEqual (3, v.RecursiveWriteCount);
634
635                         v.ExitWriteLock ();
636                         v.ExitWriteLock ();
637
638                         Assert.IsTrue (v.IsWriteLockHeld);
639                         Assert.AreEqual (1, v.RecursiveWriteCount);
640                 }
641
642                 [Test]
643                 public void RecursiveEnterExitUpgradableTest ()
644                 {
645                         var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
646
647                         v.EnterUpgradeableReadLock ();
648                         v.EnterUpgradeableReadLock ();
649                         v.EnterUpgradeableReadLock ();
650
651                         Assert.IsTrue (v.IsUpgradeableReadLockHeld);
652                         Assert.AreEqual (3, v.RecursiveUpgradeCount);
653
654                         v.ExitUpgradeableReadLock ();
655
656                         Assert.IsTrue (v.IsUpgradeableReadLockHeld);
657                         Assert.AreEqual (2, v.RecursiveUpgradeCount);
658                 }
659
660                 [Test]
661                 public void RecursiveWriteUpgradeReadTest ()
662                 {
663                         var rwlock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
664
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);
675
676                         rwlock.ExitReadLock ();
677                         Assert.IsTrue (rwlock.IsWriteLockHeld);
678                 }
679
680                 [Test]
681                 public void RecursiveWriteUpgradeTest ()
682                 {
683                         ReaderWriterLockSlim rwlock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
684
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);
696                 }
697
698                 [Test]
699                 public void RecursiveWriteReadAcquisitionInterleaving ()
700                 {
701                         var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
702
703                         v.EnterWriteLock ();
704                         Assert.IsTrue (v.IsWriteLockHeld, "#1");
705
706                         bool result = true;
707                         var t = new Thread (delegate () {
708                                         result = v.TryEnterReadLock (100);
709                                 });
710                         t.Start ();
711                         t.Join ();
712                         Assert.IsFalse (result, "#2");
713
714                         v.ExitWriteLock ();
715                         t = new Thread (delegate () {
716                                         result = v.TryEnterReadLock (100);
717                                 });
718                         t.Start ();
719                         t.Join ();
720                         Assert.IsTrue (result, "#3");
721                 }
722         }
723 }