コード例 #1
0
        /// <summary>
        /// Will at least try to process all queued system messages: in case of
        /// failure simply drop and go on to the next, because there is nothing to
        /// restart here (failure is in <see cref="ActorCell"/> somewhere …). In case the mailbox
        /// becomes closed (because of processing a <see cref="Terminate"/> message), dump all
        /// already dequeued message to deadLetters.
        /// </summary>
        private void ProcessAllSystemMessages()
        {
            Exception interruption = null;
            var       messageList  = SystemDrain(SystemMessageList.LNil);

            while (messageList.NonEmpty && !IsClosed())
            {
                var msg = messageList.Head;
                messageList = messageList.Tail;
                msg.Unlink();
                DebugPrint("{0} processing system message {1} with {2}", Actor.Self, msg, string.Join(",", Actor.GetChildren()));
                // we know here that SystemInvoke ensures that only "fatal" exceptions get rethrown
                Actor.SystemInvoke(msg);

                // don't ever execute normal message when system message present!
                if (messageList.IsEmpty && !IsClosed())
                {
                    messageList = SystemDrain(SystemMessageList.LNil);
                }
            }

            /*
             * if we closed the mailbox, we must dump the remaining system messages
             * to deadLetters (this is essential for DeathWatch)
             */
            var dlm = Actor.Dispatcher.Mailboxes.DeadLetterMailbox;

            while (messageList.NonEmpty)
            {
                var msg = messageList.Head;
                messageList = messageList.Tail;
                msg.Unlink();
                try
                {
                    dlm.SystemEnqueue(Actor.Self, msg);
                }
                catch (Exception ex)
                {
                    Actor.System.EventStream.Publish(new Error(ex, GetType().FullName, GetType(), $"error while enqueuing {msg} to deadletters: {ex.Message}"));
                }
            }

            // if we got an interruption while handling system messages, rethrow it
            if (interruption != null)
            {
                // no need to clear interrupted flag in CLR, unlike JVM
                throw interruption;
            }
        }
コード例 #2
0
 /// <summary>
 /// Dispatches a <see cref="ISystemMessage"/> from a mailbox to an <see cref="ActorCell"/>
 /// </summary>
 public virtual void SystemDispatch(ActorCell cell, Envelope envelope)
 {
     cell.SystemInvoke(envelope);
 }
コード例 #3
0
        private void Run()
        {
            if (_isClosed)
            {
                return;
            }

            var throughputDeadlineTime = dispatcher.ThroughputDeadlineTime;

            ActorCell.UseThreadContext(() =>
            {
                //if ThroughputDeadlineTime is enabled, start a stopwatch
                if (throughputDeadlineTime.HasValue && throughputDeadlineTime.Value > 0)
                {
                    if (_deadLineTimer != null)
                    {
                        _deadLineTimer.Restart();
                    }
                    else
                    {
                        _deadLineTimer = Stopwatch.StartNew();
                    }
                }

                //we are about to process all enqueued messages
                hasUnscheduledMessages = false;
                Envelope envelope;

                //start with system messages, they have the highest priority
                while (_systemMessages.TryDequeue(out envelope))
                {
                    Mailbox.DebugPrint(ActorCell.Self + " processing system message " + envelope);
                    // TODO: Add + " with " + ActorCell.GetChildren());
                    ActorCell.SystemInvoke(envelope);
                }

                //we should process x messages in this run
                var left = dispatcher.Throughput;

                //try dequeue a user message
                while (!_isSuspended && !_isClosed && _userMessages.TryDequeue(out envelope))
                {
                    Mailbox.DebugPrint(ActorCell.Self + " processing message " + envelope);

                    //run the receive handler
                    ActorCell.Invoke(envelope);

                    //check if any system message have arrived while processing user messages
                    if (_systemMessages.TryDequeue(out envelope))
                    {
                        //handle system message
                        Mailbox.DebugPrint(ActorCell.Self + " processing system message " + envelope);
                        // TODO: Add + " with " + ActorCell.GetChildren());
                        ActorCell.SystemInvoke(envelope);
                        break;
                    }
                    left--;
                    if (_isClosed)
                    {
                        return;
                    }

                    //if deadline time have expired, stop and break
                    if (throughputDeadlineTime.HasValue && throughputDeadlineTime.Value > 0 &&
                        _deadLineTimer.ElapsedTicks > throughputDeadlineTime.Value)
                    {
                        _deadLineTimer.Stop();
                        break;
                    }

                    //we are done processing messages for this run
                    if (left == 0)
                    {
                        break;
                    }
                }

                Interlocked.Exchange(ref status, MailboxStatus.Idle);

                //there are still messages that needs to be processed
                if (_systemMessages.Count > 0 || (!_isSuspended && _userMessages.Count > 0))
                {
                    //we still need has unscheduled messages for external info.
                    //e.g. repointable actor ref uses it
                    //TODO: will this be enough for external parties to work?
                    hasUnscheduledMessages = true;

                    //this is subject of a race condition
                    //but that doesn't matter, since if the above "if" misses
                    //the "Post" that adds the new message will still schedule
                    //this specific call is just to deal with existing messages
                    //that wasn't scheduled due to dispatcher throughput beeing reached
                    //or system messages arriving during user message processing
                    Schedule();
                }
            });
        }
コード例 #4
0
        /// <summary>
        ///     Runs the Message Pump.
        /// </summary>
        private void Run()
        {
            if (_isClosed)
            {
                return;
            }

            ActorCell.UseThreadContext(() =>
            {
                //if ThroughputDeadlineTime is enabled, start a stopwatch
                if (dispatcher.ThroughputDeadlineTime.HasValue)
                {
                    if (_deadLineTimer != null)
                    {
                        _deadLineTimer.Restart();
                    }
                    else
                    {
                        _deadLineTimer = Stopwatch.StartNew();
                    }
                }

                //we are about to process all enqueued messages
                hasUnscheduledMessages = false;
                Envelope envelope;

                //start with system messages, they have the highest priority
                while (_systemMessages.TryDequeue(out envelope))
                {
                    ActorCell.SystemInvoke(envelope);
                }

                //we should process x messages in this run
                int left = dispatcher.Throughput;

                //try dequeue a user message
                while (_userMessages.TryDequeue(out envelope))
                {
                    //run the receive handler
                    ActorCell.Invoke(envelope);

                    //check if any system message have arrived while processing user messages
                    if (_systemMessages.TryDequeue(out envelope))
                    {
                        //handle system message
                        ActorCell.SystemInvoke(envelope);
                        break;
                    }
                    left--;
                    if (_isClosed)
                    {
                        return;
                    }

                    //if deadline time have expired, stop and break
                    if (dispatcher.ThroughputDeadlineTime.HasValue &&
                        _deadLineTimer.ElapsedTicks > dispatcher.ThroughputDeadlineTime.Value)
                    {
                        _deadLineTimer.Stop();
                        break;
                    }

                    //we are done processing messages for this run
                    if (left == 0)
                    {
                        break;
                    }
                }

                //there are still messages that needs to be processed
                if (_userMessages.Count > 0)
                {
                    hasUnscheduledMessages = true;
                }

                if (hasUnscheduledMessages)
                {
                    dispatcher.Schedule(Run);
                }
                else
                {
                    Interlocked.Exchange(ref status, MailboxStatus.Idle);
                }
            });
        }