Esempio n. 1
0
            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);
                }
            }
Esempio n. 2
0
            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);
                }
            }