Dispatch user defined callback so it can't block the event loop

This commit is contained in:
Stephen Halter 2015-06-12 17:01:33 -07:00 committed by Brennan
parent adc0310491
commit a992c78548
1 changed files with 23 additions and 24 deletions

View File

@ -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);
}
} }