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