ListenerSecondary - reduce closure allocation
This commit is contained in:
parent
facf3ad0da
commit
34c1a671f0
|
|
@ -17,6 +17,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class ListenerSecondary : ListenerContext, IDisposable
|
public abstract class ListenerSecondary : ListenerContext, IDisposable
|
||||||
{
|
{
|
||||||
|
private string _pipeName;
|
||||||
|
|
||||||
protected ListenerSecondary(ServiceContext serviceContext) : base(serviceContext)
|
protected ListenerSecondary(ServiceContext serviceContext) : base(serviceContext)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
@ -29,97 +31,114 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||||
KestrelThread thread,
|
KestrelThread thread,
|
||||||
RequestDelegate application)
|
RequestDelegate application)
|
||||||
{
|
{
|
||||||
|
_pipeName = pipeName;
|
||||||
ServerAddress = address;
|
ServerAddress = address;
|
||||||
Thread = thread;
|
Thread = thread;
|
||||||
Application = application;
|
Application = application;
|
||||||
|
|
||||||
DispatchPipe = new UvPipeHandle(Log);
|
DispatchPipe = new UvPipeHandle(Log);
|
||||||
|
|
||||||
var tcs = new TaskCompletionSource<int>();
|
var tcs = new TaskCompletionSource<int>(this);
|
||||||
Thread.Post(_ =>
|
Thread.Post(tcs2 => StartCallback(tcs2), tcs);
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
DispatchPipe.Init(Thread.Loop, true);
|
|
||||||
var connect = new UvConnectRequest(Log);
|
|
||||||
connect.Init(Thread.Loop);
|
|
||||||
connect.Connect(
|
|
||||||
DispatchPipe,
|
|
||||||
pipeName,
|
|
||||||
(connect2, status, error, state) =>
|
|
||||||
{
|
|
||||||
connect.Dispose();
|
|
||||||
if (error != null)
|
|
||||||
{
|
|
||||||
tcs.SetException(error);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var ptr = Marshal.AllocHGlobal(4);
|
|
||||||
var buf = Thread.Loop.Libuv.buf_init(ptr, 4);
|
|
||||||
|
|
||||||
DispatchPipe.ReadStart(
|
|
||||||
(_1, _2, _3) => buf,
|
|
||||||
(_1, status2, state2) =>
|
|
||||||
{
|
|
||||||
if (status2 < 0)
|
|
||||||
{
|
|
||||||
if (status2 != Constants.EOF)
|
|
||||||
{
|
|
||||||
Exception ex;
|
|
||||||
Thread.Loop.Libuv.Check(status2, out ex);
|
|
||||||
Log.LogError("DispatchPipe.ReadStart", ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
DispatchPipe.Dispose();
|
|
||||||
Marshal.FreeHGlobal(ptr);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (DispatchPipe.PendingCount() == 0)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var acceptSocket = CreateAcceptSocket();
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
DispatchPipe.Accept(acceptSocket);
|
|
||||||
}
|
|
||||||
catch (UvException ex)
|
|
||||||
{
|
|
||||||
Log.LogError("DispatchPipe.Accept", ex);
|
|
||||||
acceptSocket.Dispose();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var connection = new Connection(this, acceptSocket);
|
|
||||||
connection.Start();
|
|
||||||
},
|
|
||||||
null);
|
|
||||||
|
|
||||||
tcs.SetResult(0);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
DispatchPipe.Dispose();
|
|
||||||
tcs.SetException(ex);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
null);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
DispatchPipe.Dispose();
|
|
||||||
tcs.SetException(ex);
|
|
||||||
}
|
|
||||||
}, null);
|
|
||||||
return tcs.Task;
|
return tcs.Task;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void StartCallback(TaskCompletionSource<int> tcs)
|
||||||
|
{
|
||||||
|
var listener = (ListenerSecondary)tcs.Task.AsyncState;
|
||||||
|
listener.StartedCallback(tcs);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void StartedCallback(TaskCompletionSource<int> tcs)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
DispatchPipe.Init(Thread.Loop, true);
|
||||||
|
var connect = new UvConnectRequest(Log);
|
||||||
|
connect.Init(Thread.Loop);
|
||||||
|
connect.Connect(
|
||||||
|
DispatchPipe,
|
||||||
|
_pipeName,
|
||||||
|
(connect2, status, error, state) => ConnectCallback(connect2, status, error, (TaskCompletionSource<int>)state),
|
||||||
|
tcs);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
DispatchPipe.Dispose();
|
||||||
|
tcs.SetException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ConnectCallback(UvConnectRequest connect, int status, Exception error, TaskCompletionSource<int> tcs)
|
||||||
|
{
|
||||||
|
var listener = (ListenerSecondary)tcs.Task.AsyncState;
|
||||||
|
listener.ConnectedCallback(connect, status, error, tcs);
|
||||||
|
}
|
||||||
|
private void ConnectedCallback(UvConnectRequest connect, int status, Exception error, TaskCompletionSource<int> tcs)
|
||||||
|
{
|
||||||
|
connect.Dispose();
|
||||||
|
if (error != null)
|
||||||
|
{
|
||||||
|
tcs.SetException(error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var ptr = Marshal.AllocHGlobal(4);
|
||||||
|
var buf = Thread.Loop.Libuv.buf_init(ptr, 4);
|
||||||
|
|
||||||
|
DispatchPipe.ReadStart(
|
||||||
|
(handle, status2, state) => buf,
|
||||||
|
(handle, status2, state) => ((ListenerSecondary)state).ReadStartCallback(handle, status2, ptr), this);
|
||||||
|
|
||||||
|
tcs.SetResult(0);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
DispatchPipe.Dispose();
|
||||||
|
tcs.SetException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ReadStartCallback(UvStreamHandle handle, int status, IntPtr ptr)
|
||||||
|
{
|
||||||
|
if (status < 0)
|
||||||
|
{
|
||||||
|
if (status != Constants.EOF)
|
||||||
|
{
|
||||||
|
Exception ex;
|
||||||
|
Thread.Loop.Libuv.Check(status, out ex);
|
||||||
|
Log.LogError("DispatchPipe.ReadStart", ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
DispatchPipe.Dispose();
|
||||||
|
Marshal.FreeHGlobal(ptr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DispatchPipe.PendingCount() == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var acceptSocket = CreateAcceptSocket();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
DispatchPipe.Accept(acceptSocket);
|
||||||
|
}
|
||||||
|
catch (UvException ex)
|
||||||
|
{
|
||||||
|
Log.LogError("DispatchPipe.Accept", ex);
|
||||||
|
acceptSocket.Dispose();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var connection = new Connection(this, acceptSocket);
|
||||||
|
connection.Start();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a socket which can be used to accept an incoming connection
|
/// Creates a socket which can be used to accept an incoming connection
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -133,7 +152,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||||
// the exception that stopped the event loop will never be surfaced.
|
// the exception that stopped the event loop will never be surfaced.
|
||||||
if (Thread.FatalError == null)
|
if (Thread.FatalError == null)
|
||||||
{
|
{
|
||||||
Thread.Send(_ => DispatchPipe.Dispose(), null);
|
Thread.Send(listener => ((ListenerSecondary)listener).DispatchPipe.Dispose(), this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue