Esempio n. 1
0
        public void FlushAsyncReturnsNonCompletedSizeWhenCommitOverTheLimit()
        {
            PipeWriter writableBuffer            = _pipe.Writer.WriteEmpty(64);
            PipeAwaiter <FlushResult> flushAsync = writableBuffer.FlushAsync();

            Assert.False(flushAsync.IsCompleted);
        }
Esempio n. 2
0
        public async Task AdvanceEmptyBufferAfterWritingResetsAwaitable()
        {
            byte[] bytes = Encoding.ASCII.GetBytes("Hello World");

            await _pipe.Writer.WriteAsync(bytes);

            ReadResult result = await _pipe.Reader.ReadAsync();

            ReadOnlySequence <byte> buffer = result.Buffer;

            Assert.Equal(11, buffer.Length);
            Assert.True(buffer.IsSingleSegment);
            var array = new byte[11];

            buffer.First.Span.CopyTo(array);
            Assert.Equal("Hello World", Encoding.ASCII.GetString(array));

            _pipe.Reader.AdvanceTo(buffer.End);

            // Now write 0 and advance 0
            await _pipe.Writer.WriteAsync(new byte[] { });

            result = await _pipe.Reader.ReadAsync();

            _pipe.Reader.AdvanceTo(result.Buffer.End);

            PipeAwaiter <ReadResult> awaitable = _pipe.Reader.ReadAsync();

            Assert.False(awaitable.IsCompleted);
        }
Esempio n. 3
0
        public async Task EmptyBufferStartCrossingSegmentBoundaryIsTreatedLikeAndEnd()
        {
            Memory <byte> memory = _pipe.Writer.GetMemory();

            // Append one full segment to a pipe
            _pipe.Writer.Write(memory.Span);
            _pipe.Writer.Commit();
            await _pipe.Writer.FlushAsync();

            // Consume entire segment
            ReadResult result = await _pipe.Reader.ReadAsync();

            _pipe.Reader.AdvanceTo(result.Buffer.End);

            // Append empty segment
            _pipe.Writer.GetMemory(1);
            _pipe.Writer.Commit();
            await _pipe.Writer.FlushAsync();

            result = await _pipe.Reader.ReadAsync();

            Assert.True(result.Buffer.IsEmpty);
            Assert.Equal(result.Buffer.Start, result.Buffer.End);

            _pipe.Writer.GetMemory();
            _pipe.Reader.AdvanceTo(result.Buffer.Start);
            PipeAwaiter <ReadResult> awaitable = _pipe.Reader.ReadAsync();

            Assert.False(awaitable.IsCompleted);
            _pipe.Writer.Commit();
        }
        public void FlushAsyncCancellationDeadlock()
        {
            var cts  = new CancellationTokenSource();
            var cts2 = new CancellationTokenSource();
            var e    = new ManualResetEventSlim();

            PipeAwaiter <ReadResult> awaiter = Pipe.Reader.ReadAsync(cts.Token);

            awaiter.OnCompleted(
                () => {
                // We are on cancellation thread and need to wait untill another ReadAsync call
                // takes pipe state lock
                e.Wait();
                // Make sure we had enough time to reach _cancellationTokenRegistration.Dispose
                Thread.Sleep(100);
                // Try to take pipe state lock
                Pipe.Reader.ReadAsync();
            });

            // Start a thread that would run cancellation calbacks
            Task cancellationTask = Task.Run(() => cts.Cancel());
            // Start a thread that would call ReadAsync with different token
            // and block on _cancellationTokenRegistration.Dispose
            Task blockingTask = Task.Run(
                () => {
                e.Set();
                Pipe.Reader.ReadAsync(cts2.Token);
            });

            bool completed = Task.WhenAll(cancellationTask, blockingTask).Wait(TimeSpan.FromSeconds(10));

            Assert.True(completed);
        }
        public async Task CancellingBeforeAdvance()
        {
            byte[]     bytes  = Encoding.ASCII.GetBytes("Hello World");
            PipeWriter output = Pipe.Writer;

            output.Write(bytes);
            await output.FlushAsync();

            ReadResult result = await Pipe.Reader.ReadAsync();

            ReadOnlySequence <byte> buffer = result.Buffer;

            Assert.Equal(11, buffer.Length);
            Assert.False(result.IsCanceled);
            Assert.True(buffer.IsSingleSegment);
            var array = new byte[11];

            buffer.First.Span.CopyTo(array);
            Assert.Equal("Hello World", Encoding.ASCII.GetString(array));

            Pipe.Reader.CancelPendingRead();

            Pipe.Reader.AdvanceTo(buffer.End);

            PipeAwaiter <ReadResult> awaitable = Pipe.Reader.ReadAsync();

            Assert.True(awaitable.IsCompleted);

            result = await awaitable;

            Assert.True(result.IsCanceled);

            Pipe.Reader.AdvanceTo(result.Buffer.Start, result.Buffer.Start);
        }
