예제 #1
0
        private void ProcessMailbox(int left, long deadlineTicks)
        {
            while (ShouldProcessMessage())
            {
                if (!TryDequeue(out var next))
                {
                    return;
                }

                DebugPrint("{0} processing message {1}", Actor.Self, next);

                // not going to bother catching ThreadAbortExceptions here, since they'll get rethrown anyway
                Actor.Invoke(next);
                ProcessAllSystemMessages();
                if (left > 1 && (Dispatcher.ThroughputDeadlineTime.HasValue == false || (MonotonicClock.GetTicks() - deadlineTicks) < 0))
                {
                    left = left - 1;
                    continue;
                }
                break;
            }
        }
예제 #2
0
 /// <summary>
 /// Dispatches a user-defined message from a mailbox to an <see cref="ActorCell"/>
 /// </summary>
 public virtual void Dispatch(ActorCell cell, Envelope envelope)
 {
     cell.Invoke(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);
                }
            });
        }