コード例 #1
0
 public void CannotWriteWhileWriting()
 {
     using (var x = new ReadWriteLock())
     {
         var ok         = true;
         var doneThread = false;
         using (x.EnterWrite())
         {
             Assert.IsTrue(x.IsCurrentThreadWriter);
             var a = new Thread
                     (
                 () =>
             {
                 IDisposable engagement = null;
                 try
                 {
                     ok &= !x.TryEnterWrite(out engagement);
                 }
                 finally
                 {
                     if (engagement != null)
                     {
                         engagement.Dispose();
                     }
                     doneThread = true;
                 }
             }
                     );
             a.Start();
             a.Join();
         }
         Assert.IsTrue(ok);
         Assert.IsTrue(doneThread);
     }
 }
コード例 #2
0
 public void CanKnowIsWriter()
 {
     // ReadWriteLock always able to tell if a therad is the writer
     using (var x = new ReadWriteLock(true))
     {
         Assert.IsFalse(x.HasWriter);
         using (x.EnterWrite())
         {
             Assert.IsTrue(x.IsCurrentThreadWriter);
             Assert.IsTrue(x.HasWriter);
         }
         // Not Reentrant ReadWriteLock is not
         using (var y = new ReadWriteLock(false))
         {
             Assert.IsFalse(y.HasWriter);
             using (y.EnterWrite())
             {
                 Assert.IsTrue(y.IsCurrentThreadWriter);
                 Assert.IsTrue(y.HasWriter);
             }
             // ReadWriteLock is not reentrant by default
             using (var z = new ReadWriteLock())
             {
                 Assert.IsFalse(z.HasWriter);
                 using (z.EnterWrite())
                 {
                     Assert.IsTrue(z.IsCurrentThreadWriter);
                     Assert.IsTrue(z.HasWriter);
                 }
             }
         }
     }
 }
コード例 #3
0
 public void ReentryReadToWriteRaceCondition()
 {
     using (var w = new ManualResetEvent(false))
     {
         using (var x = new ReadWriteLock(true))
         {
             var         enterCount   = 0;
             var         doneCount    = 0;
             var         errorCount   = 0;
             var         successCount = 0;
             ThreadStart tmp          = () =>
             {
                 using (x.EnterRead())
                 {
                     Interlocked.Increment(ref enterCount);
                     w.WaitOne();
                     // If a thread is a reader it can become a writer as long as there are no other readers
                     // When we have multiple readers trying to become a writer...
                     try
                     {
                         // write mode is requested and reserved by one thread - others fail
                         using (x.EnterWrite())
                         {
                             Interlocked.Increment(ref successCount);
                         }
                     }
                     catch (InvalidOperationException)
                     {
                         Interlocked.Increment(ref errorCount);
                     }
                 }
                 Interlocked.Increment(ref doneCount);
             };
             var threads = new Thread[5];
             for (var index = 0; index < 5; index++)
             {
                 threads[index] = new Thread(tmp);
             }
             for (var index = 0; index < 5; index++)
             {
                 threads[index].Start();
             }
             do
             {
                 Thread.Sleep(10);
             } while (enterCount < 5);
             w.Set();
             for (var index = 0; index < 5; index++)
             {
                 threads[index].Join();
             }
             Assert.AreEqual(5, doneCount);
             Assert.AreEqual(1, successCount); // One succeds - the thread that succeds to reserve write waits for others to leave
             Assert.AreEqual(4, errorCount);   // The others get InvalidOperationException - the threads that fail the reserve fail
         } // This code results in a dead lock in a not reentrant ReadWriteLock
     }
 }
コード例 #4
0
        public void CanEnterWrite()
        {
            var x = new ReadWriteLock();

            using (x.EnterWrite())
            {
                Assert.IsTrue(x.IsCurrentThreadWriter);
            }
        }
