private ValueTask <T> ReadAsyncCore(CancellationToken cancellationToken)
        {
            if (cancellationToken.IsCancellationRequested)
            {
                return(new ValueTask <T>(Task.FromCanceled <T>(cancellationToken)));
            }

            lock (SyncObj)
            {
                // Now that we hold the lock, try reading again.
                T item;
                if (TryRead(out item))
                {
                    return(new ValueTask <T>(item));
                }

                // If no more items will be written, fail the read.
                if (_doneWriting != null)
                {
                    return(ChannelUtilities.GetInvalidCompletionValueTask <T>(_doneWriting));
                }

                Debug.Assert(_blockedReader == null || ((_blockedReader as ReaderInteractor <T>)?.Task.IsCanceled ?? false),
                             "Incorrect usage; multiple outstanding reads were issued against this single-consumer channel");

                // Store the reader to be completed by a writer.
                ReaderInteractor <T> reader = ReaderInteractor <T> .Create(_runContinuationsAsynchronously, cancellationToken);

                _blockedReader = reader;
                return(new ValueTask <T>(reader.Task));
            }
        }
Exemple #2
0
        private ValueTask <T> ReadAsync(CancellationToken cancellationToken = default(CancellationToken))
        {
            // Fast-path cancellation check
            if (cancellationToken.IsCancellationRequested)
            {
                return(new ValueTask <T>(Task.FromCanceled <T>(cancellationToken)));
            }

            lock (SyncObj)
            {
                AssertInvariants();

                // If there are any items, hand one back.
                if (!_items.IsEmpty)
                {
                    return(new ValueTask <T>(DequeueItemAndPostProcess()));
                }

                // There weren't any items.  If we're done writing so that there
                // will never be more items, fail.
                if (_doneWriting != null)
                {
                    return(ChannelUtilities.GetInvalidCompletionValueTask <T>(_doneWriting));
                }

                // Otherwise, queue the reader.
                var reader = ReaderInteractor <T> .Create(_runContinuationsAsynchronously, cancellationToken);

                _blockedReaders.EnqueueTail(reader);
                return(new ValueTask <T>(reader.Task));
            }
        }
        private ValueAwaiter <T> GetAwaiterCore()
        {
            lock (SyncObj)
            {
                // Now that we hold the lock, try reading again.
                T item;
                if (TryRead(out item))
                {
                    return(new ValueAwaiter <T>(item));
                }

                // If no more items will be written, fail the read.
                if (_doneWriting != null)
                {
                    return(new ValueAwaiter <T>(ChannelUtilities.GetInvalidCompletionValueTask <T>(_doneWriting)));
                }

                Debug.Assert(_blockedReader == null || ((_blockedReader as ReaderInteractor <T>)?.Task.IsCanceled ?? false),
                             "Incorrect usage; multiple outstanding reads were issued against this single-consumer channel");

                // Store the reader to be completed by a writer.
                _blockedReader = _awaiter ?? (_awaiter = new AutoResetAwaiter <T>(_runContinuationsAsynchronously));
                return(new ValueAwaiter <T>(_awaiter));
            }
        }
Exemple #4
0
        private ValueTask <T> ReadAsyncCore(CancellationToken cancellationToken)
        {
            if (cancellationToken.IsCancellationRequested)
            {
                return(new ValueTask <T>(Task.FromCanceled <T>(cancellationToken)));
            }

            lock (SyncObj)
            {
                AssertInvariants();

                // If there are any items, return one.
                T item;
                if (_items.TryDequeue(out item))
                {
                    // Dequeue an item
                    if (_doneWriting != null && _items.IsEmpty)
                    {
                        // If we've now emptied the items queue and we're not getting any more, complete.
                        ChannelUtilities.Complete(_completion, _doneWriting);
                    }

                    return(new ValueTask <T>(item));
                }

                // There are no items, so if we're done writing, fail.
                if (_doneWriting != null)
                {
                    return(ChannelUtilities.GetInvalidCompletionValueTask <T>(_doneWriting));
                }

                // Otherwise, queue the reader.
                ReaderInteractor <T> reader = ReaderInteractor <T> .Create(_runContinuationsAsynchronously, cancellationToken);

                _blockedReaders.EnqueueTail(reader);
                return(new ValueTask <T>(reader.Task));
            }
        }