Esempio n. 6
0
        public async Task AdvanceResetsCommitHeadIndex()
        {
            _pipe.Writer.GetMemory(1);
            _pipe.Writer.Advance(100);
            await _pipe.Writer.FlushAsync();

            // Advance to the end
            ReadResult readResult = await _pipe.Reader.ReadAsync();

            _pipe.Reader.AdvanceTo(readResult.Buffer.End);

            // Try reading, it should block
            PipeAwaiter <ReadResult> awaitable = _pipe.Reader.ReadAsync();

            Assert.False(awaitable.IsCompleted);

            // Unblock without writing anything
            _pipe.Writer.GetMemory();
            await _pipe.Writer.FlushAsync();

            Assert.True(awaitable.IsCompleted);

            // Advance to the end should reset awaitable
            readResult = await awaitable;
            _pipe.Reader.AdvanceTo(readResult.Buffer.End);

            // Try reading, it should block
            awaitable = _pipe.Reader.ReadAsync();
            Assert.False(awaitable.IsCompleted);
        }
Esempio n. 7
0
        public void FlushAsyncReturnsCompletedTaskWhenSizeLessThenLimit()
        {
            PipeWriter writableBuffer            = _pipe.Writer.WriteEmpty(32);
            PipeAwaiter <FlushResult> flushAsync = writableBuffer.FlushAsync();

            Assert.True(flushAsync.IsCompleted);
            FlushResult flushResult = flushAsync.GetResult();

            Assert.False(flushResult.IsCompleted);
        }
Esempio n. 8
0
        public void FlushAsync_ReturnsCompletedTaskWhenMaxSizeIfZero()
        {
            PipeWriter writableBuffer           = _pipe.Writer.WriteEmpty(1);
            PipeAwaiter <FlushResult> flushTask = writableBuffer.FlushAsync();

            Assert.True(flushTask.IsCompleted);

            writableBuffer = _pipe.Writer.WriteEmpty(1);
            flushTask      = writableBuffer.FlushAsync();
            Assert.True(flushTask.IsCompleted);
        }
Esempio n. 9
0
        public void FlushAsyncReturnsCanceledIfCancelledBeforeFlush()
        {
            PipeWriter writableBuffer = Pipe.Writer.WriteEmpty(MaximumSizeHigh);

            Pipe.Writer.CancelPendingFlush();

            PipeAwaiter <FlushResult> flushAsync = writableBuffer.FlushAsync();

            Assert.True(flushAsync.IsCompleted);
            FlushResult flushResult = flushAsync.GetResult();

            Assert.True(flushResult.IsCanceled);
        }
Esempio n. 10
0
        public void FlushAsyncReturnsCompletedIfReaderCompletes()
        {
            PipeWriter writableBuffer            = _pipe.Writer.WriteEmpty(64);
            PipeAwaiter <FlushResult> flushAsync = writableBuffer.FlushAsync();

            Assert.False(flushAsync.IsCompleted);

            _pipe.Reader.Complete();

            Assert.True(flushAsync.IsCompleted);
            FlushResult flushResult = flushAsync.GetResult();

            Assert.True(flushResult.IsCompleted);
        }
Esempio n. 11
0
        public void FlushAsyncAwaitableDoesNotCompletesWhenReaderAdvancesUnderHight()
        {
            PipeWriter writableBuffer            = _pipe.Writer.WriteEmpty(64);
            PipeAwaiter <FlushResult> flushAsync = writableBuffer.FlushAsync();

            Assert.False(flushAsync.IsCompleted);

            ReadResult       result   = _pipe.Reader.ReadAsync().GetAwaiter().GetResult();
            SequencePosition consumed = result.Buffer.GetPosition(32);

            _pipe.Reader.AdvanceTo(consumed, consumed);

            Assert.False(flushAsync.IsCompleted);
        }
        private async Task ApplyBackpressureAsync(PipeAwaiter <FlushResult> flushTask)
        {
            Log.ConnectionPause(ConnectionId);
            _socket.ReadStop();

            var result = await flushTask;

            // If the reader isn't complete or cancelled then resume reading
            if (!result.IsCompleted && !result.IsCanceled)
            {
                Log.ConnectionResume(ConnectionId);
                StartReading();
            }
        }
