public void CanAcquireAndReleaseWriteLock()
        {
            var l = new ReaderWriterLockSlimEx();

            using (l.AcquireWriteLock())
            {
                // access lock here so it's not optimized-away after release build
                Assert.IsNotNull(l);
            }
        }
        public void CanUpgradeUpgradeableReadLock()
        {
            var l = new ReaderWriterLockSlimEx();

            using (var rl = l.AcquireUpgradeableReadLock())
            {
                // access lock here so it's not optimized-away after release build
                Assert.IsNotNull(l);

                using(rl.UpgradeToWriteLock())
                {
                    // access lock here so it's not optimized-away after release build
                    Assert.IsNotNull(l);
                }
            }
        }
        public void using_child_locks__avoids_deadlock_situations()
        {
            // Lock_1 (more coarse than Lock_2)
            // Lock_2 (child of Lock_1, more granual)

            // Thread_1 accesses Lock_1 then Lock_2
            // Thread_2 accesses Lock_2 only

            var l1 = new ReaderWriterLockSlimEx(LockRecursionPolicy.NoRecursion);
            var l2 = new ReaderWriterLockSlimEx(LockRecursionPolicy.NoRecursion);
            l1.AddChild(l2);

            bool oh_no = false;

            var t1 = Task.Run(() =>
            {
                using (l1.AcquireWriteLockIfNotHeld())
                {
                    Trace.WriteLine("t1 acquired l1");
                    Thread.Sleep(1000);

                    using (l2.AcquireReadLockIfNotHeld())
                    {
                        if (oh_no)
                            Assert.Fail(":(");
                    }
                }
            });


            var t2 = Task.Run(() =>
            {
                Thread.Sleep(100);

                using (l2.AcquireWriteLock())
                {
                    oh_no = true;
                    Trace.WriteLine("t2 acquired l2");
                }
            });

            Task.WaitAll(new[] { t1, t2 });
        }
        public void WriteLockIsHeld__AnotherThreadBlocksOnReadLockAcquisition()
        {
            var l = new ReaderWriterLockSlimEx();

            using (l.AcquireWriteLock())
            {
                Task.Factory.StartNew(() =>
                    {
                        var acquisition = (IReadLockAcquisition)null;
                        
                        if(l.TryAcquireReadLock(TEST_DefaultTimeout, out acquisition))
                        {
                            // should not get here
                            Assert.Fail();
                        }
                    }).Wait();
            }
        }
        public void SupportsRecursion__WriteLockIsHeld__AnotherLockCanBeAcquired()
        {
            var l = new ReaderWriterLockSlimEx(LockRecursionPolicy.SupportsRecursion);

            IReadLockAcquisition r;
            IUpgradeableReadLockAcquisition ur;
            IWriteLockAcquisition w;

            var a1 = l.AcquireReadLock();
            var a2 = l.TryAcquireReadLock(TEST_DefaultTimeout, out r);
            var a3 = l.TryAcquireUpgradeableReadLock(TEST_DefaultTimeout, out ur);
            var a4 = l.TryAcquireWriteLock(TEST_DefaultTimeout, out w);

            Assert.IsTrue(a2);
            Assert.IsFalse(a3);
            Assert.IsFalse(a4);
        }
        public void UpgradeableReadLockIsHeld__AnotherThreadDoesNotBlockOnUpgradeableReadLockAcquisition()
        {
            // NOTE:    this is how Reader Writer Lock Slim works
            //          only one thread can own Upgradeable Read Lock at the time

            var l = new ReaderWriterLockSlimEx();

            using (l.AcquireUpgradeableReadLock())
            {
                Task.Factory.StartNew(() =>
                {
                    var acquisition = (IUpgradeableReadLockAcquisition)null;

                    if (l.TryAcquireUpgradeableReadLock(TEST_DefaultTimeout, out acquisition))
                    {
                        Assert.Fail();
                    }

                }).Wait();
            }
        }
        public void ReadLockIsHeld__AnotherThreadDoesNotBlockOnUpgradeableReadLockAcquisition()
        {
            var l = new ReaderWriterLockSlimEx();

            using (l.AcquireReadLock())
            {
                Task.Factory.StartNew(() =>
                {
                    var acquisition = (IUpgradeableReadLockAcquisition)null;

                    if (!l.TryAcquireUpgradeableReadLock(TEST_DefaultTimeout, out acquisition))
                    {
                        // should be able to acquire
                        Assert.Fail();
                    }
                }).Wait();
            }
        }
        public void ReadLockIsHeld__CannotAcquireUpgradeableReadLock()
        {
            var l = new ReaderWriterLockSlimEx();

            using (var rl = l.AcquireReadLock())
            {
                var acquisition = (IUpgradeableReadLockAcquisition)null;

                if (l.TryAcquireUpgradeableReadLock(TEST_DefaultTimeout, out acquisition))
                {
                    // should not get here
                    Assert.Fail();
                }
            }
        }
 public ReadLockAcquisition(ReaderWriterLockSlimEx owner, IDisposable disposeWhenDone)
 {
     this.Owner = owner;
     this.Disposable = disposeWhenDone;
 }
 public UpgradeableReadLockAcquisition(ReaderWriterLockSlimEx owner)
 {
     this.Owner = owner;
 }
 public WriteLockAcquisition(ReaderWriterLockSlimEx owner)
 {
     this.Owner = owner;
 }