/// <summary> /// Processes the contents of the mailbox /// </summary> public void Run() { try { if (!IsClosed()) // Volatile read, needed here { Actor.UseThreadContext(() => { ProcessAllSystemMessages(); // First, deal with any system messages ProcessMailbox(); // Then deal with messages }); } } finally { SetAsIdle(); // Volatile write, needed here Dispatcher.RegisterForExecution(this, false, false); // schedule to run again if there are more messages, possibly } }
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()); dispatcher.SystemDispatch(ActorCell, 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 dispatcher.Dispatch(ActorCell, 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()); dispatcher.SystemDispatch(ActorCell, envelope); break; } left--; if (_isClosed) { return; } //if deadline time have expired, stop and break if (throughputDeadlineTime.HasValue && throughputDeadlineTime.Value > 0 && _deadLineTimer.Elapsed.Ticks > 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 being reached //or system messages arriving during user message processing Schedule(); } }); }
/// <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); } }); }