Small clean up and allocation removals (#21918)

- Remove IAsyncResult implementation
- Make AsyncAcceptContext derive from TaskCompletionSource
This commit is contained in:
David Fowler 2020-05-19 08:18:54 -07:00 committed by GitHub
parent 6c7a8bb397
commit 02bf53de96
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 23 additions and 68 deletions

View File

@ -10,48 +10,23 @@ using Microsoft.AspNetCore.HttpSys.Internal;
namespace Microsoft.AspNetCore.Server.HttpSys
{
internal unsafe class AsyncAcceptContext : IAsyncResult, IDisposable
internal unsafe class AsyncAcceptContext : TaskCompletionSource<RequestContext>, IDisposable
{
internal static readonly IOCompletionCallback IOCallback = new IOCompletionCallback(IOWaitCallback);
private TaskCompletionSource<RequestContext> _tcs;
private HttpSysListener _server;
private NativeRequestContext _nativeRequestContext;
internal AsyncAcceptContext(HttpSysListener server)
{
_server = server;
_tcs = new TaskCompletionSource<RequestContext>();
Server = server;
AllocateNativeRequest();
}
internal Task<RequestContext> Task
{
get
{
return _tcs.Task;
}
}
private TaskCompletionSource<RequestContext> Tcs
{
get
{
return _tcs;
}
}
internal HttpSysListener Server
{
get
{
return _server;
}
}
internal HttpSysListener Server { get; }
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Redirecting to callback")]
[SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "Disposed by callback")]
private static void IOCompleted(AsyncAcceptContext asyncResult, uint errorCode, uint numBytes)
private static void IOCompleted(AsyncAcceptContext asyncContext, uint errorCode, uint numBytes)
{
bool complete = false;
try
@ -59,28 +34,28 @@ namespace Microsoft.AspNetCore.Server.HttpSys
if (errorCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS &&
errorCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_MORE_DATA)
{
asyncResult.Tcs.TrySetException(new HttpSysException((int)errorCode));
asyncContext.TrySetException(new HttpSysException((int)errorCode));
complete = true;
}
else
{
HttpSysListener server = asyncResult.Server;
HttpSysListener server = asyncContext.Server;
if (errorCode == UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS)
{
// at this point we have received an unmanaged HTTP_REQUEST and memoryBlob
// points to it we need to hook up our authentication handling code here.
try
{
if (server.ValidateRequest(asyncResult._nativeRequestContext) && server.ValidateAuth(asyncResult._nativeRequestContext))
if (server.ValidateRequest(asyncContext._nativeRequestContext) && server.ValidateAuth(asyncContext._nativeRequestContext))
{
RequestContext requestContext = new RequestContext(server, asyncResult._nativeRequestContext);
asyncResult.Tcs.TrySetResult(requestContext);
RequestContext requestContext = new RequestContext(server, asyncContext._nativeRequestContext);
asyncContext.TrySetResult(requestContext);
complete = true;
}
}
catch (Exception)
{
server.SendError(asyncResult._nativeRequestContext.RequestId, StatusCodes.Status400BadRequest);
server.SendError(asyncContext._nativeRequestContext.RequestId, StatusCodes.Status400BadRequest);
throw;
}
finally
@ -88,30 +63,30 @@ namespace Microsoft.AspNetCore.Server.HttpSys
// The request has been handed to the user, which means this code can't reuse the blob. Reset it here.
if (complete)
{
asyncResult._nativeRequestContext = null;
asyncContext._nativeRequestContext = null;
}
else
{
asyncResult.AllocateNativeRequest(size: asyncResult._nativeRequestContext.Size);
asyncContext.AllocateNativeRequest(size: asyncContext._nativeRequestContext.Size);
}
}
}
else
{
// (uint)backingBuffer.Length - AlignmentPadding
asyncResult.AllocateNativeRequest(numBytes, asyncResult._nativeRequestContext.RequestId);
asyncContext.AllocateNativeRequest(numBytes, asyncContext._nativeRequestContext.RequestId);
}
// We need to issue a new request, either because auth failed, or because our buffer was too small the first time.
if (!complete)
{
uint statusCode = asyncResult.QueueBeginGetContext();
uint statusCode = asyncContext.QueueBeginGetContext();
if (statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS &&
statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_IO_PENDING)
{
// someother bad error, possible(?) return values are:
// ERROR_INVALID_HANDLE, ERROR_INSUFFICIENT_BUFFER, ERROR_OPERATION_ABORTED
asyncResult.Tcs.TrySetException(new HttpSysException((int)statusCode));
asyncContext.TrySetException(new HttpSysException((int)statusCode));
complete = true;
}
}
@ -123,14 +98,14 @@ namespace Microsoft.AspNetCore.Server.HttpSys
if (complete)
{
asyncResult.Dispose();
asyncContext.Dispose();
}
}
catch (Exception exception)
{
// Logged by caller
asyncResult.Tcs.TrySetException(exception);
asyncResult.Dispose();
asyncContext.TrySetException(exception);
asyncContext.Dispose();
}
}
@ -199,26 +174,6 @@ namespace Microsoft.AspNetCore.Server.HttpSys
_nativeRequestContext = new NativeRequestContext(nativeOverlapped, Server.MemoryPool, size, requestId);
}
public object AsyncState
{
get { return _tcs.Task.AsyncState; }
}
public WaitHandle AsyncWaitHandle
{
get { return ((IAsyncResult)_tcs.Task).AsyncWaitHandle; }
}
public bool CompletedSynchronously
{
get { return ((IAsyncResult)_tcs.Task).CompletedSynchronously; }
}
public bool IsCompleted
{
get { return _tcs.Task.IsCompleted; }
}
public void Dispose()
{
Dispose(true);

View File

@ -279,7 +279,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
/// </summary>
public Task<RequestContext> AcceptAsync()
{
AsyncAcceptContext asyncResult = null;
AsyncAcceptContext acceptContext = null;
try
{
CheckDisposed();
@ -287,14 +287,14 @@ namespace Microsoft.AspNetCore.Server.HttpSys
// prepare the ListenerAsyncResult object (this will have it's own
// event that the user can wait on for IO completion - which means we
// need to signal it when IO completes)
asyncResult = new AsyncAcceptContext(this);
uint statusCode = asyncResult.QueueBeginGetContext();
acceptContext = new AsyncAcceptContext(this);
uint statusCode = acceptContext.QueueBeginGetContext();
if (statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS &&
statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_IO_PENDING)
{
// some other bad error, possible(?) return values are:
// ERROR_INVALID_HANDLE, ERROR_INSUFFICIENT_BUFFER, ERROR_OPERATION_ABORTED
asyncResult.Dispose();
acceptContext.Dispose();
throw new HttpSysException((int)statusCode);
}
}
@ -304,7 +304,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
throw;
}
return asyncResult.Task;
return acceptContext.Task;
}
internal unsafe bool ValidateRequest(NativeRequestContext requestMemory)