public void TestReadWriteLock_NonConcurrent()
        {
            using (var rwlock = new ReadWriteLock())
            {
                using (rwlock.EnterReadScope()) { }
                using (rwlock.EnterWriteScope()) { }
                using (rwlock.EnterUpgradeableReadScope())
                using (rwlock.EnterWriteScope()) { }

                rwlock.Dispose();
            }
        }
        public void TestReadWriteLock_MultipleWrites()
        {
            var rwlock = new ReadWriteLock();
            var random = new Random();
            int value = 0;

            Action action = () =>
            {
                using (rwlock.EnterWriteScope())
                {
                    var v = value;
                    Thread.Sleep(random.Next(10));
                    var tmp = v + 100;
                    Thread.Sleep(random.Next(10));
                    value = tmp;
                }
            };

            var tasks = Enumerable.Range(1, 100)
                .Select(i => Task.Factory.StartNew(action))
                .ToArray();

            Task.WaitAll(tasks);

            const int expected = 100 * 100;

            Assert.AreEqual(expected, value);
        }
        public void TestReadWriteLock_NoWriteWhileReading()
        {
            // ReSharper disable AccessToModifiedClosure
            // ReSharper disable AccessToDisposedClosure
            // ReSharper disable ImplicitlyCapturedClosure
            using (var rwlock = new ReadWriteLock())
            {
                string value = "foo";

                const string expected = "foo";
                string actual = null;

                var ewh1 = new EventWaitHandle(false, EventResetMode.ManualReset);
                var ewh2 = new EventWaitHandle(false, EventResetMode.ManualReset);

                var task1 = Task.Factory.StartNew(() =>
                {
                    using (rwlock.EnterReadScope())
                    {
                        ewh1.Set();
                        Assert.False(ewh2.WaitOne(TimeSpan.FromMilliseconds(100)));
                        Thread.Sleep(100);

                        actual = value;
                    }
                    Assert.True(ewh2.WaitOne(TimeSpan.FromSeconds(5)));
                });

                var task2 = Task.Factory.StartNew(() =>
                {
                    Assert.True(ewh1.WaitOne(TimeSpan.FromSeconds(5)));
                    using (rwlock.EnterWriteScope())
                        value = "bar";
                    ewh2.Set();
                });

                Assert.True(task1.Wait(TimeSpan.FromSeconds(5)));
                Assert.True(task2.Wait(TimeSpan.FromSeconds(5)));

                Assert.AreEqual(expected, actual);
            }
            // ReSharper restore ImplicitlyCapturedClosure
            // ReSharper restore AccessToDisposedClosure
            // ReSharper restore AccessToModifiedClosure
        }