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)); } }
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)); } }
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)); } }