Task <T> IAsyncWaitQueue <T> .Enqueue()
        {
            var tcs = TaskCompletionSourceExtensions.CreateAsyncTaskSource <T>();

            _queue.AddToBack(tcs);
            return(tcs.Task);
        }
Example #2
0
        public async Task AsyncLock_DoubleDispose_OnlyPermitsOneTask()
        {
            AsyncLock mutex = new AsyncLock();
            TaskCompletionSource <object> task1HasLock  = TaskCompletionSourceExtensions.CreateAsyncTaskSource <object>();
            TaskCompletionSource <object> task1Continue = TaskCompletionSourceExtensions.CreateAsyncTaskSource <object>();

            await Task.Run(async() =>
            {
                IDisposable key = await mutex.LockAsync();
                key.Dispose();
                key.Dispose();
            }).ConfigureAwait(false);

            Task task1 = Task.Run(async() =>
            {
                using (await mutex.LockAsync())
                {
                    task1HasLock.SetResult(null);
                    await task1Continue.Task;
                }
            });
            await task1HasLock.Task;

            Task task2 = Task.Run(async() => await mutex.LockAsync());

            Assert.False(task2.IsCompleted);
            task1Continue.SetResult(null);
            await task2;
        }
Example #3
0
        public async Task AsyncLock_CancelledLock_LeavesLockUnlocked()
        {
            AsyncLock mutex = new AsyncLock();
            CancellationTokenSource       cts       = new CancellationTokenSource();
            TaskCompletionSource <object> taskReady = TaskCompletionSourceExtensions.CreateAsyncTaskSource <object>();

            IDisposable unlock = await mutex.LockAsync();

            Task task = Task.Run(async() =>
            {
                AwaitableDisposable <IDisposable> lockTask = mutex.LockAsync(cts.Token);
                taskReady.SetResult(null);
                await lockTask;
            });
            await taskReady.Task;

            cts.Cancel();
            await AsyncAssert.ThrowsAsync <OperationCanceledException>(task).ConfigureAwait(false);

            Assert.True(task.IsCanceled);
            unlock.Dispose();

            AwaitableDisposable <IDisposable> finalLockTask = mutex.LockAsync();
            await finalLockTask;
        }
        public void TryConcludeFromFailsWithNullThis()
        {
            var e = Assert.Throws <ArgumentNullException>(() =>
                                                          TaskCompletionSourceExtensions.TryConcludeFrom(null, new TaskCompletionSource <object>().Task));

            Assert.Equal("source", e.ParamName);
        }
Example #5
0
        public async Task CreateAsyncTaskSource_PermitsCompletingTask()
        {
            TaskCompletionSource <object> tcs = TaskCompletionSourceExtensions.CreateAsyncTaskSource <object>();

            tcs.SetResult(null);

            await tcs.Task;
        }
Example #6
0
 /// <summary>
 /// Creates an async-compatible manual-reset event.
 /// </summary>
 /// <param name="set">Whether the manual-reset event is initially set or unset.</param>
 public AsyncManualResetEvent(bool set)
 {
     _mutex = new object();
     _tcs   = TaskCompletionSourceExtensions.CreateAsyncTaskSource <object>();
     if (set)
     {
         _tcs.TrySetResult(null);
     }
 }
Example #7
0
 /// <summary>
 /// Resets the event. If the event is already reset, this method does nothing.
 /// </summary>
 public void Reset()
 {
     lock (_mutex)
     {
         if (_tcs.Task.IsCompleted)
         {
             _tcs = TaskCompletionSourceExtensions.CreateAsyncTaskSource <object>();
         }
     }
 }
Example #8
0
        public async Task AsyncLazy_Start_CallsFunc()
        {
            var tcs = TaskCompletionSourceExtensions.CreateAsyncTaskSource <object>();
            Func <Task <int> > func = () =>
            {
                tcs.SetResult(null);
                return(Task.FromResult(13));
            };
            var lazy = new AsyncLazy <int>(func);

            lazy.Start();
            await tcs.Task;
        }
