diff options
Diffstat (limited to 'src/mscorlib/src/System/IO/Stream.cs')
-rw-r--r-- | src/mscorlib/src/System/IO/Stream.cs | 123 |
1 files changed, 114 insertions, 9 deletions
diff --git a/src/mscorlib/src/System/IO/Stream.cs b/src/mscorlib/src/System/IO/Stream.cs index 786dfedef9..82fad24c6d 100644 --- a/src/mscorlib/src/System/IO/Stream.cs +++ b/src/mscorlib/src/System/IO/Stream.cs @@ -41,9 +41,7 @@ namespace System.IO // To implement Async IO operations on streams that don't support async IO - [NonSerialized] private ReadWriteTask _activeReadWriteTask; - [NonSerialized] private SemaphoreSlim _asyncActiveSemaphore; internal SemaphoreSlim EnsureAsyncActiveSemaphoreInitialized() @@ -416,6 +414,33 @@ namespace System.IO : BeginEndReadAsync(buffer, offset, count); } + public virtual ValueTask<int> ReadAsync(Memory<byte> destination, CancellationToken cancellationToken = default(CancellationToken)) + { + if (destination.TryGetArray(out ArraySegment<byte> array)) + { + return new ValueTask<int>(ReadAsync(array.Array, array.Offset, array.Count, cancellationToken)); + } + else + { + byte[] buffer = ArrayPool<byte>.Shared.Rent(destination.Length); + return FinishReadAsync(ReadAsync(buffer, 0, destination.Length, cancellationToken), buffer, destination); + + async ValueTask<int> FinishReadAsync(Task<int> readTask, byte[] localBuffer, Memory<byte> localDestination) + { + try + { + int result = await readTask.ConfigureAwait(false); + new Span<byte>(localBuffer, 0, result).CopyTo(localDestination.Span); + return result; + } + finally + { + ArrayPool<byte>.Shared.Return(localBuffer); + } + } + } + } + [MethodImplAttribute(MethodImplOptions.InternalCall)] private extern bool HasOverriddenBeginEndRead(); @@ -694,8 +719,6 @@ namespace System.IO return WriteAsync(buffer, offset, count, CancellationToken.None); } - - public virtual Task WriteAsync(Byte[] buffer, int offset, int count, CancellationToken cancellationToken) { // If cancellation was requested, bail early with an already completed task. @@ -705,6 +728,32 @@ namespace System.IO : BeginEndWriteAsync(buffer, offset, count); } + public virtual Task WriteAsync(ReadOnlyMemory<byte> source, CancellationToken cancellationToken = default(CancellationToken)) + { + if (source.DangerousTryGetArray(out ArraySegment<byte> array)) + { + return WriteAsync(array.Array, array.Offset, array.Count, cancellationToken); + } + else + { + byte[] buffer = ArrayPool<byte>.Shared.Rent(source.Length); + source.Span.CopyTo(buffer); + return FinishWriteAsync(WriteAsync(buffer, 0, source.Length, cancellationToken), buffer); + + async Task FinishWriteAsync(Task writeTask, byte[] localBuffer) + { + try + { + await writeTask.ConfigureAwait(false); + } + finally + { + ArrayPool<byte>.Shared.Return(localBuffer); + } + } + } + } + [MethodImplAttribute(MethodImplOptions.InternalCall)] private extern bool HasOverriddenBeginEndWrite(); @@ -734,6 +783,22 @@ namespace System.IO public abstract int Read([In, Out] byte[] buffer, int offset, int count); + public virtual int Read(Span<byte> destination) + { + byte[] buffer = ArrayPool<byte>.Shared.Rent(destination.Length); + try + { + int numRead = Read(buffer, 0, destination.Length); + if ((uint)numRead > destination.Length) + { + throw new IOException(SR.IO_StreamTooLong); + } + new Span<byte>(buffer, 0, numRead).CopyTo(destination); + return numRead; + } + finally { ArrayPool<byte>.Shared.Return(buffer); } + } + // Reads one byte from the stream by calling Read(byte[], int, int). // Will return an unsigned byte cast to an int or -1 on end of stream. // This implementation does not perform well because it allocates a new @@ -754,6 +819,17 @@ namespace System.IO public abstract void Write(byte[] buffer, int offset, int count); + public virtual void Write(ReadOnlySpan<byte> source) + { + byte[] buffer = ArrayPool<byte>.Shared.Rent(source.Length); + try + { + source.CopyTo(buffer); + Write(buffer, 0, source.Length); + } + finally { ArrayPool<byte>.Shared.Return(buffer); } + } + // Writes one byte from the stream by calling Write(byte[], int, int). // This implementation does not perform well because it allocates a new // byte[] each time you call it, and should be overridden by any @@ -957,14 +1033,20 @@ namespace System.IO return 0; } + public override int Read(Span<byte> destination) + { + return 0; + } + public override Task<int> ReadAsync(Byte[] buffer, int offset, int count, CancellationToken cancellationToken) { - var nullReadTask = s_nullReadTask; - if (nullReadTask == null) - s_nullReadTask = nullReadTask = new Task<int>(false, 0, (TaskCreationOptions)InternalTaskOptions.DoNotDispose, CancellationToken.None); // benign race condition - return nullReadTask; + return AsyncTaskMethodBuilder<int>.s_defaultResultTask; + } + + public override ValueTask<int> ReadAsync(Memory<byte> destination, CancellationToken cancellationToken = default(CancellationToken)) + { + return new ValueTask<int>(0); } - private static Task<int> s_nullReadTask; public override int ReadByte() { @@ -975,6 +1057,10 @@ namespace System.IO { } + public override void Write(ReadOnlySpan<byte> source) + { + } + public override Task WriteAsync(Byte[] buffer, int offset, int count, CancellationToken cancellationToken) { return cancellationToken.IsCancellationRequested ? @@ -982,6 +1068,13 @@ namespace System.IO Task.CompletedTask; } + public override Task WriteAsync(ReadOnlyMemory<byte> source, CancellationToken cancellationToken = default(CancellationToken)) + { + return cancellationToken.IsCancellationRequested ? + Task.FromCanceled(cancellationToken) : + Task.CompletedTask; + } + public override void WriteByte(byte value) { } @@ -1229,6 +1322,12 @@ namespace System.IO return _stream.Read(bytes, offset, count); } + public override int Read(Span<byte> destination) + { + lock (_stream) + return _stream.Read(destination); + } + public override int ReadByte() { lock (_stream) @@ -1282,6 +1381,12 @@ namespace System.IO _stream.Write(bytes, offset, count); } + public override void Write(ReadOnlySpan<byte> source) + { + lock (_stream) + _stream.Write(source); + } + public override void WriteByte(byte b) { lock (_stream) |