private async Task <int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken, bool sync) { using (sync ? _mutex.Lock(cancellationToken) : await _mutex.LockAsync(cancellationToken).ConfigureAwait(false)) { while (Empty && !_completed) { if (sync) { _notEmptyOrCompleted.Wait(cancellationToken); } else { await _notEmptyOrCompleted.WaitAsync(cancellationToken).ConfigureAwait(false); } } cancellationToken.ThrowIfCancellationRequested(); if (AvailableToRead == 0) { return(0); } // Copy the data from the stream var bytesToCopy = Math.Min(count, AvailableToRead); Array.Copy(_data.First.Value, _headDataBytesRead, buffer, offset, bytesToCopy); // Remove those bytes from the stream if (bytesToCopy == AvailableToRead) { _data.RemoveFirst(); _headDataBytesRead = 0; } else { _headDataBytesRead += bytesToCopy; } _currentBytes -= bytesToCopy; ReaderPosition += bytesToCopy; _notFullOrCompleted.Notify(); return(bytesToCopy); } }
private async Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken, bool sync) { using (sync ? _mutex.Lock(cancellationToken) : await _mutex.LockAsync(cancellationToken).ConfigureAwait(false)) { while (count != 0) { while (Full && !_completed) { if (sync) { _notFullOrCompleted.Wait(cancellationToken); } else { await _notFullOrCompleted.WaitAsync(cancellationToken).ConfigureAwait(false); } } if (_completed) { throw new OperationCanceledException("Stream has been closed for writing."); } cancellationToken.ThrowIfCancellationRequested(); // Copy the data var bytesToCopy = Math.Min(count, AvailableToWrite); var data = new byte[bytesToCopy]; Array.Copy(buffer, offset, data, 0, bytesToCopy); // Add it to the stream _data.AddLast(data); _currentBytes += bytesToCopy; WriterPosition += bytesToCopy; // Adjust status of current operation offset += bytesToCopy; count -= bytesToCopy; _notEmptyOrCompleted.Notify(); } } }