private bool TryHandleMessage(object message) { var messageType = message.GetType(); var handlerItem = _handler.MessageDispatcher.GetHandler(messageType); if (handlerItem == null) { // if generic argument, try to instantiate a generic handler by the given payload type. if (messageType.IsGenericType) { var genericHandlerItem = _handler.MessageDispatcher.GetHandler(messageType.GetGenericTypeDefinition()); if (genericHandlerItem != null) { handlerItem = genericHandlerItem.GenericHandlerBuilder(messageType); _handler.MessageDispatcher.AddHandler(messageType, handlerItem); } } if (handlerItem == null) { return(false); } } if (handlerItem.AsyncHandler != null) { var context = new MessageHandleContext { Self = Self, Sender = base.Sender, CancellationToken = CancellationToken }; if (handlerItem.IsReentrant) { _activeReentrantCount += 1; } else { BecomeStacked(OnReceiveInAtomicTask); _currentAtomicContext = context; } using (new SynchronizationContextSwitcher(new ActorSynchronizationContext(context))) { handlerItem.AsyncHandler(this, message) .ContinueWith(t => OnTaskCompleted(t.Exception, handlerItem.IsReentrant), TaskContinuationOptions.ExecuteSynchronously); } } else { handlerItem.Handler(this, message); } return(true); }
private void InitializeActorState() { _cancellationTokenSource = new CancellationTokenSource(); _activeReentrantCount = 0; _activeReentrantAsyncRequestSet = null; _currentAtomicContext = null; _requestWaiter = null; if (_handler.PerInstanceFilterCreators.Count > 0) { _perInstanceFilterList = new InterfacedActorPerInstanceFilterList(this, _handler.PerInstanceFilterCreators); } }
public void OnResponseMessage(ResponseMessage response, MessageHandleContext currentAtomicContext) { ResponseWaitingItem waitingItem; if (_responseWaitingItems.TryRemove(response.RequestId, out waitingItem) == false) { return; } // Because OnResponseMessage is always called in a message loop of actor, // it's safe to run post callback synchronously if possible. // This optimization remove one message hop. ActorSynchronizationContext.EnableSynchronousPost(currentAtomicContext); waitingItem.ResponseHandler(waitingItem.TaskCompletionSource, response); }
private void InvokeOnStart(bool restarted) { var context = new MessageHandleContext { Self = Self, Sender = base.Sender, CancellationToken = CancellationToken }; BecomeStacked(OnReceiveInAtomicTask); _currentAtomicContext = context; using (new SynchronizationContextSwitcher(new ActorSynchronizationContext(context))) { OnStart(restarted).ContinueWith( t => OnTaskCompleted(t.Exception, false), TaskContinuationOptions.ExecuteSynchronously); } }
private void InvokeOnGracefulStop() { var context = new MessageHandleContext { Self = Self, CancellationToken = CancellationToken }; BecomeStacked(OnReceiveInAtomicTask); _currentAtomicContext = context; using (new SynchronizationContextSwitcher(new ActorSynchronizationContext(context))) { OnGracefulStop().ContinueWith( t => OnTaskCompleted(t.Exception, false, stopOnCompleted: true), TaskContinuationOptions.ExecuteSynchronously); } }
private void OnTaskCompleted(Exception exception, bool isReentrant, bool stopOnCompleted = false) { if (isReentrant) { _activeReentrantCount -= 1; } else { _currentAtomicContext = null; UnbecomeStacked(); Stash.UnstashAll(); } if (exception != null) { ((ActorCell)Context).InvokeFailure(exception); } else if (stopOnCompleted) { Context.Stop(Self); } }
private void OnTaskRunMessage(TaskRunMessage taskRunMessage) { var context = new MessageHandleContext { Self = Self, Sender = base.Sender, CancellationToken = CancellationToken }; if (taskRunMessage.IsReentrant) { _activeReentrantCount += 1; } else { BecomeStacked(OnReceiveInAtomicTask); _currentAtomicContext = context; } using (new SynchronizationContextSwitcher(new ActorSynchronizationContext(context))) { taskRunMessage.Function() .ContinueWith(t => OnTaskCompleted(t.Exception, taskRunMessage.IsReentrant), TaskContinuationOptions.ExecuteSynchronously); } }
public static void EnableSynchronousPost(MessageHandleContext currentAtomicContext) { s_synchronousPostEnabled = true; s_currentAtomicContext = currentAtomicContext; }
public ActorSynchronizationContext(MessageHandleContext context) { _context = context; }
private void OnNotificationMessage(NotificationMessage notification) { object observerContext = null; if (notification.ObserverId != 0) { observerContext = EnsureObserverMap().GetContext(notification.ObserverId); if (observerContext == null) { // because it could be a removed observer, doesn't log anything. return; } } if (notification.InvokePayload == null) { Context.System.EventStream.Publish(new Event.Warning( Self.Path.ToString(), GetType(), $"Receives a bad notification with no payload from {Sender}")); return; } var payloadType = notification.InvokePayload.GetType(); var handlerItem = _handler.NotificationDispatcher.GetHandler(payloadType); if (handlerItem == null) { // if generic argument, try to instantiate a generic handler by the given payload type. if (payloadType.IsGenericType) { var genericHandlerItem = _handler.NotificationDispatcher.GetHandler(payloadType.GetGenericTypeDefinition()); if (genericHandlerItem != null) { handlerItem = genericHandlerItem.GenericHandlerBuilder(payloadType); _handler.NotificationDispatcher.AddHandler(payloadType, handlerItem); } } // oops, no handler. if (handlerItem == null) { Context.System.EventStream.Publish(new Event.Warning( Self.Path.ToString(), GetType(), $"Cannot find a handler for notification {notification.InvokePayload.GetType()} from {Sender}")); return; } } if (handlerItem.Handler != null) { // sync handle try { _observerContext = observerContext; handlerItem.Handler(this, notification); } finally { _observerContext = null; } } else { // async handle var context = new MessageHandleContext { Self = Self, Sender = base.Sender, CancellationToken = CancellationToken, ObserverContext = observerContext }; if (handlerItem.IsReentrant) { _activeReentrantCount += 1; } else { BecomeStacked(OnReceiveInAtomicTask); _currentAtomicContext = context; } using (new SynchronizationContextSwitcher(new ActorSynchronizationContext(context))) { handlerItem.AsyncHandler(this, notification) .ContinueWith(t => OnTaskCompleted(t.Exception, handlerItem.IsReentrant), TaskContinuationOptions.ExecuteSynchronously); } } }
private void OnRequestMessage(RequestMessage request) { var sender = base.Sender; if (request.InvokePayload == null) { sender.Tell(new ResponseMessage { RequestId = request.RequestId, Exception = new RequestMessageException("Empty payload") }); Context.System.EventStream.Publish(new Event.Warning( Self.Path.ToString(), GetType(), $"Receives a bad request without payload from {Sender}")); return; } var payloadType = request.InvokePayload.GetType(); var handlerItem = _handler.RequestDispatcher.GetHandler(payloadType); if (handlerItem == null) { // if generic argument, try to instantiate a generic handler by the given payload type. if (payloadType.IsGenericType) { var genericHandlerItem = _handler.RequestDispatcher.GetHandler(payloadType.GetGenericTypeDefinition()); if (genericHandlerItem != null) { handlerItem = genericHandlerItem.GenericHandlerBuilder(payloadType); _handler.RequestDispatcher.AddHandler(payloadType, handlerItem); } } // oops, no handler. if (handlerItem == null) { sender.Tell(new ResponseMessage { RequestId = request.RequestId, Exception = new RequestHandlerNotFoundException() }); Context.System.EventStream.Publish(new Event.Warning( Self.Path.ToString(), GetType(), $"Cannot find a handler for request {payloadType} from {Sender}")); return; } } if (handlerItem.Handler != null) { // sync handle handlerItem.Handler(this, request, (response, exception) => { if (request.RequestId != 0) { sender.Tell(response); } if (exception != null) { ((ActorCell)Context).InvokeFailure(exception); } }); } else { // async handle var context = new MessageHandleContext { Self = Self, Sender = base.Sender, CancellationToken = CancellationToken, RequestId = request.RequestId }; if (handlerItem.IsReentrant) { _activeReentrantCount += 1; if (request.RequestId != 0) { if (_activeReentrantAsyncRequestSet == null) { _activeReentrantAsyncRequestSet = new HashSet <MessageHandleContext>(); } _activeReentrantAsyncRequestSet.Add(context); } } else { BecomeStacked(OnReceiveInAtomicTask); _currentAtomicContext = context; } using (new SynchronizationContextSwitcher(new ActorSynchronizationContext(context))) { var requestId = request.RequestId; var isReentrant = handlerItem.IsReentrant; handlerItem.AsyncHandler(this, request, (response, exception) => { if (requestId != 0) { if (isReentrant) { _activeReentrantAsyncRequestSet.Remove(context); } sender.Tell(response); } OnTaskCompleted(exception, isReentrant); }); } } }