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

View File

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