コード例 #5
0
 public void WriteWaitsMultipleReadsToFinish() // TODO: Review
 {
     using (var w0 = new ManualResetEvent(false))
     {
         using (var w1 = new ManualResetEvent(false))
         {
             using (var x = new ReadWriteLock())
             {
                 var   ok      = false;
                 int[] z       = { 0 };
                 var   threads = new Thread[5];
                 for (var index = 0; index < 5; index++)
                 {
                     threads[index] = new Thread
                                      (
                         () =>
                     {
                         w0.WaitOne();
                         using (x.EnterRead())
                         {
                             w1.Set();
                             Interlocked.Increment(ref z[0]);
                             Thread.Sleep(10);
                         }
                     }
                                      );
                 }
                 var a = new Thread
                         (
                     () =>
                 {
                     w1.WaitOne();
                     using (x.EnterWrite())
                     {
                         Assert.IsTrue(x.IsCurrentThreadWriter);
                         ok = Interlocked.Increment(ref z[0]) == 6;
                     }
                 }
                         );
                 for (var index = 0; index < 5; index++)
                 {
                     threads[index].Start();
                 }
                 a.Start();
                 w0.Set();
                 for (var index = 0; index < 5; index++)
                 {
                     threads[index].Join();
                 }
                 a.Join();
                 Assert.IsTrue(ok);
                 Assert.AreEqual(7, Interlocked.Increment(ref z[0]));
             }
         }
     }
 }
コード例 #6
0
        public void CanReentryWriteToRead()
        {
            var x = new ReadWriteLock();

            using (x.EnterWrite())
            {
                // If a thread is a writer it can be also a reader
                using (x.EnterRead())
                {
                }
            }
        }
コード例 #7
0
 public void CannotReentryReadToWriteWhenThereAreMoreReaders()
 {
     using (var w1 = new ManualResetEvent(false))
     {
         using (var w2 = new ManualResetEvent(false))
         {
             using (var x = new ReadWriteLock(true))
             {
                 var ok = true;
                 var a  = new Thread
                          (
                     () =>
                 {
                     using (x.EnterRead())
                     {
                         w2.Set();
                         w1.WaitOne();
                     }
                 }
                          );
                 a.Start();
                 w2.WaitOne();
                 using (x.EnterRead())
                 {
                     Assert.IsFalse(x.IsCurrentThreadWriter);
                     IDisposable engagement = null;
                     try
                     {
                         ok &= !x.TryEnterWrite(out engagement);
                     }
                     finally
                     {
                         if (engagement != null)
                         {
                             engagement.Dispose();
                         }
                     }
                 }
                 w1.Set();
                 a.Join();
                 using (x.EnterRead())
                 {
                     using (x.EnterWrite())
                     {
                         Assert.IsTrue(x.IsCurrentThreadWriter);
                         Assert.IsTrue(ok);
                     }
                 }
             } // This code results in a dead lock in a not reentrant ReadWriteLock
         }
     }
 }
コード例 #8
0
        public void CanReentryReadToWrite()
        {
            var x = new ReadWriteLock(true); // This code results in a dead lock in a not reentrant ReadWriteLock

            using (x.EnterRead())
            {
                Assert.IsFalse(x.IsCurrentThreadWriter);
                // If a thread is a reader it can become a writer as long as there are no other readers
                using (x.EnterWrite())
                {
                    Assert.IsTrue(x.IsCurrentThreadWriter);
                }
            }
        }
コード例 #9
0
 public void WriteWaitsReadToFinish()
 {
     using (var w = new ManualResetEvent(false))
     {
         using (var x = new ReadWriteLock())
         {
             int[] z  = { 0 };
             var   ok = true;
             var   a  = new Thread
                        (
                 () =>
             {
                 w.WaitOne();
                 using (x.EnterWrite())
                 {
                     ok = ok && Interlocked.Increment(ref z[0]) == 2;
                 }
             }
                        );
             var b = new Thread
                     (
                 () =>
             {
                 using (x.EnterRead())
                 {
                     w.Set();
                     Thread.Sleep(10);
                     ok = ok && Interlocked.Increment(ref z[0]) == 1;
                 }
             }
                     );
             a.Start();
             b.Start();
             a.Join();
             b.Join();
             Assert.IsTrue(ok);
             Assert.AreEqual(3, Interlocked.Increment(ref z[0]));
         }
     }
 }
