コード例 #1
0
 /// <summary>
 /// Attempts to dequeue an item.
 /// </summary>
 /// <param name="cancellationToken">A cancellation token that can be used to abort the dequeue 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 dequeue operations. May be <c>null</c> if this is the only dequeue operation.</param>
 internal async Task <DequeueResult> TryDequeueAsync(CancellationToken cancellationToken, TaskCompletionSource abort)
 {
     try
     {
         using (await _mutex.LockAsync().ConfigureAwait(false))
         {
             while (!_completed.IsCancellationRequested && Empty)
             {
                 await _completedOrNotEmpty.WaitAsync(cancellationToken).ConfigureAwait(false);
             }
             if (_completed.IsCancellationRequested && Empty)
             {
                 return(FalseResult);
             }
             if (abort != null && !abort.TrySetCanceled())
             {
                 return(FalseResult);
             }
             var item = _queue.Dequeue();
             _notFull.Notify();
             return(new DequeueResult(this, item));
         }
     }
     catch (OperationCanceledException)
     {
         return(FalseResult);
     }
 }
コード例 #2
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);
            }
        }
コード例 #3
0
        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;
            });
        }
コード例 #4
0
        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);
            });
        }
コード例 #5
0
ファイル: AsyncMonitor.cs プロジェクト: mjsir911/Disa-XMPP
 /// <summary>
 /// Sends a signal to a single task waiting on this monitor. The monitor MUST already be entered when calling this method, and it will still be entered when this method returns.
 /// </summary>
 public void Pulse()
 {
     _conditionVariable.Notify();
 }
コード例 #6
0
        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);
            });
        }