public void Dispose()
 {
     if (_mutex == null)
     {
         return;
     }
     AsyncLockTracker.Remove(_mutex);
     _mutex = null;
 }
            public RecursiveLockAwaitable LockAsync(CancellationToken token)
            {
                var key = AsyncLockTracker.Lookup(this);

                if (key == null)
                {
                    key = mutex.LockAsync(token).AsTask();
                }
                return(new RecursiveLockAwaitable(key, this));
            }
        public async Task RecursiveAsyncLock_DoesNotPermitIndependentWaits()
        {
            var mutex0 = new RecursiveAsyncLock();

            using (await mutex0.LockAsync())
            {
                var mutex = new RecursiveAsyncLock();
                Func <TaskCompletionSource, TaskCompletionSource, Task> taker = async(ready, finish) =>
                {
                    Assert.IsFalse(AsyncLockTracker.Contains(mutex));
                    using (await mutex.LockAsync())
                    {
                        Assert.IsTrue(AsyncLockTracker.Contains(mutex));
                        ready.TrySetResult();
                        await finish.Task;
                        Assert.IsTrue(AsyncLockTracker.Contains(mutex));
                    }
                    Assert.IsFalse(AsyncLockTracker.Contains(mutex));
                };

                var ready1  = new TaskCompletionSource();
                var finish1 = new TaskCompletionSource();
                Assert.IsFalse(AsyncLockTracker.Contains(mutex));
                var task1 = taker(ready1, finish1);
                Assert.IsFalse(AsyncLockTracker.Contains(mutex));
                await Task.WhenAny(ready1.Task, task1);

                Assert.IsFalse(AsyncLockTracker.Contains(mutex));

                var ready2  = new TaskCompletionSource();
                var finish2 = new TaskCompletionSource();
                Assert.IsFalse(AsyncLockTracker.Contains(mutex));
                var task2 = taker(ready2, finish2);
                Assert.IsFalse(AsyncLockTracker.Contains(mutex));

                Assert.IsFalse(ready2.Task.Wait(1000));

                finish1.SetResult();
                await Task.WhenAny(ready2.Task, task2);

                Assert.IsFalse(AsyncLockTracker.Contains(mutex));
                finish2.SetResult();
                await Task.WhenAll(task1, task2);

                Assert.IsFalse(AsyncLockTracker.Contains(mutex));
            }
        }
        public async Task RecursiveAsyncLock_PermitsRecursiveWaits()
        {
            var mutex = new RecursiveAsyncLock();

            Assert.IsFalse(AsyncLockTracker.Contains(mutex));
            var task1 = mutex.LockAsync();
            var key1  = await task1;

            Assert.IsTrue(AsyncLockTracker.Contains(mutex));

            var task2 = mutex.LockAsync();
            var key2  = await task2;

            Assert.IsTrue(AsyncLockTracker.Contains(mutex));

            key2.Dispose();
            Assert.IsTrue(AsyncLockTracker.Contains(mutex));
            key1.Dispose();
            Assert.IsFalse(AsyncLockTracker.Contains(mutex));
        }
 public KeyDisposable(Task <IDisposable> keyTask, RecursiveAsyncLock mutex)
 {
     _mutex = mutex;
     AsyncLockTracker.Add(mutex, keyTask);
 }