From 6adeb9be609b013e16cc50d435bea9f0eb3bd8e2 Mon Sep 17 00:00:00 2001 From: Stephen Toub Date: Thu, 10 Oct 2019 06:04:01 -0400 Subject: [PATCH] Change some internal async Task methods to be async ValueTask (dotnet/corefx#40527) We have some internal and private `async Task` methods that are only ever `await`ed. Today there's no benefit to making them `async ValueTask` methods, so we've kept them as `async Task`. However, if we end up changing the implementation of `async ValueTask` to pool underlying objects, there becomes a potential benefit to using `async ValueTask` for these instead of `async Task`. This PR changes those in a variety of libraries where we care more about performance and allocations. There are likely a few more methods we'd want to convert based on profiling, but I believe this represents the bulk of them. Commit migrated from https://github.com/dotnet/corefx/commit/97d9fb9d6c7e1d50f527e290ef8e18767dbc6bbf --- .../src/System/Net/WebSockets/ManagedWebSocket.cs | 20 ++++++++++---------- .../IO/Compression/enc/BrotliStream.Compress.cs | 8 ++++---- .../IO/Compression/DeflateZLib/DeflateStream.cs | 12 ++++++------ .../Http/SocketsHttpHandler/AuthenticationHelper.cs | 2 +- .../SocketsHttpHandler/ChunkedEncodingReadStream.cs | 2 +- .../SocketsHttpHandler/ChunkedEncodingWriteStream.cs | 6 +++--- .../SocketsHttpHandler/ContentLengthReadStream.cs | 2 +- .../SocketsHttpHandler/ContentLengthWriteStream.cs | 6 +++--- .../Net/Http/SocketsHttpHandler/CreditManager.cs | 6 +++--- .../Net/Http/SocketsHttpHandler/Http2Connection.cs | 8 ++++---- .../Net/Http/SocketsHttpHandler/Http2Stream.cs | 10 +++++----- .../Net/Http/SocketsHttpHandler/HttpConnection.cs | 18 +++++++++--------- .../Http/SocketsHttpHandler/HttpConnectionPool.cs | 2 +- .../Http/SocketsHttpHandler/HttpContentReadStream.cs | 4 ++-- .../SocketsHttpHandler/HttpContentWriteStream.cs | 2 +- .../TaskCompletionSourceWithCancellation.cs | 2 +- .../System/Net/Security/SslStream.Implementation.cs | 15 +++++++-------- .../src/System/Net/Security/SslStream.cs | 4 ++-- .../UnitTests/Fakes/FakeSslStream.Implementation.cs | 2 +- .../src/System/Net/WebSockets/WebSocket.cs | 8 ++++---- .../src/System/IO/BufferedStream.cs | 6 +++--- .../src/System/Security/Cryptography/CryptoStream.cs | 8 ++++---- .../src/System/Threading/Channels/ChannelWriter.cs | 4 ++-- 23 files changed, 78 insertions(+), 79 deletions(-) diff --git a/src/libraries/Common/src/System/Net/WebSockets/ManagedWebSocket.cs b/src/libraries/Common/src/System/Net/WebSockets/ManagedWebSocket.cs index 4dae39d..a900ed9 100644 --- a/src/libraries/Common/src/System/Net/WebSockets/ManagedWebSocket.cs +++ b/src/libraries/Common/src/System/Net/WebSockets/ManagedWebSocket.cs @@ -370,7 +370,7 @@ namespace System.Net.WebSockets // Similarly, it should be rare that there are multiple outstanding calls to SendFrameAsync, but if there are, again // fall back to the fallback path. return cancellationToken.CanBeCanceled || !_sendFrameAsyncLock.Wait(0) ? - new ValueTask(SendFrameFallbackAsync(opcode, endOfMessage, payloadBuffer, cancellationToken)) : + SendFrameFallbackAsync(opcode, endOfMessage, payloadBuffer, cancellationToken) : SendFrameLockAcquiredNonCancelableAsync(opcode, endOfMessage, payloadBuffer); } @@ -421,10 +421,10 @@ namespace System.Net.WebSockets } } - return new ValueTask(WaitForWriteTaskAsync(writeTask)); + return WaitForWriteTaskAsync(writeTask); } - private async Task WaitForWriteTaskAsync(ValueTask writeTask) + private async ValueTask WaitForWriteTaskAsync(ValueTask writeTask) { try { @@ -443,7 +443,7 @@ namespace System.Net.WebSockets } } - private async Task SendFrameFallbackAsync(MessageOpcode opcode, bool endOfMessage, ReadOnlyMemory payloadBuffer, CancellationToken cancellationToken) + private async ValueTask SendFrameFallbackAsync(MessageOpcode opcode, bool endOfMessage, ReadOnlyMemory payloadBuffer, CancellationToken cancellationToken) { await _sendFrameAsyncLock.WaitAsync(cancellationToken).ConfigureAwait(false); try @@ -781,7 +781,7 @@ namespace System.Net.WebSockets /// Processes a received close message. /// The message header. /// The received result message. - private async Task HandleReceivedCloseAsync(MessageHeader header, CancellationToken cancellationToken) + private async ValueTask HandleReceivedCloseAsync(MessageHeader header, CancellationToken cancellationToken) { lock (StateUpdateLock) { @@ -848,7 +848,7 @@ namespace System.Net.WebSockets } /// Issues a read on the stream to wait for EOF. - private async Task WaitForServerToCloseConnectionAsync(CancellationToken cancellationToken) + private async ValueTask WaitForServerToCloseConnectionAsync(CancellationToken cancellationToken) { // Per RFC 6455 7.1.1, try to let the server close the connection. We give it up to a second. // We simply issue a read and don't care what we get back; we could validate that we don't get @@ -876,7 +876,7 @@ namespace System.Net.WebSockets /// Processes a received ping or pong message. /// The message header. - private async Task HandleReceivedPingPongAsync(MessageHeader header, CancellationToken cancellationToken) + private async ValueTask HandleReceivedPingPongAsync(MessageHeader header, CancellationToken cancellationToken) { // Consume any (optional) payload associated with the ping/pong. if (header.PayloadLength > 0 && _receiveBufferCount < header.PayloadLength) @@ -949,7 +949,7 @@ namespace System.Net.WebSockets /// The close status code to use. /// The error reason. /// An optional inner exception to include in the thrown exception. - private async Task CloseWithReceiveErrorAndThrowAsync( + private async ValueTask CloseWithReceiveErrorAndThrowAsync( WebSocketCloseStatus closeStatus, WebSocketError error, Exception innerException = null) { // Close the connection if it hasn't already been closed @@ -1132,7 +1132,7 @@ namespace System.Net.WebSockets /// The close status to send. /// The close status description to send. /// The CancellationToken to use to cancel the websocket. - private async Task SendCloseFrameAsync(WebSocketCloseStatus closeStatus, string closeStatusDescription, CancellationToken cancellationToken) + private async ValueTask SendCloseFrameAsync(WebSocketCloseStatus closeStatus, string closeStatusDescription, CancellationToken cancellationToken) { // Close payload is two bytes containing the close status followed by a UTF8-encoding of the status description, if it exists. @@ -1193,7 +1193,7 @@ namespace System.Net.WebSockets _receiveBufferOffset += count; } - private async Task EnsureBufferContainsAsync(int minimumRequiredBytes, CancellationToken cancellationToken, bool throwOnPrematureClosure = true) + private async ValueTask EnsureBufferContainsAsync(int minimumRequiredBytes, CancellationToken cancellationToken, bool throwOnPrematureClosure = true) { Debug.Assert(minimumRequiredBytes <= _receiveBuffer.Length, $"Requested number of bytes {minimumRequiredBytes} must not exceed {_receiveBuffer.Length}"); diff --git a/src/libraries/System.IO.Compression.Brotli/src/System/IO/Compression/enc/BrotliStream.Compress.cs b/src/libraries/System.IO.Compression.Brotli/src/System/IO/Compression/enc/BrotliStream.Compress.cs index dd46856..b800268 100644 --- a/src/libraries/System.IO.Compression.Brotli/src/System/IO/Compression/enc/BrotliStream.Compress.cs +++ b/src/libraries/System.IO.Compression.Brotli/src/System/IO/Compression/enc/BrotliStream.Compress.cs @@ -76,12 +76,12 @@ namespace System.IO.Compression EnsureNoActiveAsyncOperation(); EnsureNotDisposed(); - return new ValueTask(cancellationToken.IsCancellationRequested ? - Task.FromCanceled(cancellationToken) : - WriteAsyncMemoryCore(buffer, cancellationToken)); + return cancellationToken.IsCancellationRequested ? + new ValueTask(Task.FromCanceled(cancellationToken)) : + WriteAsyncMemoryCore(buffer, cancellationToken); } - private async Task WriteAsyncMemoryCore(ReadOnlyMemory buffer, CancellationToken cancellationToken, bool isFinalBlock = false) + private async ValueTask WriteAsyncMemoryCore(ReadOnlyMemory buffer, CancellationToken cancellationToken, bool isFinalBlock = false) { AsyncOperationStarting(); try diff --git a/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateZLib/DeflateStream.cs b/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateZLib/DeflateStream.cs index 9416b37..8af9471 100644 --- a/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateZLib/DeflateStream.cs +++ b/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateZLib/DeflateStream.cs @@ -631,7 +631,7 @@ namespace System.IO.Compression } } - private async Task PurgeBuffersAsync() + private async ValueTask PurgeBuffersAsync() { // Same logic as PurgeBuffers, except with async counterparts. @@ -809,12 +809,12 @@ namespace System.IO.Compression EnsureNoActiveAsyncOperation(); EnsureNotDisposed(); - return new ValueTask(cancellationToken.IsCancellationRequested ? - Task.FromCanceled(cancellationToken) : - WriteAsyncMemoryCore(buffer, cancellationToken)); + return cancellationToken.IsCancellationRequested ? + new ValueTask(Task.FromCanceled(cancellationToken)) : + WriteAsyncMemoryCore(buffer, cancellationToken); } - private async Task WriteAsyncMemoryCore(ReadOnlyMemory buffer, CancellationToken cancellationToken) + private async ValueTask WriteAsyncMemoryCore(ReadOnlyMemory buffer, CancellationToken cancellationToken) { AsyncOperationStarting(); try @@ -838,7 +838,7 @@ namespace System.IO.Compression /// /// Writes the bytes that have already been deflated /// - private async Task WriteDeflaterOutputAsync(CancellationToken cancellationToken) + private async ValueTask WriteDeflaterOutputAsync(CancellationToken cancellationToken) { Debug.Assert(_deflater != null && _buffer != null); while (!_deflater.NeedsInput()) diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/AuthenticationHelper.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/AuthenticationHelper.cs index c310a4d..67b7df5 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/AuthenticationHelper.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/AuthenticationHelper.cs @@ -184,7 +184,7 @@ namespace System.Net.Http SetRequestAuthenticationHeaderValue(request, new AuthenticationHeaderValue(BasicScheme, base64AuthString), isProxyAuth); } - private static async Task TrySetDigestAuthToken(HttpRequestMessage request, NetworkCredential credential, DigestResponse digestResponse, bool isProxyAuth) + private static async ValueTask TrySetDigestAuthToken(HttpRequestMessage request, NetworkCredential credential, DigestResponse digestResponse, bool isProxyAuth) { string parameter = await GetDigestTokenForCredential(credential, request, digestResponse).ConfigureAwait(false); diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ChunkedEncodingReadStream.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ChunkedEncodingReadStream.cs index c526c2f..d28f3d2 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ChunkedEncodingReadStream.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ChunkedEncodingReadStream.cs @@ -429,7 +429,7 @@ namespace System.Net.Http public override bool NeedsDrain => (_connection != null); - public override async Task DrainAsync(int maxDrainBytes) + public override async ValueTask DrainAsync(int maxDrainBytes) { Debug.Assert(_connection != null); diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ChunkedEncodingWriteStream.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ChunkedEncodingWriteStream.cs index 11f37ce..0f2f5e1 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ChunkedEncodingWriteStream.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ChunkedEncodingWriteStream.cs @@ -31,11 +31,11 @@ namespace System.Net.Http // Don't write if nothing was given, especially since we don't want to accidentally send a 0 chunk, // which would indicate end of body. Instead, just ensure no content is stuck in the buffer. connection.FlushAsync() : - new ValueTask(WriteChunkAsync(connection, buffer)); + WriteChunkAsync(connection, buffer); return task; - static async Task WriteChunkAsync(HttpConnection connection, ReadOnlyMemory buffer) + static async ValueTask WriteChunkAsync(HttpConnection connection, ReadOnlyMemory buffer) { // Write chunk length in hex followed by \r\n await connection.WriteHexInt32Async(buffer.Length).ConfigureAwait(false); @@ -47,7 +47,7 @@ namespace System.Net.Http } } - public override async Task FinishAsync() + public override async ValueTask FinishAsync() { // Send 0 byte chunk to indicate end, then final CrLf HttpConnection connection = GetConnectionOrThrow(); diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ContentLengthReadStream.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ContentLengthReadStream.cs index 00345da..7aba584 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ContentLengthReadStream.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ContentLengthReadStream.cs @@ -191,7 +191,7 @@ namespace System.Net.Http public override bool NeedsDrain => (_connection != null); - public override async Task DrainAsync(int maxDrainBytes) + public override async ValueTask DrainAsync(int maxDrainBytes) { Debug.Assert(_connection != null); Debug.Assert(_contentBytesRemaining > 0); diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ContentLengthWriteStream.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ContentLengthWriteStream.cs index 4804427..393271e 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ContentLengthWriteStream.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ContentLengthWriteStream.cs @@ -23,13 +23,13 @@ namespace System.Net.Http // that are still buffered. HttpConnection connection = GetConnectionOrThrow(); Debug.Assert(connection._currentRequest != null); - return new ValueTask(connection.WriteAsync(buffer)); + return connection.WriteAsync(buffer); } - public override Task FinishAsync() + public override ValueTask FinishAsync() { _connection = null; - return Task.CompletedTask; + return default; } } } diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/CreditManager.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/CreditManager.cs index 6337f64..f1bbf34 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/CreditManager.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/CreditManager.cs @@ -64,9 +64,9 @@ namespace System.Net.Http var waiter = new Waiter { Amount = amount }; (_waiters ??= new Queue()).Enqueue(waiter); - return new ValueTask(cancellationToken.CanBeCanceled ? - waiter.WaitWithCancellationAsync(cancellationToken) : - waiter.Task); + return cancellationToken.CanBeCanceled ? + waiter.WaitWithCancellationAsync(cancellationToken) : + new ValueTask(waiter.Task); } } diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Connection.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Connection.cs index e73667b..2f1e6c1 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Connection.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Connection.cs @@ -127,7 +127,7 @@ namespace System.Net.Http private object SyncObject => _httpStreams; - public async Task SetupAsync() + public async ValueTask SetupAsync() { _outgoingBuffer.EnsureAvailableSpace(s_http2ConnectionPreface.Length + FrameHeader.Size + (FrameHeader.SettingLength * 2) + @@ -165,7 +165,7 @@ namespace System.Net.Http _ = ProcessIncomingFramesAsync(); } - private async Task EnsureIncomingBytesAsync(int minReadBytes) + private async ValueTask EnsureIncomingBytesAsync(int minReadBytes) { if (NetEventSource.IsEnabled) Trace($"{nameof(minReadBytes)}={minReadBytes}"); if (_incomingBuffer.ActiveLength >= minReadBytes) @@ -321,7 +321,7 @@ namespace System.Net.Http } } - private async Task ProcessHeadersFrame(FrameHeader frameHeader) + private async ValueTask ProcessHeadersFrame(FrameHeader frameHeader) { if (NetEventSource.IsEnabled) Trace($"{frameHeader}"); Debug.Assert(frameHeader.Type == FrameType.Headers); @@ -783,7 +783,7 @@ namespace System.Net.Http } } - private async Task AcquireWriteLockAsync(CancellationToken cancellationToken) + private async ValueTask AcquireWriteLockAsync(CancellationToken cancellationToken) { Task acquireLockTask = _writerLock.WaitAsync(cancellationToken); if (!acquireLockTask.IsCompletedSuccessfully) diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Stream.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Stream.cs index 06a4e81..f05b316 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Stream.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Stream.cs @@ -269,7 +269,7 @@ namespace System.Net.Http // We can either get 100 response from server and send body // or we may exceed timeout and send request body anyway. // If we get response status >= 300, we will not send the request body. - public async Task WaitFor100ContinueAsync(CancellationToken cancellationToken) + public async ValueTask WaitFor100ContinueAsync(CancellationToken cancellationToken) { Debug.Assert(_request.Content != null); if (NetEventSource.IsEnabled) Trace($"Waiting to send request body content for 100-Continue."); @@ -969,7 +969,7 @@ namespace System.Net.Http } } - private async Task SendDataAsync(ReadOnlyMemory buffer, CancellationToken cancellationToken) + private async ValueTask SendDataAsync(ReadOnlyMemory buffer, CancellationToken cancellationToken) { ReadOnlyMemory remaining = buffer; @@ -1047,11 +1047,11 @@ namespace System.Net.Http // if it is cancelable, then register for the cancellation callback, allocate a task for the asynchronously // completing case, etc. return cancellationToken.CanBeCanceled ? - new ValueTask(GetCancelableWaiterTask(cancellationToken)) : + GetCancelableWaiterTask(cancellationToken) : new ValueTask(this, _waitSource.Version); } - private async Task GetCancelableWaiterTask(CancellationToken cancellationToken) + private async ValueTask GetCancelableWaiterTask(CancellationToken cancellationToken) { using (cancellationToken.UnsafeRegister(s => { @@ -1213,7 +1213,7 @@ namespace System.Net.Http return new ValueTask(Task.FromException(new ObjectDisposedException(nameof(Http2WriteStream)))); } - return new ValueTask(http2Stream.SendDataAsync(buffer, cancellationToken)); + return http2Stream.SendDataAsync(buffer, cancellationToken); } public override Task FlushAsync(CancellationToken cancellationToken) diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnection.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnection.cs index 438903c..1fed738 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnection.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnection.cs @@ -217,7 +217,7 @@ namespace System.Net.Http _readOffset += bytesToConsume; } - private async Task WriteHeadersAsync(HttpHeaders headers, string cookiesFromContainer) + private async ValueTask WriteHeadersAsync(HttpHeaders headers, string cookiesFromContainer) { if (headers.HeaderStore != null) { @@ -278,7 +278,7 @@ namespace System.Net.Http } } - private async Task WriteHostHeaderAsync(Uri uri) + private async ValueTask WriteHostHeaderAsync(Uri uri) { await WriteBytesAsync(KnownHeaders.Host.AsciiBytesWithColonSpace).ConfigureAwait(false); @@ -773,7 +773,7 @@ namespace System.Net.Http private static bool IsLineEmpty(ArraySegment line) => line.Count == 0; - private async Task SendRequestContentAsync(HttpRequestMessage request, HttpContentWriteStream stream, CancellationToken cancellationToken) + private async ValueTask SendRequestContentAsync(HttpRequestMessage request, HttpContentWriteStream stream, CancellationToken cancellationToken) { // Now that we're sending content, prohibit retries on this connection. _canRetry = false; @@ -986,7 +986,7 @@ namespace System.Net.Http _writeOffset += source.Length; } - private async Task WriteAsync(ReadOnlyMemory source) + private async ValueTask WriteAsync(ReadOnlyMemory source) { int remaining = _writeBuffer.Length - _writeOffset; @@ -1063,10 +1063,10 @@ namespace System.Net.Http // There's data in the write buffer and the data we're writing doesn't fit after it. // Do two writes, one to flush the buffer and then another to write the supplied content. - return new ValueTask(FlushThenWriteWithoutBufferingAsync(source)); + return FlushThenWriteWithoutBufferingAsync(source); } - private async Task FlushThenWriteWithoutBufferingAsync(ReadOnlyMemory source) + private async ValueTask FlushThenWriteWithoutBufferingAsync(ReadOnlyMemory source) { await FlushAsync().ConfigureAwait(false); await WriteToStreamAsync(source).ConfigureAwait(false); @@ -1405,7 +1405,7 @@ namespace System.Net.Http } // Throws IOException on EOF. This is only called when we expect more data. - private async Task FillAsync() + private async ValueTask FillAsync() { Debug.Assert(_readAheadTask == null); @@ -1598,7 +1598,7 @@ namespace System.Net.Http return bytesToCopy; } - private async Task CopyFromBufferAsync(Stream destination, int count, CancellationToken cancellationToken) + private async ValueTask CopyFromBufferAsync(Stream destination, int count, CancellationToken cancellationToken) { Debug.Assert(count <= _readLength - _readOffset); @@ -1768,7 +1768,7 @@ namespace System.Net.Http } } - public async Task DrainResponseAsync(HttpResponseMessage response) + public async ValueTask DrainResponseAsync(HttpResponseMessage response) { Debug.Assert(_inUse); diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionPool.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionPool.cs index 4bfc178..843882a 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionPool.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionPool.cs @@ -311,7 +311,7 @@ namespace System.Net.Http // We are at the connection limit. Wait for an available connection or connection count (indicated by null). if (NetEventSource.IsEnabled) Trace("Connection limit reached, waiting for available connection."); - return new ValueTask(waiter.WaitWithCancellationAsync(cancellationToken)); + return waiter.WaitWithCancellationAsync(cancellationToken); } private async ValueTask<(HttpConnectionBase connection, bool isNewConnection, HttpResponseMessage failureResponse)> diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpContentReadStream.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpContentReadStream.cs index 8911933..11ac180 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpContentReadStream.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpContentReadStream.cs @@ -29,10 +29,10 @@ namespace System.Net.Http protected bool IsDisposed => _disposed == 1; - public virtual Task DrainAsync(int maxDrainBytes) + public virtual ValueTask DrainAsync(int maxDrainBytes) { Debug.Fail($"DrainAsync should not be called for this response stream: {GetType()}"); - return Task.FromResult(false); + return new ValueTask(false); } protected override void Dispose(bool disposing) diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpContentWriteStream.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpContentWriteStream.cs index 537ee6f..3c53400 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpContentWriteStream.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpContentWriteStream.cs @@ -36,7 +36,7 @@ namespace System.Net.Http public sealed override Task CopyToAsync(Stream destination, int bufferSize, CancellationToken cancellationToken) => throw new NotSupportedException(); - public abstract Task FinishAsync(); + public abstract ValueTask FinishAsync(); } } } diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/TaskCompletionSourceWithCancellation.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/TaskCompletionSourceWithCancellation.cs index 0c954c4..4d2cba1 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/TaskCompletionSourceWithCancellation.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/TaskCompletionSourceWithCancellation.cs @@ -20,7 +20,7 @@ namespace System.Net.Http TrySetCanceled(_cancellationToken); } - public async Task WaitWithCancellationAsync(CancellationToken cancellationToken) + public async ValueTask WaitWithCancellationAsync(CancellationToken cancellationToken) { _cancellationToken = cancellationToken; using (cancellationToken.UnsafeRegister(s => ((TaskCompletionSourceWithCancellation)s).OnCancellation(), this)) diff --git a/src/libraries/System.Net.Security/src/System/Net/Security/SslStream.Implementation.cs b/src/libraries/System.Net.Security/src/System/Net/Security/SslStream.Implementation.cs index 9403b2d..be9300a 100644 --- a/src/libraries/System.Net.Security/src/System/Net/Security/SslStream.Implementation.cs +++ b/src/libraries/System.Net.Security/src/System/Net/Security/SslStream.Implementation.cs @@ -1177,7 +1177,7 @@ namespace System.Net.Security } } - private async Task WriteAsyncChunked(TWriteAdapter writeAdapter, ReadOnlyMemory buffer) + private async ValueTask WriteAsyncChunked(TWriteAdapter writeAdapter, ReadOnlyMemory buffer) where TWriteAdapter : struct, ISslWriteAdapter { do @@ -1185,7 +1185,6 @@ namespace System.Net.Security int chunkBytes = Math.Min(buffer.Length, MaxDataSize); await WriteSingleChunk(writeAdapter, buffer.Slice(0, chunkBytes)).ConfigureAwait(false); buffer = buffer.Slice(chunkBytes); - } while (buffer.Length != 0); } @@ -1197,7 +1196,7 @@ namespace System.Net.Security if (!ioSlot.IsCompletedSuccessfully) { // Operation is async and has been queued, return. - return new ValueTask(WaitForWriteIOSlot(writeAdapter, ioSlot, buffer)); + return WaitForWriteIOSlot(writeAdapter, ioSlot, buffer); } byte[] rentedBuffer = ArrayPool.Shared.Rent(buffer.Length + FrameOverhead); @@ -1222,16 +1221,16 @@ namespace System.Net.Security } else { - return new ValueTask(CompleteAsync(t, rentedBuffer)); + return CompleteAsync(t, rentedBuffer); } - async Task WaitForWriteIOSlot(TWriteAdapter wAdapter, Task lockTask, ReadOnlyMemory buff) + async ValueTask WaitForWriteIOSlot(TWriteAdapter wAdapter, Task lockTask, ReadOnlyMemory buff) { await lockTask.ConfigureAwait(false); await WriteSingleChunk(wAdapter, buff).ConfigureAwait(false); } - async Task CompleteAsync(ValueTask writeTask, byte[] bufferToReturn) + async ValueTask CompleteAsync(ValueTask writeTask, byte[] bufferToReturn) { try { @@ -1464,7 +1463,7 @@ namespace System.Net.Security } } - private async Task WriteAsyncInternal(TWriteAdapter writeAdapter, ReadOnlyMemory buffer) + private async ValueTask WriteAsyncInternal(TWriteAdapter writeAdapter, ReadOnlyMemory buffer) where TWriteAdapter : struct, ISslWriteAdapter { ThrowIfExceptionalOrNotAuthenticatedOrShutdown(); @@ -1484,7 +1483,7 @@ namespace System.Net.Security { ValueTask t = buffer.Length < MaxDataSize ? WriteSingleChunk(writeAdapter, buffer) : - new ValueTask(WriteAsyncChunked(writeAdapter, buffer)); + WriteAsyncChunked(writeAdapter, buffer); await t.ConfigureAwait(false); } catch (Exception e) diff --git a/src/libraries/System.Net.Security/src/System/Net/Security/SslStream.cs b/src/libraries/System.Net.Security/src/System/Net/Security/SslStream.cs index f9d2dc1..75d4c0f 100644 --- a/src/libraries/System.Net.Security/src/System/Net/Security/SslStream.cs +++ b/src/libraries/System.Net.Security/src/System/Net/Security/SslStream.cs @@ -765,7 +765,7 @@ namespace System.Net.Security ValidateParameters(buffer, offset, count); SslWriteSync writeAdapter = new SslWriteSync(this); - WriteAsyncInternal(writeAdapter, new ReadOnlyMemory(buffer, offset, count)).GetAwaiter().GetResult(); + WriteAsyncInternal(writeAdapter, new ReadOnlyMemory(buffer, offset, count)).AsTask().GetAwaiter().GetResult(); } public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback asyncCallback, object asyncState) @@ -803,7 +803,7 @@ namespace System.Net.Security { ThrowIfExceptionalOrNotAuthenticated(); SslWriteAsync writeAdapter = new SslWriteAsync(this, cancellationToken); - return new ValueTask(WriteAsyncInternal(writeAdapter, buffer)); + return WriteAsyncInternal(writeAdapter, buffer); } public override Task ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) diff --git a/src/libraries/System.Net.Security/tests/UnitTests/Fakes/FakeSslStream.Implementation.cs b/src/libraries/System.Net.Security/tests/UnitTests/Fakes/FakeSslStream.Implementation.cs index 7fb43f70..dbeaead 100644 --- a/src/libraries/System.Net.Security/tests/UnitTests/Fakes/FakeSslStream.Implementation.cs +++ b/src/libraries/System.Net.Security/tests/UnitTests/Fakes/FakeSslStream.Implementation.cs @@ -37,7 +37,7 @@ namespace System.Net.Security { } - private Task WriteAsyncInternal(TWriteAdapter writeAdapter, ReadOnlyMemory buffer) + private ValueTask WriteAsyncInternal(TWriteAdapter writeAdapter, ReadOnlyMemory buffer) where TWriteAdapter : struct, ISslWriteAdapter => default; private ValueTask ReadAsyncInternal(TReadAdapter adapter, Memory buffer) => default; diff --git a/src/libraries/System.Net.WebSockets/src/System/Net/WebSockets/WebSocket.cs b/src/libraries/System.Net.WebSockets/src/System/Net/WebSockets/WebSocket.cs index 88da035..0dc6f28 100644 --- a/src/libraries/System.Net.WebSockets/src/System/Net/WebSockets/WebSocket.cs +++ b/src/libraries/System.Net.WebSockets/src/System/Net/WebSockets/WebSocket.cs @@ -55,11 +55,11 @@ namespace System.Net.WebSockets } public virtual ValueTask SendAsync(ReadOnlyMemory buffer, WebSocketMessageType messageType, bool endOfMessage, CancellationToken cancellationToken) => - new ValueTask(MemoryMarshal.TryGetArray(buffer, out ArraySegment arraySegment) ? - SendAsync(arraySegment, messageType, endOfMessage, cancellationToken) : - SendWithArrayPoolAsync(buffer, messageType, endOfMessage, cancellationToken)); + MemoryMarshal.TryGetArray(buffer, out ArraySegment arraySegment) ? + new ValueTask(SendAsync(arraySegment, messageType, endOfMessage, cancellationToken)) : + SendWithArrayPoolAsync(buffer, messageType, endOfMessage, cancellationToken); - private async Task SendWithArrayPoolAsync( + private async ValueTask SendWithArrayPoolAsync( ReadOnlyMemory buffer, WebSocketMessageType messageType, bool endOfMessage, diff --git a/src/libraries/System.Runtime.Extensions/src/System/IO/BufferedStream.cs b/src/libraries/System.Runtime.Extensions/src/System/IO/BufferedStream.cs index 5c497ad..2702709 100644 --- a/src/libraries/System.Runtime.Extensions/src/System/IO/BufferedStream.cs +++ b/src/libraries/System.Runtime.Extensions/src/System/IO/BufferedStream.cs @@ -431,7 +431,7 @@ namespace System.IO _stream.Flush(); } - private async Task FlushWriteAsync(CancellationToken cancellationToken) + private async ValueTask FlushWriteAsync(CancellationToken cancellationToken) { Debug.Assert(_stream != null); Debug.Assert(_readPos == 0 && _readLen == 0, @@ -1117,7 +1117,7 @@ namespace System.IO } // Delegate to the async implementation. - return new ValueTask(WriteToUnderlyingStreamAsync(buffer, cancellationToken, semaphoreLockTask)); + return WriteToUnderlyingStreamAsync(buffer, cancellationToken, semaphoreLockTask); } /// BufferedStream should be as thin a wrapper as possible. We want WriteAsync to delegate to @@ -1125,7 +1125,7 @@ namespace System.IO /// in terms of the other. This allows BufferedStream to affect the semantics of the stream it wraps as /// little as possible. /// - private async Task WriteToUnderlyingStreamAsync( + private async ValueTask WriteToUnderlyingStreamAsync( ReadOnlyMemory buffer, CancellationToken cancellationToken, Task semaphoreLockTask) { Debug.Assert(_stream != null); diff --git a/src/libraries/System.Security.Cryptography.Primitives/src/System/Security/Cryptography/CryptoStream.cs b/src/libraries/System.Security.Cryptography.Primitives/src/System/Security/Cryptography/CryptoStream.cs index 00ee3db..65d084b 100644 --- a/src/libraries/System.Security.Cryptography.Primitives/src/System/Security/Cryptography/CryptoStream.cs +++ b/src/libraries/System.Security.Cryptography.Primitives/src/System/Security/Cryptography/CryptoStream.cs @@ -101,9 +101,9 @@ namespace System.Security.Cryptography // byte[] ciphertext = ms.ToArray(); // cs.Close(); public void FlushFinalBlock() => - FlushFinalBlockAsync(useAsync: false).GetAwaiter().GetResult(); + FlushFinalBlockAsync(useAsync: false).AsTask().GetAwaiter().GetResult(); - private async Task FlushFinalBlockAsync(bool useAsync) + private async ValueTask FlushFinalBlockAsync(bool useAsync) { if (_finalBlockTransformed) throw new NotSupportedException(SR.Cryptography_CryptoStream_FlushFinalBlockTwice); @@ -496,7 +496,7 @@ namespace System.Security.Cryptography public override void Write(byte[] buffer, int offset, int count) { CheckWriteArguments(buffer, offset, count); - WriteAsyncCore(buffer, offset, count, default(CancellationToken), useAsync: false).GetAwaiter().GetResult(); + WriteAsyncCore(buffer, offset, count, default(CancellationToken), useAsync: false).AsTask().GetAwaiter().GetResult(); } private void CheckWriteArguments(byte[] buffer, int offset, int count) @@ -511,7 +511,7 @@ namespace System.Security.Cryptography throw new ArgumentException(SR.Argument_InvalidOffLen); } - private async Task WriteAsyncCore(byte[] buffer, int offset, int count, CancellationToken cancellationToken, bool useAsync) + private async ValueTask WriteAsyncCore(byte[] buffer, int offset, int count, CancellationToken cancellationToken, bool useAsync) { // write <= count bytes to the output stream, transforming as we go. // Basic idea: using bytes in the _InputBuffer first, make whole blocks, diff --git a/src/libraries/System.Threading.Channels/src/System/Threading/Channels/ChannelWriter.cs b/src/libraries/System.Threading.Channels/src/System/Threading/Channels/ChannelWriter.cs index a13dfb2..42623af 100644 --- a/src/libraries/System.Threading.Channels/src/System/Threading/Channels/ChannelWriter.cs +++ b/src/libraries/System.Threading.Channels/src/System/Threading/Channels/ChannelWriter.cs @@ -44,7 +44,7 @@ namespace System.Threading.Channels return cancellationToken.IsCancellationRequested ? new ValueTask(Task.FromCanceled(cancellationToken)) : TryWrite(item) ? default : - new ValueTask(WriteAsyncCore(item, cancellationToken)); + WriteAsyncCore(item, cancellationToken); } catch (Exception e) { @@ -52,7 +52,7 @@ namespace System.Threading.Channels } } - private async Task WriteAsyncCore(T innerItem, CancellationToken ct) + private async ValueTask WriteAsyncCore(T innerItem, CancellationToken ct) { while (await WaitToWriteAsync(ct).ConfigureAwait(false)) { -- 2.7.4