Dispatch user defined callback so it can't block the event loop
This commit is contained in:
parent
adc0310491
commit
a992c78548
|
|
@ -4,6 +4,7 @@
|
||||||
using Microsoft.AspNet.Server.Kestrel.Networking;
|
using Microsoft.AspNet.Server.Kestrel.Networking;
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Server.Kestrel.Http
|
namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||||
{
|
{
|
||||||
|
|
@ -37,25 +38,17 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||||
var req = new ThisWriteReq();
|
var req = new ThisWriteReq();
|
||||||
req.Init(_thread.Loop);
|
req.Init(_thread.Loop);
|
||||||
req.Contextualize(this, _socket, buffer, callback, state);
|
req.Contextualize(this, _socket, buffer, callback, state);
|
||||||
_thread.Post(x =>
|
req.Write();
|
||||||
{
|
|
||||||
((ThisWriteReq)x).Write();
|
|
||||||
}, req);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ThisWriteReq : UvWriteReq
|
public class ThisWriteReq : UvWriteReq
|
||||||
{
|
{
|
||||||
private static readonly Action<UvWriteReq, int, Exception, object> _writeCallback = WriteCallback;
|
|
||||||
private static void WriteCallback(UvWriteReq req, int status, Exception error, object state)
|
|
||||||
{
|
|
||||||
((ThisWriteReq)state).OnWrite(req, status, error);
|
|
||||||
}
|
|
||||||
|
|
||||||
SocketOutput _self;
|
SocketOutput _self;
|
||||||
ArraySegment<byte> _buffer;
|
ArraySegment<byte> _buffer;
|
||||||
UvStreamHandle _socket;
|
UvStreamHandle _socket;
|
||||||
Action<Exception, object> _callback;
|
Action<Exception, object> _callback;
|
||||||
object _state;
|
object _state;
|
||||||
|
Exception _callbackError;
|
||||||
|
|
||||||
internal void Contextualize(
|
internal void Contextualize(
|
||||||
SocketOutput socketOutput,
|
SocketOutput socketOutput,
|
||||||
|
|
@ -73,27 +66,33 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||||
|
|
||||||
public void Write()
|
public void Write()
|
||||||
{
|
{
|
||||||
Write(
|
_self._thread.Post(obj =>
|
||||||
_socket,
|
{
|
||||||
new ArraySegment<ArraySegment<byte>>(
|
var req = (ThisWriteReq)obj;
|
||||||
new[]{_buffer}),
|
req.Write(
|
||||||
_writeCallback,
|
req._socket,
|
||||||
this);
|
new ArraySegment<ArraySegment<byte>>(
|
||||||
|
new[] { req._buffer }),
|
||||||
|
(r, status, error, state) => ((ThisWriteReq)state).OnWrite(status, error),
|
||||||
|
req);
|
||||||
|
}, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnWrite(UvWriteReq req, int status, Exception error)
|
private void OnWrite(int status, Exception error)
|
||||||
{
|
{
|
||||||
KestrelTrace.Log.ConnectionWriteCallback(0, status);
|
KestrelTrace.Log.ConnectionWriteCallback(0, status);
|
||||||
//NOTE: pool this?
|
//NOTE: pool this?
|
||||||
|
|
||||||
var callback = _callback;
|
|
||||||
_callback = null;
|
|
||||||
var state = _state;
|
|
||||||
_state = null;
|
|
||||||
|
|
||||||
Dispose();
|
Dispose();
|
||||||
callback(error, state);
|
|
||||||
}
|
// Get off the event loop before calling user code!
|
||||||
|
_callbackError = error;
|
||||||
|
ThreadPool.QueueUserWorkItem(obj =>
|
||||||
|
{
|
||||||
|
var req = (ThisWriteReq)obj;
|
||||||
|
req._callback(req._callbackError, req._state);
|
||||||
|
}, this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue