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); }
public void SystemMessageList_value_class_must_be_able_to_properly_reverse_contents() { var create0 = new Failed(null, null, 0); var create1 = new Failed(null, null, 1); var create2 = new Failed(null, null, 2); var list = LNil + create0 + create1 + create2; EarliestFirstSystemMessageList listRev = list.Reverse; listRev.IsEmpty.ShouldBeFalse(); listRev.Size.ShouldBe(3); (listRev.Head == create0).ShouldBeTrue(); (listRev.Tail.Head == create1).ShouldBeTrue(); (listRev.Tail.Tail.Head == create2).ShouldBeTrue(); (listRev.Tail.Tail.Tail.Head == null).ShouldBeTrue(); (create0.Next == create1).ShouldBeTrue(); (create1.Next == create2).ShouldBeTrue(); (create2.Next == null).ShouldBeTrue(); }
private void SysMsgInvokeAll(EarliestFirstSystemMessageList messages, int currentState) { while (true) { var rest = messages.Tail; var message = messages.Head; message.Unlink(); try { switch (message) { case SystemMessage sm when ShouldStash(sm, currentState): Stash(message); break; case ActorTaskSchedulerMessage atsm: HandleActorTaskSchedulerMessage(atsm); break; case Failed f: HandleFailed(f); break; case DeathWatchNotification n: WatchedActorTerminated(n.Actor, n.ExistenceConfirmed, n.AddressTerminated); break; case Create c: Create(c.Failure); break; case Watch w: AddWatcher(w.Watchee, w.Watcher); break; case Unwatch uw: RemWatcher(uw.Watchee, uw.Watcher); break; case Recreate r: FaultRecreate(r.Cause); break; case Suspend _: FaultSuspend(); break; case Resume r: FaultResume(r.CausedByFailure); break; case Terminate _: Terminate(); break; case Supervise s: Supervise(s.Child, s.Async); break; default: throw new NotSupportedException($"Unknown message {message.GetType().Name}"); } } catch (Exception cause) { HandleInvokeFailure(cause); } var nextState = CalculateState(); // As each state accepts a strict subset of another state, it is enough to unstash if we "walk up" the state // chain var todo = nextState < currentState ? rest + UnstashAll() : rest; if (IsTerminated) { SendAllToDeadLetters(todo); break; } else if (todo.IsEmpty) { break; } currentState = nextState; messages = todo; } }
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 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); } switch (m) { case ActorTaskSchedulerMessage message: HandleActorTaskSchedulerMessage(message); break; case Failed failed: HandleFailed(failed); break; case DeathWatchNotification notification: { var msg = notification; WatchedActorTerminated(msg.Actor, msg.ExistenceConfirmed, msg.AddressTerminated); break; } case Create create: Create(create.Failure); break; case Watch watch1: { var watch = watch1; AddWatcher(watch.Watchee, watch.Watcher); break; } case Unwatch unwatch1: { var unwatch = unwatch1; RemWatcher(unwatch.Watchee, unwatch.Watcher); break; } case Recreate recreate: FaultRecreate(recreate.Cause); break; case Suspend _: FaultSuspend(); break; case Resume resume: FaultResume(resume.CausedByFailure); break; case Terminate _: Terminate(); break; case Supervise supervise1: { var supervise = supervise1; Supervise(supervise.Child, supervise.Async); break; } default: 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 } } }