public void EnterExit()
        {
            using (ReaderWriterLockSlim rwls = new ReaderWriterLockSlim())
            {
                Assert.IsFalse(rwls.IsReadLockHeld);
                rwls.EnterReadLock();
                Assert.IsTrue(rwls.IsReadLockHeld);
                rwls.ExitReadLock();
                Assert.IsFalse(rwls.IsReadLockHeld);

                Assert.IsFalse(rwls.IsUpgradeableReadLockHeld);
                rwls.EnterUpgradeableReadLock();
                Assert.IsTrue(rwls.IsUpgradeableReadLockHeld);
                rwls.ExitUpgradeableReadLock();
                Assert.IsFalse(rwls.IsUpgradeableReadLockHeld);

                Assert.IsFalse(rwls.IsWriteLockHeld);
                rwls.EnterWriteLock();
                Assert.IsTrue(rwls.IsWriteLockHeld);
                rwls.ExitWriteLock();
                Assert.IsFalse(rwls.IsWriteLockHeld);

                Assert.IsFalse(rwls.IsUpgradeableReadLockHeld);
                rwls.EnterUpgradeableReadLock();
                Assert.IsFalse(rwls.IsWriteLockHeld);
                Assert.IsTrue(rwls.IsUpgradeableReadLockHeld);
                rwls.EnterWriteLock();
                Assert.IsTrue(rwls.IsWriteLockHeld);
                rwls.ExitWriteLock();
                Assert.IsFalse(rwls.IsWriteLockHeld);
                Assert.IsTrue(rwls.IsUpgradeableReadLockHeld);
                rwls.ExitUpgradeableReadLock();
                Assert.IsFalse(rwls.IsUpgradeableReadLockHeld);

                Assert.IsTrue(rwls.TryEnterReadLock(0));
                rwls.ExitReadLock();

                Assert.IsTrue(rwls.TryEnterReadLock(Timeout2.InfiniteTimeSpan));
                rwls.ExitReadLock();

                Assert.IsTrue(rwls.TryEnterUpgradeableReadLock(0));
                rwls.ExitUpgradeableReadLock();

                Assert.IsTrue(rwls.TryEnterUpgradeableReadLock(Timeout2.InfiniteTimeSpan));
                rwls.ExitUpgradeableReadLock();

                Assert.IsTrue(rwls.TryEnterWriteLock(0));
                rwls.ExitWriteLock();

                Assert.IsTrue(rwls.TryEnterWriteLock(Timeout2.InfiniteTimeSpan));
                rwls.ExitWriteLock();
            }
        }
        public void InvalidTimeouts()
        {
            using (ReaderWriterLockSlim rwls = new ReaderWriterLockSlim())
            {
                AssertExtensions.Throws <ArgumentOutOfRangeException>(() => rwls.TryEnterReadLock(-2));
                AssertExtensions.Throws <ArgumentOutOfRangeException>(() => rwls.TryEnterUpgradeableReadLock(-3));
                AssertExtensions.Throws <ArgumentOutOfRangeException>(() => rwls.TryEnterWriteLock(-4));

                AssertExtensions.Throws <ArgumentOutOfRangeException>(() => rwls.TryEnterReadLock(TimeSpan.MaxValue));
                AssertExtensions.Throws <ArgumentOutOfRangeException>(() => rwls.TryEnterUpgradeableReadLock(TimeSpan.MinValue));
                AssertExtensions.Throws <ArgumentOutOfRangeException>(() => rwls.TryEnterWriteLock(TimeSpan.FromMilliseconds(-2)));
            }
        }
        public void Dispose()
        {
            ReaderWriterLockSlim rwls;

            rwls = new ReaderWriterLockSlim();
            rwls.Dispose();
            AssertExtensions.Throws <ObjectDisposedException>(() => rwls.TryEnterReadLock(0));
            AssertExtensions.Throws <ObjectDisposedException>(() => rwls.TryEnterUpgradeableReadLock(0));
            AssertExtensions.Throws <ObjectDisposedException>(() => rwls.TryEnterWriteLock(0));
            rwls.Dispose();

            for (int i = 0; i < 3; i++)
            {
                rwls = new ReaderWriterLockSlim();
                switch (i)
                {
                case 0: rwls.EnterReadLock(); break;

                case 1: rwls.EnterUpgradeableReadLock(); break;

                case 2: rwls.EnterWriteLock(); break;
                }
                AssertExtensions.Throws <SynchronizationLockException>(() => rwls.Dispose());
            }
        }
 public void WriterToWriterChain()
 {
     using (AutoResetEvent are = new AutoResetEvent(false))
         using (ReaderWriterLockSlim rwls = new ReaderWriterLockSlim())
         {
             rwls.EnterWriteLock();
             Task t = Task.Factory.StartNew(() =>
             {
                 Assert.IsFalse(rwls.TryEnterWriteLock(10));
                 Task.Run(() => are.Set()); // ideally this won't fire until we've called EnterWriteLock, but it's a benign race in that the test will succeed either way
                 rwls.EnterWriteLock();
                 rwls.ExitWriteLock();
             }, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default);
             are.WaitOne();
             rwls.ExitWriteLock();
             t.GetAwaiter().GetResult();
         }
 }
 public void WritersAreMutuallyExclusiveFromWriters()
 {
     using (Barrier barrier = new Barrier(2))
         using (ReaderWriterLockSlim rwls = new ReaderWriterLockSlim())
         {
             Task.WaitAll(
                 Task.Run(() =>
             {
                 rwls.EnterWriteLock();
                 barrier.SignalAndWait();
                 Assert.IsTrue(rwls.IsWriteLockHeld);
                 barrier.SignalAndWait();
                 rwls.ExitWriteLock();
             }),
                 Task.Run(() =>
             {
                 barrier.SignalAndWait();
                 Assert.IsFalse(rwls.TryEnterWriteLock(0));
                 Assert.IsFalse(rwls.IsReadLockHeld);
                 barrier.SignalAndWait();
             }));
         }
 }
        //[OuterLoop]
        //[SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework, "Hangs in desktop, issue dotnet/corefx#3364 is not fixed there")]
        public void ReleaseReadersWhenWaitingWriterTimesOut()
        {
            using (var rwls = new ReaderWriterLockSlim())
            {
                // Enter the read lock
                rwls.EnterReadLock();
                // Typical order of execution: 0

                Thread writeWaiterThread;
                using (var beforeTryEnterWriteLock = new ManualResetEvent(false))
                {
                    writeWaiterThread =
                        new Thread(() =>
                    {
                        // Typical order of execution: 1

                        // Add a writer to the wait list for enough time to allow successive readers to enter the wait list while this
                        // writer is waiting
                        beforeTryEnterWriteLock.Set();
                        if (rwls.TryEnterWriteLock(1000))
                        {
                            // The typical order of execution is not guaranteed, as sleep times are not guaranteed. For
                            // instance, before this write lock is added to the wait list, the two new read locks may be
                            // acquired. In that case, the test may complete before or while the write lock is taken.
                            rwls.ExitWriteLock();
                        }

                        // Typical order of execution: 4
                    });
                    writeWaiterThread.IsBackground = true;
                    writeWaiterThread.Start();
                    beforeTryEnterWriteLock.WaitOne();
                }
                Thread.Sleep(500); // wait for TryEnterWriteLock to enter the wait list

                // A writer should now be waiting, add readers to the wait list. Since a read lock is still acquired, the writer
                // should time out waiting, then these readers should enter and exit the lock.
                ThreadStart EnterAndExitReadLock = () =>
                {
                    // Typical order of execution: 2, 3
                    rwls.EnterReadLock();
                    // Typical order of execution: 5, 6
                    rwls.ExitReadLock();
                };
                var readerThreads =
                    new Thread[]
                {
                    new Thread(EnterAndExitReadLock),
                    new Thread(EnterAndExitReadLock)
                };
                foreach (var readerThread in readerThreads)
                {
                    readerThread.IsBackground = true;
                    readerThread.Start();
                }
                foreach (var readerThread in readerThreads)
                {
                    readerThread.Join();
                }

                rwls.ExitReadLock();
                // Typical order of execution: 7

                writeWaiterThread.Join();
            }
        }