Exemple #1
0
        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);
        }
Exemple #2
0
        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);
        }
Exemple #3
0
        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);
        }