private async Task HandleReentryTriggerAsync(object[] args, StateRepresentation representativeState, Transition transition) { StateRepresentation representation; transition = await representativeState.ExitAsync(transition); var newRepresentation = GetRepresentation(transition.Destination); if (!transition.Source.Equals(transition.Destination)) { // Then Exit the final superstate transition = new Transition(transition.Destination, transition.Destination, transition.Trigger, args); await newRepresentation.ExitAsync(transition); await _onTransitionedEvent.InvokeAsync(transition); representation = await EnterStateAsync(newRepresentation, transition, args); await _onTransitionCompletedEvent.InvokeAsync(transition); } else { await _onTransitionedEvent.InvokeAsync(transition); representation = await EnterStateAsync(newRepresentation, transition, args); await _onTransitionCompletedEvent.InvokeAsync(transition); } State = representation.UnderlyingState; }
public void MoveToState(TState state, StateTransitionOption option = StateTransitionOption.Default) { lock (syncRoot) { if (!IsEnabled) { return; } StateRepresentation <TState, TTrigger> rep; if (configDictionary.TryGetValue(state, out rep)) { if ((option & StateTransitionOption.CurrentStateExitTransition) == StateTransitionOption.CurrentStateExitTransition) { ExecuteAction(CurrentStateRepresentation.OnExitAction); } if ((option & StateTransitionOption.NewStateEntryTransition) == StateTransitionOption.NewStateEntryTransition) { ExecuteAction(rep.OnEntryAction); } CurrentStateRepresentation = rep; } else { throw new InvalidOperationException("Invalid state: " + state.ToString()); } } }
private void HandleTransitioningTrigger(object[] args, StateRepresentation representativeState, Transition transition) { transition = representativeState.Exit(transition); State = transition.Destination; var newRepresentation = GetRepresentation(transition.Destination); // Check if there is an intital transition configured if (newRepresentation.HasInitialTransition) { // Verify that the target state is a substate if (!newRepresentation.GetSubstates().Any(s => s.UnderlyingState.Equals(newRepresentation.InitialTransitionTarget))) { throw new InvalidOperationException($"The target ({newRepresentation.InitialTransitionTarget}) for the initial transition is not a substate."); } // Check if state has substate(s), and if an initial transition(s) has been set up. while (newRepresentation.GetSubstates().Any() && newRepresentation.HasInitialTransition) { var initialTransition = new Transition(transition.Source, newRepresentation.InitialTransitionTarget, transition.Trigger); newRepresentation = GetRepresentation(newRepresentation.InitialTransitionTarget); newRepresentation.Enter(initialTransition, args); State = newRepresentation.UnderlyingState; } //Alert all listeners of state transition _onTransitionedEvent.Invoke(transition); } else { //Alert all listeners of state transition _onTransitionedEvent.Invoke(transition); newRepresentation.Enter(transition, args); } }
private StateRepresentation EnterState(StateRepresentation representation, Transition transition, object [] args) { // Enter the new state representation.Enter(transition, args); if (FiringMode.Immediate.Equals(_firingMode) && !State.Equals(transition.Destination)) { // This can happen if triggers are fired in OnEntry // Must update current representation with updated State representation = GetRepresentation(State); transition = new Transition(transition.Source, State, transition.Trigger, args); } // Recursively enter substates that have an initial transition if (representation.HasInitialTransition) { // Verify that the target state is a substate // Check if state has substate(s), and if an initial transition(s) has been set up. if (!representation.GetSubstates().Any(s => s.UnderlyingState.Equals(representation.InitialTransitionTarget))) { throw new InvalidOperationException($"The target ({representation.InitialTransitionTarget}) for the initial transition is not a substate."); } var initialTransition = new InitialTransition(transition.Source, representation.InitialTransitionTarget, transition.Trigger, args); representation = GetRepresentation(representation.InitialTransitionTarget); representation = EnterState(representation, initialTransition, args); } return(representation); }
async Task ExecuteInternalActionsAsync(Transition transition, object[] args) { InternalTriggerBehaviour internalTransition = null; // Look for actions in superstate(s) recursivly until we hit the topmost superstate, or we actually find some trigger handlers. StateRepresentation aStateRep = this; while (aStateRep != null) { if (aStateRep.TryFindLocalHandler(transition.Trigger, args, out TriggerBehaviourResult result)) { // Trigger handler(s) found in this state internalTransition = result.Handler as InternalTriggerBehaviour; break; } // Try to look for trigger handlers in superstate (if it exists) aStateRep = aStateRep._superstate; } // Execute internal transition event handler if (internalTransition == null) { throw new ArgumentNullException("The configuration is incorrect, no action assigned to this internal transition."); } await(internalTransition.ExecuteAsync(transition, args)).ConfigureAwait(false); }
private void HandleReentryTrigger(object[] args, StateRepresentation representativeState, Transition transition) { StateRepresentation representation; transition = representativeState.Exit(transition); var newRepresentation = GetRepresentation(transition.Destination); if (!transition.Source.Equals(transition.Destination)) { // Then Exit the final superstate transition = new Transition(transition.Destination, transition.Destination, transition.Trigger, args); newRepresentation.Exit(transition); _onTransitionedEvent.Invoke(transition); representation = EnterState(newRepresentation, transition, args); _onTransitionCompletedEvent.Invoke(transition); } else { _onTransitionedEvent.Invoke(transition); representation = EnterState(newRepresentation, transition, args); _onTransitionCompletedEvent.Invoke(transition); } State = representation.UnderlyingState; }
internal void InternalAction(Transition transition, object[] args) { InternalTriggerBehaviour.Sync internalTransition = null; // Look for actions in superstate(s) recursivly until we hit the topmost superstate, or we actually find some trigger handlers. StateRepresentation aStateRep = this; while (aStateRep != null) { if (aStateRep.TryFindLocalHandler(transition.Trigger, args, out TriggerBehaviourResult result)) { // Trigger handler found in this state if (result.Handler is InternalTriggerBehaviour.Async) { throw new InvalidOperationException("Running Async internal actions in synchronous mode is not allowed"); } internalTransition = result.Handler as InternalTriggerBehaviour.Sync; break; } // Try to look for trigger handlers in superstate (if it exists) aStateRep = aStateRep._superstate; } // Execute internal transition event handler if (internalTransition == null) { throw new ArgumentNullException("The configuration is incorrect, no action assigned to this internal transition."); } internalTransition.InternalAction(transition, args); }
/// <summary> /// Clone constructor /// </summary> private StateRepresentation(TState state, IEnumerable <KeyValuePair <TTrigger, ICollection <TriggerBehaviour> > > triggerBehaviours, IEnumerable <Action <Transition, object[]> > entryActions, IEnumerable <Action <Transition> > exitActions, StateRepresentation superstate, IEnumerable <StateRepresentation> substates) { _state = state; foreach (var behaviour in triggerBehaviours) { _triggerBehaviours.Add(behaviour); } foreach (var action in entryActions) { _entryActions.Add(action); } foreach (var action in exitActions) { _exitActions.Add(action); } if (superstate != null) { _superstate = superstate.Clone(); } foreach (var substate in substates) { _substates.Add(substate.Clone()); } }
internal void InternalAction(Transition transition, object[] args) { var possibleActions = new List <InternalActionBehaviour>(); // Look for actions in superstate(s) recursivly until we hit the topmost superstate, or we actually find some trigger handlers. StateRepresentation aStateRep = this; while (aStateRep != null) { if (aStateRep.TryFindLocalHandler(transition.Trigger, out TriggerBehaviourResult result)) { // Trigger handler(s) found in this state possibleActions.AddRange(aStateRep._internalActions); break; } // Try to look for trigger handlers in superstate (if it exists) aStateRep = aStateRep._superstate; } // Execute internal transition event handler foreach (var action in possibleActions) { action.Execute(transition, args); } }
public void AddSubstate(StateRepresentation substate) { if (substate != null) { mSubStates.Add(substate); } }
/// <summary> /// Sets the superstate that the configured state is a substate of. /// </summary> /// <remarks> /// Substates inherit the allowed transitions of their superstate. /// When entering directly into a substate from outside of the superstate, /// entry actions for the superstate are executed. /// Likewise when leaving from the substate to outside the supserstate, /// exit actions for the superstate will execute. /// </remarks> /// <param name="superstate">The superstate.</param> /// <returns>The receiver.</returns> public StateConfiguration SubstateOf(TState superstate) { StateRepresentation superRepresentation = _lookup(superstate); _representation.Superstate = superRepresentation; superRepresentation.AddSubstate(_representation); return(this); }
StateRepresentation GetRepresentation(TState state) { if (!_stateConfiguration.TryGetValue(state, out StateRepresentation result)) { result = new StateRepresentation(state); _stateConfiguration.Add(state, result); } return(result); }
public StateConfiguration Permit(TTrigger trigger, TState destinationState, Func <TState, TTrigger, bool> action) { if (!_representation.TriggerBehaviours.ContainsKey(trigger)) { StateRepresentation sr = _machine.GetRepresentation(_machine._nullState); sr.AddTriggerBehaviour(new TransitioningTriggerBehaviour(trigger, destinationState, action)); } _representation.AddTriggerBehaviour(new TransitioningTriggerBehaviour(trigger, destinationState, action)); return(this); }
private StateRepresentation GetRepresentation(TState state) { StateRepresentation result; if (!mStateConfiguration.TryGetValue(state, out result)) { result = new StateRepresentation(state); mStateConfiguration.Add(state, result); } return(result); }
StateRepresentation GetRepresentation(TState state) { StateRepresentation result; if (!_stateConfiguration.TryGetValue(state, out result)) { result = new StateRepresentation(state); _stateConfiguration.Add(state, result); //Configure(_state).Permit(_firstTrigger, state); } return(_stateConfiguration[state]); }
internal StateMachine(TState initialState, StateMachineConfiguration<TState, TTrigger> configuration) { Contract.Requires(configuration != null); Contract.Requires(initialState != null); currentStateRepresentation = configuration.GetStateRepresentation(initialState); if (currentStateRepresentation == null) { throw new InvalidOperationException("StateMachine has no state"); } IsEnabled = true; }
internal StateConfigurationHelper(Dictionary <TState, StateRepresentation <TState, TTrigger> > config, TState currentState) { Contract.Requires(config != null); Contract.Requires(currentState != null); Contract.Ensures(this.config != null); Contract.Ensures(currentStateRepresentation != null); this.config = config; currentStateRepresentation = FindOrCreateStateRepresentation(currentState, config); }
internal BlockingStateMachine(TState initialState, StateMachineConfiguration <TState, TTrigger> configuration) { Contract.Requires(configuration != null); Contract.Requires(initialState != null); CurrentStateRepresentation = configuration.GetInitialStateRepresentation(initialState); if (CurrentStateRepresentation == null) { throw new InvalidOperationException("StateMachine has an unreachable state"); } configDictionary = configuration.Config; }
private void HandleTransitioningTrigger(object[] args, StateRepresentation representativeState, Transition transition) { transition = representativeState.Exit(transition); State = transition.Destination; var newRepresentation = GetRepresentation(transition.Destination); //Alert all listeners of state transition _onTransitionedEvent.Invoke(transition); var representation = EnterState(newRepresentation, transition, args); State = representation.UnderlyingState; }
protected RawStateMachineBase(TState initialState, Configuration <TState, TTrigger> configuration) { Representations = configuration.Representations; CurrentStateRepresentation = StateConfigurationHelper.FindStateRepresentation( initialState, Representations); if (CurrentStateRepresentation == null) { ExceptionHelper.ThrowInvalidState(initialState); } diagnostics = new RawStateMachineDiagnostics <TState, TTrigger>(this); }
private void HandleReentryTrigger(object[] args, StateRepresentation representativeState, Transition transition) { transition = representativeState.Exit(transition); State = transition.Destination; var newRepresentation = GetRepresentation(transition.Destination); if (!transition.Source.Equals(transition.Destination)) { // Then Exit the final superstate transition = new Transition(transition.Destination, transition.Destination, transition.Trigger); newRepresentation.Exit(transition); } _onTransitionedEvent.Invoke(transition); newRepresentation.Enter(transition, args); }
public void MoveToState(TState state, StateTransitionOption option = StateTransitionOption.Default) { if (monitor.TryEnter()) { try { if (!IsEnabled) { return; } StateRepresentation <TState, TTrigger> rep; if (configDictionary.TryGetValue(state, out rep)) { if ((option & StateTransitionOption.CurrentStateExitTransition) == StateTransitionOption.CurrentStateExitTransition) { ExecuteAction(CurrentStateRepresentation.OnExitAction); } if ((option & StateTransitionOption.NewStateEntryTransition) == StateTransitionOption.NewStateEntryTransition) { ExecuteAction(rep.OnEntryAction); } CurrentStateRepresentation = rep; } else { throw new InvalidOperationException("Invalid state: " + state.ToString()); } } finally { monitor.Exit(); } } else { if (IsEnabled) { throw new InvalidOperationException("State cannot be changed while in transition. Use AsyncStateMachine or a BlockingStateMachine for these semantics."); } } }
void ExecuteInternalActions(Transition transition, object[] args) { var possibleActions = new List <InternalActionBehaviour>(); // Look for actions in superstate(s) recursivly until we hit the topmost superstate StateRepresentation aStateRep = this; do { possibleActions.AddRange(aStateRep._internalActions); aStateRep = aStateRep._superstate; } while (aStateRep != null); // Execute internal transition event handler foreach (var action in possibleActions) { action.Execute(transition, args); } }
internal static StateRepresentation <TState, TTrigger> FindOrCreateStateRepresentation(TState state, Dictionary <TState, StateRepresentation <TState, TTrigger> > config) { Contract.Requires(state != null); Contract.Requires(config != null); Contract.Ensures(Contract.Result <StateRepresentation <TState, TTrigger> >() != null); StateRepresentation <TState, TTrigger> rep; if (config.TryGetValue(state, out rep)) { return(rep); } rep = new StateRepresentation <TState, TTrigger>(state); config[state] = rep; return(rep); }
private void HandleTransitioningTrigger(object[] args, StateRepresentation representativeState, Transition transition) { transition = representativeState.Exit(transition); State = transition.Destination; var newRepresentation = GetRepresentation(transition.Destination); //Alert all listeners of state transition _onTransitionedEvent.Invoke(transition); var representation = EnterState(newRepresentation, transition, args); // Check if state has changed by entering new state (by fireing triggers in OnEntry or such) if (!representation.UnderlyingState.Equals(State)) { // The state has been changed after entering the state, must update current state to new one State = representation.UnderlyingState; } _onTransitionCompletedEvent.Invoke(transition); }
private async Task HandleTransitioningTriggerAsync(object[] args, StateRepresentation representativeState, Transition transition) { transition = await representativeState.ExitAsync(transition); State = transition.Destination; var newRepresentation = GetRepresentation(transition.Destination); //Alert all listeners of state transition await _onTransitionedEvent.InvokeAsync(transition); var representation = await EnterStateAsync(newRepresentation, transition, args); // Check if state has changed by entering new state (by fireing triggers in OnEntry or such) if (!representation.UnderlyingState.Equals(State)) { // The state has been changed after entering the state, must update current state to new one State = representation.UnderlyingState; } await _onTransitionCompletedEvent.InvokeAsync(new Transition(transition.Source, State, transition.Trigger, transition.Parameters)); }
private StateRepresentation EnterState(StateRepresentation representation, Transition transition, object [] args) { // Enter the new state representation.Enter(transition, args); // Recursively enter substates that have an initial transition if (representation.HasInitialTransition) { // Verify that the target state is a substate // Check if state has substate(s), and if an initial transition(s) has been set up. if (!representation.GetSubstates().Any(s => s.UnderlyingState.Equals(representation.InitialTransitionTarget))) { throw new InvalidOperationException($"The target ({representation.InitialTransitionTarget}) for the initial transition is not a substate."); } var initialTransition = new Transition(transition.Source, representation.InitialTransitionTarget, transition.Trigger); representation = GetRepresentation(representation.InitialTransitionTarget); representation = EnterState(representation, initialTransition, args); } return(representation); }
public void AddSubstate(StateRepresentation substate) { Enforce.ArgumentNotNull(substate, nameof(substate)); _substates.Add(substate); }
internal static TriggerRepresentation <TTrigger, TState> FindOrCreateTriggerRepresentation(TTrigger trigger, StateRepresentation <TState, TTrigger> stateRepresentation) { Contract.Requires(stateRepresentation != null); Contract.Requires(trigger != null); Contract.Ensures(Contract.Result <TriggerRepresentation <TTrigger, TState> >() != null); var rep = FindTriggerRepresentation(trigger, stateRepresentation); if (rep != null) { Contract.Assume(rep.Trigger != null); return(rep); } rep = new TriggerRepresentation <TTrigger, TState>(trigger); stateRepresentation.Triggers.Add(rep); return(rep); }
internal static TriggerRepresentation <TTrigger, TState> FindTriggerRepresentation(TTrigger trigger, StateRepresentation <TState, TTrigger> stateRepresentation) { return(stateRepresentation.Triggers.Find(x => x.Trigger.Equals(trigger))); }