コード例 #10
0
 public void OnlyOneWriterAtTheTime()
 {
     using (var w = new ManualResetEvent(false))
     {
         using (var x = new ReadWriteLock())
         {
             int[] z       = { 0 };
             var   ok      = true;
             var   threads = new Thread[5];
             for (var index = 0; index < 5; index++)
             {
                 threads[index] = new Thread
                                  (
                     () =>
                 {
                     w.WaitOne();
                     using (x.EnterWrite())
                     {
                         var got = Interlocked.Increment(ref z[0]);
                         Thread.Sleep(10);
                         ok = ok && Interlocked.Increment(ref z[0]) == got + 1;
                     }
                 }
                                  );
             }
             for (var index = 0; index < 5; index++)
             {
                 threads[index].Start();
             }
             w.Set();
             for (var index = 0; index < 5; index++)
             {
                 threads[index].Join();
             }
             Assert.IsTrue(ok);
             Assert.AreEqual(11, Interlocked.Increment(ref z[0]));
         }
     }
 }
コード例 #11
0
 public void OnlyOneWriterAtTheTimeEx() // TODO: Review - race condition
 {
     using (var w = new ManualResetEvent(false))
     {
         using (var x = new ReadWriteLock())
         {
             var         doneThread = 0;
             var         ok         = true;
             ThreadStart tmp        = () =>
             {
                 w.WaitOne();
                 IDisposable engagementA = null;
                 try
                 {
                     ok &= !x.TryEnterWrite(out engagementA);
                 }
                 finally
                 {
                     if (engagementA != null)
                     {
                         engagementA.Dispose();
                     }
                     Interlocked.Increment(ref doneThread);
                 }
             };
             var a = new Thread(tmp);
             using (x.EnterWrite())
             {
                 a.Start();
                 w.Set();
                 Thread.Sleep(10);
             }
             a.Join();
             Assert.IsTrue(ok);
             Assert.AreEqual(1, doneThread);
             var         b           = new Thread(tmp);
             IDisposable engagementB = null;
             try
             {
                 if (x.TryEnterWrite(out engagementB))
                 {
                     Assert.IsTrue(x.IsCurrentThreadWriter);
                     b.Start();
                     w.Set();
                     b.Join();
                 }
                 else
                 {
                     Assert.Fail();
                 }
             }
             finally
             {
                 if (engagementB != null)
                 {
                     engagementB.Dispose();
                 }
             }
             Assert.IsTrue(ok);
             Assert.AreEqual(2, doneThread);
         }
     }
 }
コード例 #12
0
 public void WriteWaitsMultipleReadsToFinish()
 {
     using (var w0 = new ManualResetEvent(false))
     {
         using (var w1 = new ManualResetEvent(false))
         {
             using (var x = new ReadWriteLock())
             {
                 int[] z            = { 0, 0 };
                 var   foundReaders = -1;
                 var   ok           = false;
                 var   threads      = new Thread[5];
                 for (var index = 0; index < 5; index++)
                 {
                     threads[index] = new Thread
                                      (
                         () =>
                     {
                         w0.WaitOne();
                         using (x.EnterRead())
                         {
                             Interlocked.Increment(ref z[1]);
                             w1.Set();
                             Interlocked.Increment(ref z[0]);
                             Thread.Sleep(10);
                             Interlocked.Decrement(ref z[1]);
                         }
                     }
                                      );
                 }
                 var a = new Thread
                         (
                     () =>
                 {
                     w1.WaitOne();
                     using (x.EnterWrite())
                     {
                         foundReaders = Volatile.Read(ref z[1]);
                         ok           = x.IsCurrentThreadWriter;
                         Interlocked.Increment(ref z[0]);
                     }
                 }
                         );
                 for (var index = 0; index < 5; index++)
                 {
                     threads[index].Start();
                 }
                 a.Start();
                 w0.Set();
                 for (var index = 0; index < 5; index++)
                 {
                     threads[index].Join();
                 }
                 a.Join();
                 Assert.IsTrue(ok);
                 Assert.AreEqual(0, foundReaders);
                 Assert.AreEqual(7, Interlocked.Increment(ref z[0]));
             }
         }
     }
 }