コード例 #1
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
         }
     }
 }
コード例 #2
0
        public void CanReentryReadToRead()
        {
            var x = new ReadWriteLock();

            using (x.EnterRead())
            {
                Assert.IsFalse(x.IsCurrentThreadWriter);
                using (x.EnterRead())
                {
                    Assert.IsFalse(x.IsCurrentThreadWriter);
                }
            }
        }
コード例 #3
0
 public void CanKnowIsReader()
 {
     // Reentrant ReadWriteLock is able to tell if a therad is a reader
     using (var x = new ReadWriteLock(true))
     {
         Assert.IsFalse(x.HasReader);
         using (x.EnterRead())
         {
             Assert.IsTrue(x.IsCurrentThreadReader);
             Assert.IsTrue(x.HasReader);
         }
         // Not Reentrant ReadWriteLock is not
         using (var y = new ReadWriteLock(false))
         {
             Assert.IsFalse(y.HasReader);
             using (y.EnterRead())
             {
                 Assert.Throws(typeof(NotSupportedException), () => GC.KeepAlive(y.IsCurrentThreadReader));
                 Assert.IsTrue(y.HasReader);
             }
             // ReadWriteLock is not reentrant by default
             using (var z = new ReadWriteLock())
             {
                 Assert.IsFalse(z.HasReader);
                 using (z.EnterRead())
                 {
                     Assert.Throws(typeof(NotSupportedException), () => GC.KeepAlive(z.IsCurrentThreadReader));
                     Assert.IsTrue(z.HasReader);
                 }
             }
         }
     }
 }
コード例 #4
0
 public void CannotWriteWhileReading()
 {
     using (var x = new ReadWriteLock())
     {
         var ok         = true;
         var doneThread = false;
         using (x.EnterRead())
         {
             Assert.IsFalse(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);
     }
 }
コード例 #5
0
        public void ReentryReadToWriteCheck()
        {
            var         w            = new ManualResetEvent(false);
            var         x            = new ReadWriteLock();
            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...
                    IDisposable engagement = null;
                    try
                    {
                        // Write mode is not requested - there are other readers which we don't wait to leave
                        if (x.TryEnterWrite(out engagement))
                        {
                            Interlocked.Increment(ref successCount);
                        }
                        else
                        {
                            Interlocked.Increment(ref errorCount);
                        }
                    }
                    finally
                    {
                        if (engagement != null)
                        {
                            engagement.Dispose();
                        }
                    }
                }
                Interlocked.Increment(ref doneCount);
            };
            var threads = new Thread[5];

            for (int index = 0; index < 5; index++)
            {
                threads[index] = new Thread(tmp);
            }
            for (int index = 0; index < 5; index++)
            {
                threads[index].Start();
            }
            Thread.Sleep(10);
            Assert.AreEqual(5, enterCount);
            w.Set();
            for (int index = 0; index < 5; index++)
            {
                threads[index].Join();
            }
            Assert.AreEqual(5, doneCount);
            Assert.AreEqual(0, successCount); // None succeds
            Assert.AreEqual(5, errorCount);   // All fail
        }
コード例 #6
0
        public void MultipleReadersAtTheTime()
        {
            var w = new ManualResetEvent(false);
            var x = new ReadWriteLock();

            int[] z       = { 0 };
            var   threads = new Thread[5];

            for (int index = 0; index < 5; index++)
            {
                threads[index] = new Thread
                                 (
                    () =>
                {
                    w.WaitOne();
                    using (x.EnterRead())
                    {
                        Interlocked.Increment(ref z[0]);
                        Thread.Sleep(10);
                    }
                }
                                 );
            }
            for (int index = 0; index < 5; index++)
            {
                threads[index].Start();
            }
            w.Set();
            for (int index = 0; index < 5; index++)
            {
                threads[index].Join();
            }
            Assert.AreEqual(6, Interlocked.Increment(ref z[0]));
        }
コード例 #7
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
     }
 }
コード例 #8
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]));
             }
         }
     }
 }
コード例 #9
0
 public void CanEnterRead()
 {
     using (var x = new ReadWriteLock())
     {
         using (x.EnterRead())
         {
             Assert.IsFalse(x.IsCurrentThreadWriter);
         }
     }
 }
コード例 #10
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())
                {
                }
            }
        }
コード例 #11
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);
                }
            }
        }
コード例 #12
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]));
         }
     }
 }
コード例 #13
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]));
             }
         }
     }
 }