Example #9
0
        public async Task PulseAll_ReleasesAllWaiters()
        {
            AsyncMonitor monitor = new AsyncMonitor();

            int[] completed = { 0 };
            TaskCompletionSource <object> task1Ready = TaskCompletionSourceExtensions.CreateAsyncTaskSource <object>();
            TaskCompletionSource <object> task2Ready = TaskCompletionSourceExtensions.CreateAsyncTaskSource <object>();
            Task waitTask1 = null;
            Task task1     = Task.Run(async() =>
            {
                using (await monitor.EnterAsync())
                {
                    waitTask1 = monitor.WaitAsync();
                    task1Ready.SetResult(null);
                    await waitTask1;
                    Interlocked.Increment(ref completed[0]);
                }
            });
            await task1Ready.Task;
            Task waitTask2 = null;
            Task task2     = Task.Run(async() =>
            {
                using (await monitor.EnterAsync())
                {
                    waitTask2 = monitor.WaitAsync();
                    task2Ready.SetResult(null);
                    await waitTask2;
                    Interlocked.Increment(ref completed[0]);
                }
            });
            await task2Ready.Task;

            AwaitableDisposable <IDisposable> lockTask3 = monitor.EnterAsync();

            using (await lockTask3)
            {
                monitor.PulseAll();
            }
            await Task.WhenAll(task1, task2).ConfigureAwait(false);

            int result = Interlocked.CompareExchange(ref completed[0], 0, 0);

            Assert.Equal(2, result);
        }
        public async Task PulseAll_ReleasesAllWaiters()
        {
            var  monitor    = new AsyncMonitor();
            int  completed  = 0;
            var  task1Ready = TaskCompletionSourceExtensions.CreateAsyncTaskSource <object>();
            var  task2Ready = TaskCompletionSourceExtensions.CreateAsyncTaskSource <object>();
            Task waitTask1  = null;
            var  task1      = Task.Run(async() =>
            {
                using (await monitor.EnterAsync())
                {
                    waitTask1 = monitor.WaitAsync();
                    task1Ready.SetResult(null);
                    await waitTask1;
                    Interlocked.Increment(ref completed);
                }
            });
            await task1Ready.Task;
            Task waitTask2 = null;
            var  task2     = Task.Run(async() =>
            {
                using (await monitor.EnterAsync())
                {
                    waitTask2 = monitor.WaitAsync();
                    task2Ready.SetResult(null);
                    await waitTask2;
                    Interlocked.Increment(ref completed);
                }
            });
            await task2Ready.Task;

            var lockTask3 = monitor.EnterAsync();

            using (await lockTask3)
            {
                monitor.PulseAll();
            }
            await Task.WhenAll(task1, task2);

            var result = Interlocked.CompareExchange(ref completed, 0, 0);

            Assert.Equal(2, result);
        }
Example #11
0
        /// <summary>
        /// Returns a <see cref="Task{T}"/> that completes when a specified event next fires. This overload is for events that are of any type.
        /// </summary>
        /// <typeparam name="TDelegate">The type of the event delegate.</typeparam>
        /// <typeparam name="TEventArguments">A type containing all event arguments.</typeparam>
        /// <param name="convert">A conversion delegate that takes an <see cref="Action{TEventArguments}"/> and converts it to a <typeparamref name="TDelegate"/>. This is generally of the form <c>x => (...) => x(new TEventArguments(...))</c>.</param>
        /// <param name="subscribe">A method that takes a <typeparamref name="TDelegate"/> and subscribes it to the event.</param>
        /// <param name="unsubscribe">A method that takes an <typeparamref name="TDelegate"/> and unsubscribes it from the event. This method is invoked in a captured context if <paramref name="unsubscribeOnCapturedContext"/> is <c>true</c>.</param>
        /// <param name="cancellationToken">A cancellation token that can be used to cancel the task (and unsubscribe from the event handler).</param>
        /// <param name="unsubscribeOnCapturedContext">Whether to invoke <paramref name="unsubscribe"/> on a captured context.</param>
        /// <remarks>
        /// <para>Calling this method in a loop is often an anti-pattern, because the event is only subscribed to when this method is invoked, and is unsubscribed from when the task completes. From the time the task is completed until this method is called again, the event may fire and be "lost". If you find yourself needing a loop around this method, consider using Rx or TPL Dataflow instead.</para>
        /// </remarks>
        public static async Task <TEventArguments> FromAnyEvent <TDelegate, TEventArguments>(Func <Action <TEventArguments>, TDelegate> convert,
                                                                                             Action <TDelegate> subscribe, Action <TDelegate> unsubscribe, CancellationToken cancellationToken, bool unsubscribeOnCapturedContext)
        {
            cancellationToken.ThrowIfCancellationRequested();
            TaskCompletionSource <TEventArguments> tcs = TaskCompletionSourceExtensions.CreateAsyncTaskSource <TEventArguments>();
            TDelegate subscription = convert(result => tcs.TrySetResult(result));

            try
            {
                using (cancellationToken.Register(() => tcs.TrySetCanceled(), useSynchronizationContext: false))
                {
                    subscribe(subscription);
                    return(await tcs.Task.ConfigureAwait(continueOnCapturedContext : unsubscribeOnCapturedContext));
                }
            }
            finally
            {
                unsubscribe(subscription);
            }
        }
        public async Task WriteLocked_Unlocked_PermitsAnotherWriterLock()
        {
            AsyncReaderWriterLock         rwl = new AsyncReaderWriterLock();
            TaskCompletionSource <object> firstWriteLockTaken   = TaskCompletionSourceExtensions.CreateAsyncTaskSource <object>();
            TaskCompletionSource <object> releaseFirstWriteLock = TaskCompletionSourceExtensions.CreateAsyncTaskSource <object>();
            Task task = Task.Run(async() =>
            {
                using (await rwl.WriterLockAsync())
                {
                    firstWriteLockTaken.SetResult(null);
                    await releaseFirstWriteLock.Task;
                }
            });
            await firstWriteLockTaken.Task;
            Task <IDisposable> lockTask = rwl.WriterLockAsync().AsTask();

            Assert.False(lockTask.IsCompleted);
            releaseFirstWriteLock.SetResult(null);
            await lockTask;
        }
