public void MultipleWaits_NotifyAll_AllAreCompleted()
        {
            AsyncContext.Run(async () =>
            {
                var mutex = new AsyncLock();
                var cv = new AsyncConditionVariable(mutex);
                var key1 = await mutex.LockAsync();
                var task1 = cv.WaitAsync();
                var __ = task1.ContinueWith(_ => key1.Dispose());
                var key2 = await mutex.LockAsync();
                var task2 = cv.WaitAsync();
                var ___ = task2.ContinueWith(_ => key2.Dispose());

                await Task.Run(async () =>
                {
                    using (await mutex.LockAsync())
                    {
                        cv.NotifyAll();
                    }
                });

                await task1;
                await task2;
            });
        }
Пример #2
0
 /// <summary>
 /// Asynchronously waits until an item is available to dequeue. Returns <c>false</c> if the producer/consumer queue has completed adding and there are no more items.
 /// </summary>
 /// <param name="cancellationToken">A cancellation token that can be used to abort the asynchronous wait.</param>
 public async Task <bool> OutputAvailableAsync(CancellationToken cancellationToken)
 {
     using (await _mutex.LockAsync().ConfigureAwait(false))
     {
         while (!_completed.IsCancellationRequested && Empty)
         {
             await _completedOrNotEmpty.WaitAsync(cancellationToken).ConfigureAwait(false);
         }
         return(!Empty);
     }
 }
Пример #3
0
        /// <summary>
        /// Attempts to enqueue an item.
        /// </summary>
        /// <param name="item">The item to enqueue.</param>
        /// <param name="cancellationToken">A cancellation token that can be used to abort the enqueue operation. If <paramref name="abort"/> is not <c>null</c>, then this token must include signals from the <paramref name="abort"/> object.</param>
        /// <param name="abort">A synchronization object used to cancel related enqueue operations. May be <c>null</c> if this is the only enqueue operation.</param>
        internal async Task <AsyncProducerConsumerQueue <T> > TryEnqueueAsync(T item, CancellationToken cancellationToken, TaskCompletionSource abort)
        {
            try
            {
                using (var combinedToken = CancellationTokenHelpers.Normalize(_completed.Token, cancellationToken))
                    using (await _mutex.LockAsync().ConfigureAwait(false))
                    {
                        // Wait for the queue to be not full.
                        while (Full)
                        {
                            await _notFull.WaitAsync(combinedToken.Token).ConfigureAwait(false);
                        }

                        // Explicitly check whether the queue has been marked complete to prevent a race condition where notFull is signalled at the same time the queue is marked complete.
                        if (_completed.IsCancellationRequested)
                        {
                            return(null);
                        }

                        // Set the abort signal. If another queue has already set the abort signal, then abort.
                        if (abort != null && !abort.TrySetCanceled())
                        {
                            return(null);
                        }

                        _queue.Enqueue(item);
                        _completedOrNotEmpty.Notify();
                        return(this);
                    }
            }
            catch (OperationCanceledException)
            {
                return(null);
            }
        }
        public void WaitAsync_WithoutNotify_IsNotCompleted()
        {
            Test.Async(async () =>
            {
                var mutex = new AsyncLock();
                var cv = new AsyncConditionVariable(mutex);

                await mutex.LockAsync();
                var task = cv.WaitAsync();

                await AssertEx.NeverCompletesAsync(task);
            });
        }
        public void WaitAsync_Notified_IsCompleted()
        {
            Test.Async(async () =>
            {
                var mutex = new AsyncLock();
                var cv = new AsyncConditionVariable(mutex);
                await mutex.LockAsync();
                var task = cv.WaitAsync();

                await TaskShim.Run(async () =>
                {
                    using (await mutex.LockAsync())
                    {
                        cv.Notify();
                    }
                });
                await task;
            });
        }
        public void WaitAsync_AfterNotify_IsNotCompleted()
        {
            Test.Async(async () =>
            {
                var mutex = new AsyncLock();
                var cv = new AsyncConditionVariable(mutex);
                await TaskShim.Run(async () =>
                {
                    using (await mutex.LockAsync())
                    {
                        cv.Notify();
                    }
                });

                await mutex.LockAsync();
                var task = cv.WaitAsync();

                await AssertEx.NeverCompletesAsync(task);
            });
        }
Пример #7
0
 /// <summary>
 /// Asynchronously waits for a pulse signal on this monitor. The monitor MUST already be entered when calling this method, and it will still be entered when this method returns, even if the method is cancelled. This method internally will leave the monitor while waiting for a notification.
 /// </summary>
 /// <param name="cancellationToken">The cancellation signal used to cancel this wait.</param>
 public Task WaitAsync(CancellationToken cancellationToken)
 {
     return(_conditionVariable.WaitAsync(cancellationToken));
 }
        public void MultipleWaits_Notify_OneIsCompleted()
        {
            Test.Async(async () =>
            {
                var mutex = new AsyncLock();
                var cv = new AsyncConditionVariable(mutex);
                var key = await mutex.LockAsync();
                var task1 = cv.WaitAsync();
                var __ = task1.ContinueWith(_ => key.Dispose());
                await mutex.LockAsync();
                var task2 = cv.WaitAsync();

                await TaskShim.Run(async () =>
                {
                    using (await mutex.LockAsync())
                    {
                        cv.Notify();
                    }
                });

                await task1;
                await AssertEx.NeverCompletesAsync(task2);
            });
        }