internal static void PushActorRefToStack(LocalActorRef actorRef) { InterlockedSpin.Swap(ref _stack, st => st == null ? ImmutableStack.Create(actorRef) : st.Push(actorRef)); }
private void HandleTerminateActor() { //TODO: UnwatchWatchedActors(); //Stop all children Children.GetChildrenRefs().ForEach(c => c.Stop()); var actorIsAlreadyTerminating = _actorStatus.IsTerminating; //If we have children we must wait for, then set status to Terminating, so we know what to do when all children have terminated var weHaveChildrenWeMustWaitFor = InterlockedSpin.ConditionallySwap(ref _actorStatus, _ => Children.HasChildrenThatAreTerminating(), _ => ActorStatus.Terminating); if (weHaveChildrenWeMustWaitFor) { if (!actorIsAlreadyTerminating) { //Children were not yet terminated, and this is the first time we try to terminate this actor //We should not not process normal messages while waiting for all children to terminate SuspendThisOnly(); // do not propagate failures during shutdown to the supervisor SetFailedPerpatrator(this); if (_system.Settings.DebugLifecycle) { Publish(new DebugLogEvent(_path.ToString(), SafeGetTypeForLogging(), "Stopping")); } } } else { SetTerminatedChildrenCollection(); FinishTerminate(); } }
internal static void PopActorAndMarkerFromStack() { InterlockedSpin.Swap(ref _stack, st => st == null ? null : st.Peek() == null // if first item is null, i.e. a marker ? st.Pop().Pop() // then pop that value, : st.Pop()); // otherwise pop only the actor }
private bool UpdateChildrenCollection(Func <ChildrenCollection, ChildrenCollection> updater, Predicate <ChildrenCollection> shouldUpdate) { #pragma warning disable 420 //Ok to disregard from CS0420 "a reference to a volatile field will not be treated as volatile" as we're using interlocked underneath, see http://msdn.microsoft.com/en-us/library/4bw5ewxy.aspx return(InterlockedSpin.ConditionallySwap(ref _childrenDoNotCallMeDirectly, c => { if (shouldUpdate(c)) { var newC = updater(c); return Tuple.Create(true, newC); } return Tuple.Create(false, c); })); #pragma warning restore 420 }
private void CreateActorInstanceDueToFailure(Exception cause) { Debug.Assert(_mailbox.IsSuspended, "Mailbox must be suspended during restart, status=" + (_mailbox is MailboxBase ? (_mailbox as MailboxBase).GetMailboxStatusForDebug() : "unknown")); Debug.Assert(_failPerpatrator == this, "Perpetrator should be this instance"); //Stop all children Children.GetChildrenRefs().ForEach(c => c.Stop()); //If we have children we must wait for, then set status to creating, so we know what to do when all children have terminated var weHaveChildrenWeMustWaitFor = InterlockedSpin.ConditionallySwap(ref _actorStatus, _ => Children.HasChildrenThatAreTerminating(), ActorStatus.Creating(cause)); if (!weHaveChildrenWeMustWaitFor) { FinishCreateActorInstanceDueToFailure(cause); } }
private void RecreateActor(Exception cause) { if (_actor == null) { //The actor has not yet been created. We can use a simpler approach Publish(new DebugLogEvent(_path.ToString(), SafeGetTypeForLogging(), "Changing recreate into Create after " + cause)); CreateActorInstanceDueToFailure(cause); } else if (_actorStatus.IsNotCreatingRecreatingOrTerminating) { var failedActor = _actor; if (failedActor != null) { //TODO: Stash optional message object optionalMessage = null; ActorRef optionalSender = null; if (_currentMessage != null) { optionalMessage = _currentMessage.Message; optionalSender = _currentMessage.Sender; } try { try { failedActor.PreRestart(cause, optionalMessage, optionalSender); } catch (Exception e) { Publish(new ErrorLogEvent(_path.ToString(), SafeGetTypeForLogging(failedActor), "Exception thrown during actor.PreRestart()", e)); } } finally { ClearActor(failedActor); } Debug.Assert(_mailbox.IsSuspended, "Mailbox must be suspended during restart, status=" + (_mailbox is MailboxBase ? (_mailbox as MailboxBase).GetMailboxStatusForDebug() : "unknown")); //If we have children we must wait for, then set status to recreating, so we know what to do when all children have terminated var weHaveChildrenWeMustWaitFor = InterlockedSpin.ConditionallySwap(ref _actorStatus, _ => Children.HasChildrenThatAreTerminating(), _ => ActorStatus.Recreating(cause)); if (!weHaveChildrenWeMustWaitFor) { //No children we must wait for. Continue with recreating FinishRecreateActor(failedActor, cause); } } } else { ResumeActor(null); } }
public static void Clear_ForTestingONLY() { InterlockedSpin.Swap(ref _stack, st => st.Clear()); InterlockedSpin.Swap(ref _stack, st => st.Clear()); }
private void UpdateChildrenCollection(Func <ChildrenCollection, ChildrenCollection> updater) { #pragma warning disable 420 //Ok to disregard from CS0420 "a reference to a volatile field will not be treated as volatile" as we're using interlocked underneath, see http://msdn.microsoft.com/en-us/library/4bw5ewxy.aspx InterlockedSpin.Swap(ref _childrenDoNotCallMeDirectly, updater); #pragma warning restore 420 }