public Task <IDisposable> EnterAsync(CancellationToken ct) { // The item may have been already dequeued by the previous since it was set as '_next', // If so, return sync (note: the '_count' was already incremented) if (_state == State.Waiting) { _enterAsync = new FastTaskCompletionSource <IDisposable>(); if (ct.CanBeCanceled) { _enterAsync.OnCompleted(ct.Register(Abort).Dispose); void Abort() { if (Interlocked.CompareExchange(ref _state, State.Aborted, State.Waiting) == State.Waiting) { _enterAsync.SetCanceled(); } } } // This instance may have been dequeued by previous while we where initiazing the async hanlde, // so make sure to not wait a task that will never complete. if (_state == State.Waiting) { return(_enterAsync.Task); } } return(Task.FromResult <IDisposable>(new Handle(this))); }
private bool DequeueWaiter(out FastTaskCompletionSource <bool> result) { #if HAS_NO_CONCURRENT_DICT lock (_queue) { if (_queue.Count == 0) { result = null; return(false); } result = _queue.Dequeue(); return(true); } #else return(_queue.TryDequeue(out result)); #endif }
public Task <bool> Wait(CancellationToken cancellationToken) { var src = new FastTaskCompletionSource <bool>(); bool shouldWait; int result; do { if (cancellationToken.IsCancellationRequested) { src.TrySetResult(false); return(src.Task); } shouldWait = true; result = _currentCount; if (result > 0) { shouldWait = false; } else { break; } } while (Interlocked.CompareExchange(ref _currentCount, result - 1, result) != result); if (!shouldWait) { src.TrySetResult(true); } else { #if HAS_NO_CONCURRENT_DICT lock (_queue) #endif { _queue.Enqueue(src); } } return(src.Task); }