예제 #1
0
        public void CannotWriteWhileWritingEx()
        {
            var         x           = new ReadWriteLock();
            var         ok          = true;
            var         doneThread  = false;
            IDisposable engagementA = null;

            try
            {
                if (x.TryEnterWrite(out engagementA))
                {
                    Assert.IsTrue(x.IsCurrentThreadWriter);
                    var a = new Thread
                            (
                        () =>
                    {
                        IDisposable engagementB = null;
                        try
                        {
                            if (x.TryEnterWrite(out engagementB))
                            {
                                ok = false;
                            }
                        }
                        finally
                        {
                            if (engagementB != null)
                            {
                                engagementB.Dispose();
                            }
                            doneThread = true;
                        }
                    }
                            );
                    a.Start();
                    a.Join();
                }
            }
            finally
            {
                if (engagementA != null)
                {
                    engagementA.Dispose();
                }
                doneThread = true;
            }
            Assert.IsTrue(ok);
            Assert.IsTrue(doneThread);
        }
예제 #2
0
 public void CanEnterWriteEx()
 {
     using (var x = new ReadWriteLock())
     {
         IDisposable engagement = null;
         try
         {
             if (x.TryEnterWrite(out engagement))
             {
                 Assert.IsTrue(x.IsCurrentThreadWriter);
             }
             else
             {
                 Assert.Fail();
             }
         }
         finally
         {
             if (engagement != null)
             {
                 engagement.Dispose();
             }
         }
     }
 }
예제 #3
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);
     }
 }
예제 #4
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
        }
예제 #5
0
 public void CanReentryWriteToWriteEx()
 {
     using (var x = new ReadWriteLock())
     {
         IDisposable engagementA = null;
         try
         {
             if (x.TryEnterWrite(out engagementA))
             {
                 Assert.IsTrue(x.IsCurrentThreadWriter);
                 IDisposable engagementB = null;
                 try
                 {
                     if (x.TryEnterWrite(out engagementB))
                     {
                         Assert.IsTrue(x.IsCurrentThreadWriter);
                     }
                     else
                     {
                         Assert.Fail();
                     }
                 }
                 finally
                 {
                     if (engagementB != null)
                     {
                         engagementB.Dispose();
                     }
                 }
             }
             else
             {
                 Assert.Fail();
             }
         }
         finally
         {
             if (engagementA != null)
             {
                 engagementA.Dispose();
             }
         }
     }
 }
예제 #6
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
         }
     }
 }
예제 #7
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);
         }
     }
 }
예제 #8
0
 public void CanReentryReadToWriteEx()
 {
     using (var x = new ReadWriteLock(false))
     {
         IDisposable engagementA = null;
         try
         {
             if (x.TryEnterRead(out engagementA))
             {
                 Assert.IsFalse(x.IsCurrentThreadWriter);
                 IDisposable engagementB = null;
                 try
                 {
                     if (x.TryEnterWrite(out engagementB))
                     {
                         Assert.Fail();
                     }
                     else
                     {
                         // Not reentrant ReadWriteLock will not be able to upgrade the lock
                         Assert.IsFalse(x.IsCurrentThreadWriter);
                     }
                 }
                 finally
                 {
                     if (engagementB != null)
                     {
                         engagementB.Dispose();
                     }
                 }
             }
             else
             {
                 Assert.Fail();
             }
         }
         finally
         {
             if (engagementA != null)
             {
                 engagementA.Dispose();
             }
         }
         //
         using (var y = new ReadWriteLock(true))
         {
             IDisposable engagementC = null;
             try
             {
                 if (y.TryEnterRead(out engagementC))
                 {
                     Assert.IsFalse(y.IsCurrentThreadWriter);
                     IDisposable engagementD = null;
                     try
                     {
                         if (y.TryEnterWrite(out engagementD))
                         {
                             // Reentrant ReadWriteLock will be able to upgrade the lock
                             Assert.IsTrue(y.IsCurrentThreadWriter);
                         }
                         else
                         {
                             Assert.Fail();
                         }
                     }
                     finally
                     {
                         if (engagementD != null)
                         {
                             engagementD.Dispose();
                         }
                     }
                 }
                 else
                 {
                     Assert.Fail();
                 }
             }
             finally
             {
                 if (engagementC != null)
                 {
                     engagementC.Dispose();
                 }
             }
         }
     }
 }