Esempio n. 13
0
        public void AdvanceThrowsIfFlushActiveAndNotConsumedPastThreshold()
        {
            PipeWriter writableBuffer            = _pipe.Writer.WriteEmpty(64);
            PipeAwaiter <FlushResult> flushAsync = writableBuffer.FlushAsync();

            Assert.False(flushAsync.IsCompleted);

            ReadResult       result   = _pipe.Reader.ReadAsync().GetAwaiter().GetResult();
            SequencePosition consumed = result.Buffer.GetPosition(31);

            Assert.Throws <InvalidOperationException>(() => _pipe.Reader.AdvanceTo(consumed, result.Buffer.End));

            _pipe.Reader.AdvanceTo(result.Buffer.End, result.Buffer.End);
        }
Esempio n. 14
0
        private static async Task Continue(PipeAwaiter <FlushResult> awaitable, ReadOperation operation)
        {
            // Keep reading once we get the completion
            var flushResult = await awaitable;

            if (!flushResult.IsCompleted)
            {
                operation.Read();
            }
            else
            {
                operation.Writer.Complete();

                operation.Dispose();
            }
        }
        public void ReadAsyncReturnsIsCancelOnCancelPendingReadBeforeGetResult()
        {
            PipeAwaiter <ReadResult> awaitable = Pipe.Reader.ReadAsync();

            Assert.False(awaitable.IsCompleted);
            awaitable.OnCompleted(() => { });

            Pipe.Writer.WriteAsync(new byte[] { });
            Pipe.Reader.CancelPendingRead();

            Assert.True(awaitable.IsCompleted);

            ReadResult result = awaitable.GetResult();

            Assert.True(result.IsCanceled);
        }
Esempio n. 16
0
        public void FlushAsyncReturnsIsCancelOnCancelPendingFlushBeforeGetResult()
        {
            PipeWriter writableBuffer           = Pipe.Writer.WriteEmpty(MaximumSizeHigh);
            PipeAwaiter <FlushResult> awaitable = writableBuffer.FlushAsync();

            Assert.False(awaitable.IsCompleted);
            awaitable.OnCompleted(() => { });

            Pipe.Reader.AdvanceTo(Pipe.Reader.ReadAsync().GetResult().Buffer.End);
            Pipe.Writer.CancelPendingFlush();

            Assert.True(awaitable.IsCompleted);

            FlushResult result = awaitable.GetResult();

            Assert.True(result.IsCanceled);
        }
Esempio n. 17
0
        public void FlushAsyncCompletedAfterPreCancellation()
        {
            PipeWriter writableBuffer = Pipe.Writer.WriteEmpty(1);

            Pipe.Writer.CancelPendingFlush();

            PipeAwaiter <FlushResult> flushAsync = writableBuffer.FlushAsync();

            Assert.True(flushAsync.IsCompleted);

            FlushResult flushResult = flushAsync.GetResult();

            Assert.True(flushResult.IsCanceled);

            flushAsync = writableBuffer.FlushAsync();

            Assert.True(flushAsync.IsCompleted);
        }
        public async Task AdvanceShouldResetStateIfReadCanceled()
        {
            Pipe.Reader.CancelPendingRead();

            ReadResult result = await Pipe.Reader.ReadAsync();

            ReadOnlySequence <byte> buffer = result.Buffer;

            Pipe.Reader.AdvanceTo(buffer.End);

            Assert.False(result.IsCompleted);
            Assert.True(result.IsCanceled);
            Assert.True(buffer.IsEmpty);

            PipeAwaiter <ReadResult> awaitable = Pipe.Reader.ReadAsync();

            Assert.False(awaitable.IsCompleted);
        }
