private void SysMsgInvokeAll(EarliestFirstSystemMessageList messages, int currentState) { var nextState = currentState; var todo = messages; while(true) { var m = todo.Head; todo = messages.Tail; m.Unlink(); try { // TODO: replace with direct cast if (ShouldStash(m, nextState)) { Stash(m); } if (m is ActorTaskSchedulerMessage) HandleActorTaskSchedulerMessage((ActorTaskSchedulerMessage)m); else if (m is Failed) HandleFailed(m as Failed); else if (m is DeathWatchNotification) { var msg = m as DeathWatchNotification; WatchedActorTerminated(msg.Actor, msg.ExistenceConfirmed, msg.AddressTerminated); } else if (m is Create) Create((m as Create).Failure); else if (m is Watch) { var watch = m as Watch; AddWatcher(watch.Watchee, watch.Watcher); } else if (m is Unwatch) { var unwatch = m as Unwatch; RemWatcher(unwatch.Watchee, unwatch.Watcher); } else if (m is Recreate) FaultRecreate((m as Recreate).Cause); else if (m is Suspend) FaultSuspend(); else if (m is Resume) FaultResume((m as Resume).CausedByFailure); else if (m is Terminate) Terminate(); else if (m is Supervise) { var supervise = m as Supervise; Supervise(supervise.Child, supervise.Async); } else { throw new NotSupportedException($"Unknown message {m.GetType().Name}"); } } catch (Exception cause) { HandleInvokeFailure(cause); } nextState = CalculateState(); // As each state accepts a strict subset of another state, it is enough to unstash if we "walk up" the state // chain todo = nextState < currentState ? todo + UnstashAll() : todo; if (IsTerminated) { SendAllToDeadLetters(todo); return; } if (todo.IsEmpty) return; // keep running until the stash is empty } }
private void SendAllToDeadLetters(EarliestFirstSystemMessageList messages) { if (messages.IsEmpty) return; // don't run any of this if there are no system messages do { var msg = messages.Head; messages = messages.Tail; msg.Unlink(); SystemImpl.Provider.DeadLetters.Tell(msg, Self); } while (messages.NonEmpty); }