Example #13
0
        public async Task AsyncLock_Locked_OnlyPermitsOneLockerAtATime()
        {
            AsyncLock mutex = new AsyncLock();
            TaskCompletionSource <object> task1HasLock  = TaskCompletionSourceExtensions.CreateAsyncTaskSource <object>();
            TaskCompletionSource <object> task1Continue = TaskCompletionSourceExtensions.CreateAsyncTaskSource <object>();
            TaskCompletionSource <object> task2Ready    = TaskCompletionSourceExtensions.CreateAsyncTaskSource <object>();
            TaskCompletionSource <object> task2HasLock  = TaskCompletionSourceExtensions.CreateAsyncTaskSource <object>();
            TaskCompletionSource <object> task2Continue = TaskCompletionSourceExtensions.CreateAsyncTaskSource <object>();

            Task task1 = Task.Run(async() =>
            {
                using (await mutex.LockAsync())
                {
                    task1HasLock.SetResult(null);
                    await task1Continue.Task;
                }
            });
            await task1HasLock.Task;

            Task task2 = Task.Run(async() =>
            {
                AwaitableDisposable <IDisposable> key = mutex.LockAsync();
                task2Ready.SetResult(null);
                using (await key)
                {
                    task2HasLock.SetResult(null);
                    await task2Continue.Task;
                }
            });
            await task2Ready.Task;

            Task task3 = Task.Run(async() => await mutex.LockAsync());

            task1Continue.SetResult(null);
            await task2HasLock.Task;

            Assert.False(task3.IsCompleted);
            task2Continue.SetResult(null);
            await task2;
            await task3;
        }
Example #14
0
        public async Task AsyncLock_Locked_PreventsLockUntilUnlocked()
        {
            AsyncLock mutex = new AsyncLock();
            TaskCompletionSource <object> task1HasLock  = TaskCompletionSourceExtensions.CreateAsyncTaskSource <object>();
            TaskCompletionSource <object> task1Continue = TaskCompletionSourceExtensions.CreateAsyncTaskSource <object>();

            Task task1 = Task.Run(async() =>
            {
                using (await mutex.LockAsync())
                {
                    task1HasLock.SetResult(null);
                    await task1Continue.Task;
                }
            });
            await task1HasLock.Task;

            Task task2 = Task.Run(async() => await mutex.LockAsync());

            Assert.False(task2.IsCompleted);
            task1Continue.SetResult(null);
            await task2;
        }
        public async Task Locked_PreventsLockUntilUnlocked()
        {
            var monitor       = new AsyncMonitor();
            var task1HasLock  = TaskCompletionSourceExtensions.CreateAsyncTaskSource <object>();
            var task1Continue = TaskCompletionSourceExtensions.CreateAsyncTaskSource <object>();

            var task1 = Task.Run(async() =>
            {
                using (await monitor.EnterAsync())
                {
                    task1HasLock.SetResult(null);
                    await task1Continue.Task;
                }
            });
            await task1HasLock.Task;

            var lockTask = monitor.EnterAsync().AsTask();

            Assert.False(lockTask.IsCompleted);
            task1Continue.SetResult(null);
            await lockTask;
        }
Example #16
0
        public async Task AsyncLazy_MultipleAwaiters_OnlyInvokeFuncOnce()
        {
            int invokeCount         = 0;
            var tcs                 = TaskCompletionSourceExtensions.CreateAsyncTaskSource <object>();
            Func <Task <int> > func = async() =>
            {
                Interlocked.Increment(ref invokeCount);
                await tcs.Task;
                return(13);
            };
            var lazy = new AsyncLazy <int>(func);

            var task1 = Task.Run(async() => await lazy);
            var task2 = Task.Run(async() => await lazy);

            Assert.False(task1.IsCompleted);
            Assert.False(task2.IsCompleted);
            tcs.SetResult(null);
            var results = await Task.WhenAll(task1, task2);

            Assert.True(results.SequenceEqual(new[] { 13, 13 }));
            Assert.Equal(1, invokeCount);
        }