public void WriteLocked_PreventsUpgradeableReaderLock()
 {
     Test.Async(async () =>
     {
         var rwl = new AsyncReaderWriterLock();
         await rwl.WriterLockAsync();
         var task = rwl.UpgradeableReaderLockAsync().AsTask();
         await AssertEx.NeverCompletesAsync(task);
     });
 }
        public void ReaderLocked_ReaderReleased_ReaderAndUpgradingReaderWaiting_DoesNotReleaseReaderOrUpgradingReader()
        {
            Test.Async(async () =>
            {
                var rwl = new AsyncReaderWriterLock();
                Task readLock, upgradingReadLock;
                await rwl.ReaderLockAsync();
                using (await rwl.ReaderLockAsync())
                {
                    var upgradeableReadLock = await rwl.UpgradeableReaderLockAsync();
                    upgradingReadLock = upgradeableReadLock.UpgradeAsync().AsTask();
                    readLock = rwl.ReaderLockAsync().AsTask();
                }

                await TaskShim.WhenAll(AssertEx.NeverCompletesAsync(upgradingReadLock),
                    AssertEx.NeverCompletesAsync(readLock));
            });
        }
        public void LockReleased_AllowsUpgradeableReadAndMultipleReaders()
        {
            Test.Async(async () =>
            {
                var rwl = new AsyncReaderWriterLock();
                Task upgradeableReadLock, readLock1, readLock2;
                using (await rwl.WriterLockAsync())
                {
                    upgradeableReadLock = rwl.UpgradeableReaderLockAsync().AsTask();
                    readLock1 = rwl.ReaderLockAsync().AsTask();
                    readLock2 = rwl.ReaderLockAsync().AsTask();
                }

                await TaskShim.WhenAll(upgradeableReadLock, readLock1, readLock2);
            });
        }
        public void LockReleased_WriteTakesPriorityOverUpgradeableRead()
        {
            Test.Async(async () =>
            {
                var rwl = new AsyncReaderWriterLock();
                Task writeLock, upgradeableReadLock;
                using (await rwl.WriterLockAsync())
                {
                    upgradeableReadLock = rwl.UpgradeableReaderLockAsync().AsTask();
                    writeLock = rwl.WriterLockAsync().AsTask();
                }

                await writeLock;
                await AssertEx.NeverCompletesAsync(upgradeableReadLock);
            });
        }
        public void WriteLocked_UpgradeableReaderLockCancelled_DoesNotTakeLockWhenUnlocked()
        {
            Test.Async(async () =>
            {
                var rwl = new AsyncReaderWriterLock();
                using (await rwl.WriterLockAsync())
                {
                    var cts = new CancellationTokenSource();
                    var task = rwl.UpgradeableReaderLockAsync(cts.Token).AsTask();
                    cts.Cancel();
                    await AssertEx.ThrowsExceptionAsync<OperationCanceledException>(() => task);
                }

                await rwl.UpgradeableReaderLockAsync();
            });
        }
        public void Upgrade_PreCancelled_LockNotAvailable_SynchronouslyCancels()
        {
            var rwl = new AsyncReaderWriterLock();
            var token = new CancellationToken(true);
            var key = rwl.UpgradeableReaderLockAsync().AsTask().Result;
            rwl.ReaderLockAsync();

            var task = key.UpgradeAsync(token).AsTask();

            Assert.IsTrue(task.IsCompleted);
            Assert.IsTrue(task.IsCanceled);
            Assert.IsFalse(task.IsFaulted);
        }
 public void UpgradeKey_MultiDispose_DoesNothing()
 {
     AsyncContext.Run(async () =>
     {
         var rwl = new AsyncReaderWriterLock();
         var upgradeable = await rwl.UpgradeableReaderLockAsync();
         var key = await upgradeable.UpgradeAsync();
         key.Dispose();
         key.Dispose();
         await upgradeable.UpgradeAsync();
     });
 }
 public void UpgradeableKey_MultiUpgradeWhenFirstUpgradeIsIncomplete_ThrowsSynchronousException()
 {
     Test.Async(async () =>
     {
         var rwl = new AsyncReaderWriterLock();
         await rwl.ReaderLockAsync();
         var key = await rwl.UpgradeableReaderLockAsync();
         var _ = key.UpgradeAsync();
         AssertEx.ThrowsException<InvalidOperationException>(() => key.UpgradeAsync());
     });
 }
        public void UpgradeableReadAndReadLocked_UpgradeAborted_CompletesAsCanceled()
        {
            Test.Async(async () =>
            {
                var rwl = new AsyncReaderWriterLock();
                var readLockTaken = new TaskCompletionSource();
                var task = TaskShim.Run(async () =>
                {
                    using (await rwl.ReaderLockAsync())
                    {
                        readLockTaken.SetResult();
                        await TaskConstants.Never;
                    }
                });
                await readLockTaken.Task;
                Task upgradeTask;
                using (var key = await rwl.UpgradeableReaderLockAsync())
                {
                    upgradeTask = key.UpgradeAsync().AsTask();
                    Assert.IsFalse(key.Upgraded);
                }

                await AssertEx.ThrowsExceptionAsync<OperationCanceledException>(upgradeTask);
            });
        }
 public void UpgradeableReadAndReadLocked_Upgrade_WaitsForReaderLockToUnlock()
 {
     Test.Async(async () =>
     {
         var rwl = new AsyncReaderWriterLock();
         var readLockTaken = new TaskCompletionSource();
         var releaseReadLock = new TaskCompletionSource();
         var task = TaskShim.Run(async () =>
         {
             using (await rwl.ReaderLockAsync())
             {
                 readLockTaken.SetResult();
                 await releaseReadLock.Task;
             }
         });
         await readLockTaken.Task;
         using (var key = await rwl.UpgradeableReaderLockAsync())
         {
             Assert.IsFalse(key.Upgraded);
             var lockTask = key.UpgradeAsync().AsTask();
             Assert.IsFalse(lockTask.IsCompleted);
             releaseReadLock.SetResult();
             await lockTask;
             Assert.IsTrue(key.Upgraded);
         }
     });
 }
 public void UpgradeableReadLocked_Upgraded_PreventsReaderLock()
 {
     Test.Async(async () =>
     {
         var rwl = new AsyncReaderWriterLock();
         var key = await rwl.UpgradeableReaderLockAsync();
         await key.UpgradeAsync();
         Assert.IsTrue(key.Upgraded);
         var task = rwl.WriterLockAsync().AsTask();
         await AssertEx.NeverCompletesAsync(task);
     });
 }
 public void UpgradeableReadLocked_Unlocked_AllowsWriterLock()
 {
     Test.Async(async () =>
     {
         var rwl = new AsyncReaderWriterLock();
         using (var key = await rwl.UpgradeableReaderLockAsync())
         {
             Assert.IsFalse(key.Upgraded);
         }
         await rwl.WriterLockAsync();
     });
 }
 public void UpgradeableReadLocked_AllowsMultipleReaderLocks()
 {
     Test.Async(async () =>
     {
         var rwl = new AsyncReaderWriterLock();
         var key = await rwl.UpgradeableReaderLockAsync();
         Assert.IsFalse(key.Upgraded);
         await rwl.ReaderLockAsync();
         await rwl.ReaderLockAsync();
     });
 }
 public void ReadLocked_AllowsUpgradeableReaderLock()
 {
     Test.Async(async () =>
     {
         var rwl = new AsyncReaderWriterLock();
         await rwl.ReaderLockAsync();
         await rwl.UpgradeableReaderLockAsync();
     });
 }
        public void ReaderLocked_UpgradableReaderReleased_UpgradableReaderWaiting_ReleasesUpgrableReader()
        {
            Test.Async(async () =>
            {
                var rwl = new AsyncReaderWriterLock();
                Task upgradableReadLock;
                using (await rwl.ReaderLockAsync())
                using (await rwl.UpgradeableReaderLockAsync())
                {
                    upgradableReadLock = rwl.UpgradeableReaderLockAsync().AsTask();
                    Assert.IsFalse(upgradableReadLock.IsCompleted);
                }

                await upgradableReadLock;
            });
        }
 public void UpgradeableKey_MultiUpgrade_ThrowsException()
 {
     Test.Async(async () =>
     {
         var rwl = new AsyncReaderWriterLock();
         var key = await rwl.UpgradeableReaderLockAsync();
         await key.UpgradeAsync();
         await AssertEx.ThrowsExceptionAsync<InvalidOperationException>(async () => { await key.UpgradeAsync(); });
     });
 }
 public void UpgradeableReadLocked_Downgrade_AllowsReaderLock()
 {
     Test.Async(async () =>
     {
         var rwl = new AsyncReaderWriterLock();
         var key = await rwl.UpgradeableReaderLockAsync();
         var upgradeKey = await key.UpgradeAsync();
         upgradeKey.Dispose();
         await rwl.ReaderLockAsync();
     });
 }
        public void UpgradeableReaderLock_PreCancelled_LockAvailable_SynchronouslyTakesLock()
        {
            var rwl = new AsyncReaderWriterLock();
            var token = new CancellationToken(true);

            var task = rwl.UpgradeableReaderLockAsync(token).AsTask();

            Assert.IsTrue(task.IsCompleted);
            Assert.IsFalse(task.IsCanceled);
            Assert.IsFalse(task.IsFaulted);
        }
 public void UpgradeableReadLocked_PreventsWriterLock()
 {
     AsyncContext.Run(async () =>
     {
         var rwl = new AsyncReaderWriterLock();
         var key = await rwl.UpgradeableReaderLockAsync();
         Assert.IsFalse(key.Upgraded);
         var task = rwl.WriterLockAsync();
         await AssertEx.NeverCompletesAsync(task);
     });
 }