public override ValueTask <bool> WaitToReadAsync(CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { return(new ValueTask <bool>(Task.FromCanceled <bool>(cancellationToken))); } BoundedChannel <T> parent = _parent; lock (parent.SyncObj) { parent.AssertInvariants(); // If there are any items available, a read is possible. if (!parent._items.IsEmpty) { return(new ValueTask <bool>(true)); } // There were no items available, so if we're done writing, a read will never be possible. if (parent._doneWriting != null) { return(parent._doneWriting != ChannelUtilities.s_doneWritingSentinel ? new ValueTask <bool>(Task.FromException <bool>(parent._doneWriting)) : new ValueTask <bool>(false)); } // There were no items available, but there could be in the future, so ensure // there's a blocked reader task and return it. var waiter = new AsyncOperation <bool>(parent._runContinuationsAsynchronously, cancellationToken); ChannelUtilities.QueueWaiter(ref _parent._waitingReadersTail, waiter); return(waiter.ValueTaskOfT); } }
public override ValueTask <bool> WaitToReadAsync(CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { return(new ValueTask <bool>(Task.FromCanceled <bool>(cancellationToken))); } if (!_parent._items.IsEmpty) { return(new ValueTask <bool>(true)); } UnboundedChannel <T> parent = _parent; lock (parent.SyncObj) { parent.AssertInvariants(); // Try again to read now that we're synchronized with writers. if (!parent._items.IsEmpty) { return(new ValueTask <bool>(true)); } // There are no items, so if we're done writing, there's never going to be data available. if (parent._doneWriting != null) { return(parent._doneWriting != ChannelUtilities.s_doneWritingSentinel ? new ValueTask <bool>(Task.FromException <bool>(parent._doneWriting)) : new ValueTask <bool>(false)); } // If we're able to use the singleton waiter, do so. if (!cancellationToken.CanBeCanceled) { AsyncOperation <bool> singleton = _waiterSingleton; if (singleton.TryOwnAndReset()) { ChannelUtilities.QueueWaiter(ref parent._waitingReadersTail, singleton); return(singleton.ValueTaskOfT); } } // Otherwise, create and queue a waiter. var waiter = new AsyncOperation <bool>(parent._runContinuationsAsynchronously, cancellationToken); ChannelUtilities.QueueWaiter(ref parent._waitingReadersTail, waiter); return(waiter.ValueTaskOfT); } }