FlushResult IWritableBufferAwaiter.GetResult() { var result = new FlushResult(); lock (_sync) { if (!_writerAwaitable.IsCompleted) { PipelinesThrowHelper.ThrowInvalidOperationException(ExceptionResource.GetResultNotCompleted); } // Change the state from to be cancelled -> observed if (_writerAwaitable.ObserveCancelation()) { result.ResultFlags |= ResultFlags.Cancelled; } if (_readerCompletion.IsCompletedOrThrow()) { result.ResultFlags |= ResultFlags.Completed; } } return(result); }
private void PrepareFlush(out CompletionData completionData, out ValueTask <FlushResult> result, CancellationToken cancellationToken) { var completeReader = CommitUnsynchronized(); // AttachToken before completing reader awaiter in case cancellationToken is already completed _writerAwaitable.BeginOperation(cancellationToken, s_signalWriterAwaitable, this); // If the writer is completed (which it will be most of the time) then return a completed ValueTask if (_writerAwaitable.IsCompleted) { FlushResult flushResult = default; GetFlushResult(ref flushResult); result = new ValueTask <FlushResult>(flushResult); } else { // Otherwise it's async result = new ValueTask <FlushResult>(_writer, token: 0); } // Complete reader only if new data was pushed into the pipe // Avoid throwing in between completing the reader and scheduling the callback // if the intent is to allow pipe to continue reading the data if (completeReader) { _readerAwaitable.Complete(out completionData); } else { completionData = default; } // I couldn't find a way for flush to induce backpressure deadlock // if it always adds new data to pipe and wakes up the reader but assert anyway Debug.Assert(_writerAwaitable.IsCompleted || _readerAwaitable.IsCompleted); }
internal FlushResult GetFlushAsyncResult() { var result = new FlushResult(); lock (_sync) { if (!_writerAwaitable.IsCompleted) { ThrowHelper.ThrowInvalidOperationException_GetResultNotCompleted(); } // Change the state from to be canceled -> observed if (_writerAwaitable.ObserveCancelation()) { result._resultFlags |= ResultFlags.Canceled; } if (_readerCompletion.IsCompletedOrThrow()) { result._resultFlags |= ResultFlags.Completed; } } return(result); }