Beispiel #1
0
        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);
        }
Beispiel #2
0
        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);
        }
Beispiel #4
0
        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);
            }
        }
Beispiel #5
0
        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);
            }
        }
Beispiel #6
0
        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);
            }
        }
Beispiel #7
0
        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;
 }
 public static void EnableSynchronousPost(MessageHandleContext currentAtomicContext)
 {
     s_synchronousPostEnabled = true;
     s_currentAtomicContext = currentAtomicContext;
 }
 public ActorSynchronizationContext(MessageHandleContext context)
 {
     _context = context;
 }
Beispiel #12
0
        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);
                }
            }
        }
Beispiel #13
0
        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);
                    });
                }
            }
        }