Esempio n. 19
0
        public async Task FlushCallbackRunsOnWriterScheduler()
        {
            using (var pool = new TestMemoryPool())
            {
                using (var scheduler = new ThreadScheduler())
                {
                    var pipe = new Pipe(
                        new PipeOptions(
                            pool,
                            resumeWriterThreshold: 32,
                            pauseWriterThreshold: 64,
                            readerScheduler: PipeScheduler.Inline,
                            writerScheduler: scheduler));

                    PipeWriter writableBuffer            = pipe.Writer.WriteEmpty(64);
                    PipeAwaiter <FlushResult> flushAsync = writableBuffer.FlushAsync();

                    Assert.False(flushAsync.IsCompleted);

                    Func <Task> doWrite = async() =>
                    {
                        int oid = Thread.CurrentThread.ManagedThreadId;

                        await flushAsync;

                        Assert.NotEqual(oid, Thread.CurrentThread.ManagedThreadId);

                        pipe.Writer.Complete();

                        Assert.Equal(Thread.CurrentThread.ManagedThreadId, scheduler.Thread.ManagedThreadId);
                    };

                    Task writing = doWrite();

                    ReadResult result = await pipe.Reader.ReadAsync();

                    pipe.Reader.AdvanceTo(result.Buffer.End, result.Buffer.End);

                    pipe.Reader.Complete();

                    await writing;
                }
            }
        }
        public void GetResultThrowsIfReadAsyncCanceledBeforeOnCompleted()
        {
            var onCompletedCalled       = false;
            var cancellationTokenSource = new CancellationTokenSource();

            PipeAwaiter <ReadResult> awaiter = Pipe.Reader.ReadAsync(cancellationTokenSource.Token);
            bool awaiterIsCompleted          = awaiter.IsCompleted;

            cancellationTokenSource.Cancel();

            awaiter.OnCompleted(
                () => {
                onCompletedCalled = true;
                Assert.Throws <OperationCanceledException>(() => awaiter.GetResult());
            });

            Assert.False(awaiterIsCompleted);
            Assert.True(onCompletedCalled);
        }
        public void ReadAsyncCompletedAfterPreCancellation()
        {
            Pipe.Reader.CancelPendingRead();
            Pipe.Writer.WriteAsync(new byte[] { 1, 2, 3 }).GetAwaiter().GetResult();

            PipeAwaiter <ReadResult> awaitable = Pipe.Reader.ReadAsync();

            Assert.True(awaitable.IsCompleted);

            ReadResult result = awaitable.GetResult();

            Assert.True(result.IsCanceled);

            awaitable = Pipe.Reader.ReadAsync();

            Assert.True(awaitable.IsCompleted);

            Pipe.Reader.AdvanceTo(awaitable.GetResult().Buffer.End);
        }
Esempio n. 22
0
        public void GetResultThrowsIfFlushAsyncCancelledBeforeOnCompleted()
        {
            var        onCompletedCalled       = false;
            var        cancellationTokenSource = new CancellationTokenSource();
            PipeWriter buffer = Pipe.Writer.WriteEmpty(MaximumSizeHigh);

            PipeAwaiter <FlushResult> awaiter = buffer.FlushAsync(cancellationTokenSource.Token);
            bool awaiterIsCompleted           = awaiter.IsCompleted;

            cancellationTokenSource.Cancel();

            awaiter.OnCompleted(
                () => {
                onCompletedCalled = true;
                Assert.Throws <OperationCanceledException>(() => awaiter.GetResult());
            });

            Assert.False(awaiterIsCompleted);
            Assert.True(onCompletedCalled);
        }
Esempio n. 23
0
        private async Task FlushAsyncAwaited(PipeAwaiter <FlushResult> awaitable, CancellationToken cancellationToken)
        {
            // https://github.com/dotnet/corefxlab/issues/1334
            // Since the flush awaitable doesn't currently support multiple awaiters
            // we need to use a task to track the callbacks.
            // All awaiters get the same task
            lock (_flushLock)
            {
                if (_flushTcs == null || _flushTcs.Task.IsCompleted)
                {
                    _flushTcs = new TaskCompletionSource <object>();

                    awaitable.OnCompleted(_flushCompleted);
                }
            }

            await _flushTcs.Task;

            cancellationToken.ThrowIfCancellationRequested();
        }
        public void OnWriterCompletedRanBeforeReadContinuation()
        {
            var callbackRan     = false;
            var continuationRan = false;
            var pipe            = new Pipe(new PipeOptions(_pool));

            pipe.Reader.OnWriterCompleted(
                (exception, state) => {
                callbackRan = true;
                Assert.False(continuationRan);
            }, null);

            PipeAwaiter <ReadResult> awaiter = pipe.Reader.ReadAsync();

            Assert.False(awaiter.IsCompleted);
            awaiter.OnCompleted(() => { continuationRan = true; });
            pipe.Writer.Complete();

            Assert.True(callbackRan);
        }
