Beispiel #1
0
        internal ValueTask <FlushResult> FlushAsync(CancellationToken cancellationToken)
        {
            CompletionData completionData;
            CancellationTokenRegistration cancellationTokenRegistration;
            ValueTask <FlushResult>       result;

            lock (_sync)
            {
                CommitUnsynchronized();

                // AttachToken before completing reader awaiter in case cancellationToken is already completed
                cancellationTokenRegistration = _writerAwaitable.AttachToken(cancellationToken, s_signalWriterAwaitable, this);

                _readerAwaitable.Complete(out completionData);

                // If the writer is completed (which it will be most of the time) the return a completed ValueTask
                if (_writerAwaitable.IsCompleted)
                {
                    var flushResult = new FlushResult();
                    GetFlushResult(ref flushResult);
                    result = new ValueTask <FlushResult>(flushResult);
                }
                else
                {
                    // Otherwise it's async
                    result = new ValueTask <FlushResult>(_writer, token: 0);
                }
            }

            cancellationTokenRegistration.Dispose();

            TrySchedule(_readerScheduler, completionData);

            return(result);
        }
Beispiel #2
0
        internal ValueTask <FlushResult> FlushAsync(CancellationToken cancellationToken)
        {
            CompletionData completionData;
            CancellationTokenRegistration cancellationTokenRegistration;
            ValueTask <FlushResult>       result;

            lock (_sync)
            {
                var wasEmpty = CommitUnsynchronized();

                // AttachToken before completing reader awaiter in case cancellationToken is already completed
                cancellationTokenRegistration = _writerAwaitable.AttachToken(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)
                {
                    var flushResult = new FlushResult();
                    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 (!wasEmpty)
                {
                    _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);
            }

            cancellationTokenRegistration.Dispose();

            TrySchedule(_readerScheduler, completionData);

            return(result);
        }
Beispiel #3
0
        ReadableBufferAwaitable IPipeReader.ReadAsync(CancellationToken token)
        {
            CancellationTokenRegistration cancellationTokenRegistration;

            if (_readerCompletion.IsCompleted)
            {
                PipelinesThrowHelper.ThrowInvalidOperationException(ExceptionResource.NoReadingAllowed, _readerCompletion.Location);
            }
            lock (_sync)
            {
                cancellationTokenRegistration = _readerAwaitable.AttachToken(token, _signalReaderAwaitable, this);
            }
            cancellationTokenRegistration.Dispose();
            return(new ReadableBufferAwaitable(this));
        }
Beispiel #4
0
        internal PipeAwaiter <ReadResult> ReadAsync(CancellationToken token)
        {
            CancellationTokenRegistration cancellationTokenRegistration;

            if (_readerCompletion.IsCompleted)
            {
                ThrowHelper.ThrowInvalidOperationException_NoReadingAllowed();
            }
            lock (_sync)
            {
                cancellationTokenRegistration = _readerAwaitable.AttachToken(token, s_signalReaderAwaitable, this);
            }
            cancellationTokenRegistration.Dispose();
            return(new PipeAwaiter <ReadResult>(_reader));
        }
Beispiel #5
0
        internal WritableBufferAwaitable FlushAsync(CancellationToken cancellationToken = default)
        {
            Action awaitable;
            CancellationTokenRegistration cancellationTokenRegistration;

            lock (_sync)
            {
                if (_writingState.IsActive)
                {
                    // Commit the data as not already committed
                    CommitUnsynchronized();
                }

                awaitable = _readerAwaitable.Complete();

                cancellationTokenRegistration = _writerAwaitable.AttachToken(cancellationToken, _signalWriterAwaitable, this);
            }

            cancellationTokenRegistration.Dispose();

            TrySchedule(_readerScheduler, awaitable);

            return(new WritableBufferAwaitable(this));
        }
Beispiel #6
0
        internal PipeAwaiter <FlushResult> FlushAsync(CancellationToken cancellationToken)
        {
            Action awaitable;
            CancellationTokenRegistration cancellationTokenRegistration;

            lock (_sync)
            {
                if (_writingHead != null)
                {
                    // Commit the data as not already committed
                    CommitUnsynchronized();
                }

                awaitable = _readerAwaitable.Complete();

                cancellationTokenRegistration = _writerAwaitable.AttachToken(cancellationToken, s_signalWriterAwaitable, this);
            }

            cancellationTokenRegistration.Dispose();

            TrySchedule(_readerScheduler, awaitable);

            return(new PipeAwaiter <FlushResult>(_writer));
        }
Beispiel #7
0
        internal ValueTask <FlushResult> FlushAsync(CancellationToken cancellationToken)
        {
            CompletionData completionData;
            CancellationTokenRegistration cancellationTokenRegistration;

            lock (_sync)
            {
                if (_writingHead != null)
                {
                    // Commit the data as not already committed
                    CommitUnsynchronized();
                }

                _readerAwaitable.Complete(out completionData);

                cancellationTokenRegistration = _writerAwaitable.AttachToken(cancellationToken, s_signalWriterAwaitable, this);
            }

            cancellationTokenRegistration.Dispose();

            TrySchedule(_readerScheduler, completionData);

            return(new ValueTask <FlushResult>(_writer, token: 0));
        }