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