Esempio n. 25
0
        public void AwaitingReadAsyncAwaitableTwiceCompletesWriterWithException()
        {
            async Task Await(PipeAwaiter <ReadResult> a)
            {
                await a;
            }

            PipeAwaiter <ReadResult> awaitable = Pipe.Reader.ReadAsync();

            Task task1 = Await(awaitable);
            Task task2 = Await(awaitable);

            Assert.Equal(true, task1.IsCompleted);
            Assert.Equal(true, task1.IsFaulted);
            Assert.Equal("Concurrent reads or writes are not supported.", task1.Exception.InnerExceptions[0].Message);

            Assert.Equal(true, task2.IsCompleted);
            Assert.Equal(true, task2.IsFaulted);
            Assert.Equal("Concurrent reads or writes are not supported.", task2.Exception.InnerExceptions[0].Message);
        }
        public void ReadAsyncNotCompletedAfterCancellationTokenCanceled()
        {
            var onCompletedCalled = false;
            var cts = new CancellationTokenSource();
            PipeAwaiter <ReadResult> awaitable = Pipe.Reader.ReadAsync(cts.Token);

            Assert.False(awaitable.IsCompleted);
            awaitable.OnCompleted(
                () => {
                onCompletedCalled = true;
                Assert.True(awaitable.IsCompleted);

                Assert.Throws <OperationCanceledException>(() => awaitable.GetResult());

                awaitable = Pipe.Reader.ReadAsync();
                Assert.False(awaitable.IsCompleted);
            });

            cts.Cancel();
            Assert.True(onCompletedCalled);
        }
        public void ReadAsyncNotCompletedAfterCancellation()
        {
            var onCompletedCalled = false;
            PipeAwaiter <ReadResult> awaitable = Pipe.Reader.ReadAsync();

            Assert.False(awaitable.IsCompleted);
            awaitable.OnCompleted(
                () => {
                onCompletedCalled = true;
                Assert.True(awaitable.IsCompleted);

                ReadResult readResult = awaitable.GetResult();
                Assert.True(readResult.IsCanceled);

                awaitable = Pipe.Reader.ReadAsync();
                Assert.False(awaitable.IsCompleted);
            });

            Pipe.Reader.CancelPendingRead();
            Assert.True(onCompletedCalled);
        }
Esempio n. 28
0
        public async Task DefaultWriterSchedulerRunsOnThreadPool()
        {
            using (var pool = new TestMemoryPool())
            {
                var pipe = new Pipe(
                    new PipeOptions(
                        pool,
                        resumeWriterThreshold: 32,
                        pauseWriterThreshold: 64
                        ));

                PipeWriter writableBuffer            = pipe.Writer.WriteEmpty(64);
                PipeAwaiter <FlushResult> flushAsync = writableBuffer.FlushAsync();

                Assert.False(flushAsync.IsCompleted);

                var id = 0;

                Func <Task> doWrite = async() =>
                {
                    await flushAsync;

                    pipe.Writer.Complete();

                    Assert.True(Thread.CurrentThread.IsThreadPoolThread);
                };

                Task writing = doWrite();

                ReadResult result = await pipe.Reader.ReadAsync();

                id = Thread.CurrentThread.ManagedThreadId;

                pipe.Reader.AdvanceTo(result.Buffer.End, result.Buffer.End);

                pipe.Reader.Complete();

                await writing;
            }
        }
        public void OnReaderCompletedRanBeforeFlushContinuation()
        {
            var callbackRan     = false;
            var continuationRan = false;
            var pipe            = new Pipe(new PipeOptions(_pool, pauseWriterThreshold: 5));

            pipe.Writer.OnReaderCompleted(
                (exception, state) => {
                Assert.False(continuationRan);
                callbackRan = true;
            }, null);

            PipeWriter buffer = pipe.Writer.WriteEmpty(10);
            PipeAwaiter <FlushResult> awaiter = buffer.FlushAsync();

            Assert.False(awaiter.IsCompleted);
            awaiter.OnCompleted(() => { continuationRan = true; });
            pipe.Reader.Complete();

            Assert.True(callbackRan);
            pipe.Writer.Complete();
        }
Esempio n. 30
0
        public void FlushAsyncAwaitableResetsOnCommit()
        {
            PipeWriter writableBuffer            = _pipe.Writer.WriteEmpty(64);
            PipeAwaiter <FlushResult> flushAsync = writableBuffer.FlushAsync();

            Assert.False(flushAsync.IsCompleted);

            ReadResult       result   = _pipe.Reader.ReadAsync().GetAwaiter().GetResult();
            SequencePosition consumed = result.Buffer.GetPosition(33);

            _pipe.Reader.AdvanceTo(consumed, consumed);

            Assert.True(flushAsync.IsCompleted);
            FlushResult flushResult = flushAsync.GetResult();

            Assert.False(flushResult.IsCompleted);

            writableBuffer = _pipe.Writer.WriteEmpty(64);
            flushAsync     = writableBuffer.FlushAsync();

            Assert.False(flushAsync.IsCompleted);
        }