示例#1
0
 /// <summary>
 /// Re-routes a transition between a specified source and destination
 /// </summary>
 /// <param name="transition">The transition to re-route.</param>
 /// <param name="source">The new source for the transition.</param>
 /// <param name="target">The new target for the transition.</param>
 /// <remarks>
 /// This method can be used when extending state machines.
 /// Careful design consideration should be made before using this method.
 /// Never change a state machines structure while it is running.
 /// </remarks>
 protected void rerouteTransition(NSFTransition transition, NSFState source, NSFState target)
 {
     transition.Source.removeOutgoingTransition(transition);
     transition.Target.removeIncomingTransition(transition);
     transition.Source = source;
     transition.Target = target;
 }
        /// <summary>
        /// Determines if the queuing the an event causes a state to enter before defaultWaitTime elapses.
        /// </summary>
        /// <param name="eventToInject">The event to queue.</param>
        /// <param name="stateToWaitFor">The state to wait for.</param>
        /// <param name="waitTime">The time in ms to wait for the stateToWaitFor to enter.</param>
        /// <returns>
        ///     True if the stateToWaitFor is entered.
        ///     False if the stateToWaitFor is not entered before time expires.
        /// </returns>
        /// <remarks>
        /// This is a blocking call, the caller may be blocked for as long as waitTime.
        /// </remarks>
        public bool doesEventResultInState(NSFEvent eventToInject, NSFState stateToWaitFor, int waitTime)
        {
            firstSignal.clear();

            stateToWaitFor.EntryActions += firstSignal.send;

            if (eventToInject != null)
            {
                eventToInject.queueEvent();
            }

            if (stateToWaitFor.isActive())
            {
                stateToWaitFor.EntryActions -= firstSignal.send;
                return true;
            }

            if (!firstSignal.wait(waitTime))
            {
                stateToWaitFor.EntryActions -= firstSignal.send;
                return false;
            }

            stateToWaitFor.EntryActions -= firstSignal.send;
            return true;
        }
 /// <summary>
 /// Creates a state machine context.
 /// </summary>
 /// <param name="source">The state machine.</param>
 /// <param name="enteringState">The state being entered.</param>
 /// <param name="exitingState">The state being exited.</param>
 /// <param name="transition">The associated transition.</param>
 /// <param name="trigger">The triggering event.</param>
 public NSFStateMachineContext(NSFStateMachine source, NSFState enteringState, NSFState exitingState, NSFTransition transition, NSFEvent trigger)
     : base(source)
 {
     EnteringState = enteringState;
     ExitingState  = exitingState;
     Transition    = transition;
     Trigger       = trigger;
 }
示例#4
0
        /// <summary>
        /// Indicates if the region's active substate is the specified state.
        /// </summary>
        /// <param name="state">The state in question.</param>
        /// <returns>True if the region's active substate is the specified state, false otherwise.</returns>
        public bool isInState(NSFState state)
        {
            if (!active)
            {
                return(false);
            }

            return(activeSubstate.isInState(state));
        }
        /// <summary>
        /// Indicates if the specified state is active, i.e. is "in" the specified state.
        /// </summary>
        /// <param name="state">State in question.</param>
        /// <returns>True if the specified state is active, otherwise false.</returns>
        public virtual bool isInState(NSFState state)
        {
            if (!active)
            {
                return(false);
            }

            return(this == state);
        }
示例#6
0
        /// <summary>
        /// Sets the region's active substate.
        /// </summary>
        /// <param name="substate">The new active substate.</param>
        internal void setActiveSubstate(NSFState substate)
        {
            // Set history substate to the current, active substate whenever the active substate is about to becomes the null state,
            // except that the history substate should not be set to the null state or the initial state.
            if ((substate == NSFState.NullState) && (activeSubstate != NSFState.NullState) && (activeSubstate != initialState))
            {
                historySubstate = activeSubstate;
            }

            activeSubstate = substate;
        }
        /// <summary>
        /// Creates a local transition.
        /// </summary>
        /// <param name="name">User assigned name for transition.</param>
        /// <param name="source">Transition source.</param>
        /// <param name="target">Transition target.</param>
        /// <param name="trigger">Transition trigger.</param>
        /// <param name="guard">Transition guard.</param>
        /// <param name="action">Transition action.</param>
        public NSFLocalTransition(NSFString name, NSFCompositeState source, NSFState target, NSFEvent trigger, NSFBoolGuard <NSFStateMachineContext> guard, NSFVoidAction <NSFStateMachineContext> action)
            : base(name, source, target, trigger, guard, action)
        {
            compositeSource = source;

            // Target must be substate of source or the source itself
            if ((!Source.isParent(Target)) && (Source != Target))
            {
                throw new Exception(Name + " invalid local transition, source is neither parent of nor equal to target");
            }

            Source.addOutgoingTransition(this);
        }
        /// <summary>
        /// Creates a local transition.
        /// </summary>
        /// <param name="name">User assigned name for transition.</param>
        /// <param name="source">Transition source.</param>
        /// <param name="target">Transition target.</param>
        /// <param name="trigger">Transition trigger.</param>
        /// <param name="guard">Transition guard.</param>
        /// <param name="action">Transition action.</param>
        public NSFLocalTransition(NSFString name, NSFCompositeState source, NSFState target, NSFEvent trigger, NSFBoolGuard<NSFStateMachineContext> guard, NSFVoidAction<NSFStateMachineContext> action)
            : base(name, source, target, trigger, guard, action)
        {
            compositeSource = source;

            // Target must be substate of source or the source itself
            if ((!Source.isParent(Target)) && (Source != Target))
            {
                throw new Exception(Name + " invalid local transition, source is neither parent of nor equal to target");
            }

            Source.addOutgoingTransition(this);
        }
示例#9
0
        protected internal override void enter(NSFStateMachineContext context, bool useHistory)
        {
            // Base class behavior
            base.enter(context, false);

            // Additional behavior

            // Enter history substate, using recursive history
            NSFState historySubstate = parentRegion.HistorySubstate;

            if (historySubstate != NSFState.NullState)
            {
                historySubstate.enter(context, true);
            }
        }
        /// <summary>
        /// Indicates if this state is a parent of the specified substate.
        /// </summary>
        /// <param name="substate">The substate in question.</param>
        /// <returns>True if this state is a parent, false otherwise.</returns>
        internal bool isParent(NSFState substate)
        {
            NSFState substateParent = substate.ParentState;

            while (substateParent != null)
            {
                if (substateParent == this)
                {
                    return(true);
                }
                else
                {
                    substateParent = substateParent.ParentState;
                }
            }

            return(false);
        }
示例#11
0
        protected override void fireTransition(NSFStateMachineContext context)
        {
            Source.exit(context);

            // Exit parent states until common parent is found
            NSFState parentState = Source.ParentState;

            while ((parentState != null) && (!parentState.isParent(Target)))
            {
                parentState.exit(context);
                parentState = parentState.ParentState;
            }

            // Reset context possibly changed by exiting states
            context.EnteringState = null;
            context.ExitingState  = null;

            Actions.execute(context);

            Target.enter(context, false);
        }
示例#12
0
        /// <summary>
        /// Creates a transition.
        /// </summary>
        /// <param name="name">User assigned name for transition.</param>
        /// <param name="source">Transition source.</param>
        /// <param name="target">Transition target.</param>
        /// <param name="trigger">Transition trigger.</param>
        /// <param name="guard">Transition guard.</param>
        /// <param name="action">Transition action.</param>
        /// <remarks>Deprecated - Use NSFExternalTransition or NSFLocalTransition</remarks>
        protected NSFTransition(NSFString name, NSFState source, NSFState target, NSFEvent trigger, NSFBoolGuard <NSFStateMachineContext> guard, NSFVoidAction <NSFStateMachineContext> action)
            : base(name)
        {
            this.source = source;
            this.target = target;
            Guards     += guard;
            Actions    += action;

            addTrigger(trigger);

            // Validity check
            if ((source == target) && (triggers.Count == 0) && Guards.isEmpty())
            {
                throw new Exception(Name + " invalid self-transition with no trigger or guard");
            }

            target.addIncomingTransition(this);
            // Outgoing transitions must be added by concrete classes

            Guards.setExceptionAction(handleGuardException);
            Actions.setExceptionAction(handleActionException);
        }
        /// <summary>
        /// Creates a transition.
        /// </summary>
        /// <param name="name">User assigned name for transition.</param>
        /// <param name="source">Transition source.</param>
        /// <param name="target">Transition target.</param>
        /// <param name="trigger">Transition trigger.</param>
        /// <param name="guard">Transition guard.</param>
        /// <param name="action">Transition action.</param>
        /// <remarks>Deprecated - Use NSFExternalTransition or NSFLocalTransition</remarks>
        protected NSFTransition(NSFString name, NSFState source, NSFState target, NSFEvent trigger, NSFBoolGuard<NSFStateMachineContext> guard, NSFVoidAction<NSFStateMachineContext> action)
            : base(name)
        {
            this.source = source;
            this.target = target;
            Guards += guard;
            Actions += action;

            addTrigger(trigger);

            // Validity check
            if ((source == target) && (triggers.Count == 0) && Guards.isEmpty())
            {
                throw new Exception(Name + " invalid self-transition with no trigger or guard");
            }

            target.addIncomingTransition(this);
            // Outgoing transitions must be added by concrete classes

            Guards.setExceptionAction(handleGuardException);
            Actions.setExceptionAction(handleActionException);
        }
示例#14
0
        /// <summary>
        /// Adds a substate to the region's list of substates.
        /// </summary>
        /// <param name="substate">The substate to add.</param>
        internal void addSubstate(NSFState substate)
        {
            substates.Add(substate);

            // Any single state in a region can be the initial state
            // If more than one state exists in a region, there must be one and only one NSFInitialState

            // First substate is automatically registered as initial state
            if (substates.Count == 1)
            {
                initialState = substate;
                return;
            }

            // Not first state

            // If initial state is not already an NSFInitialState
            if (!(initialState is NSFInitialState))
            {
                if (substate is NSFInitialState)
                {
                    initialState = substate;
                }
                else // Not adding an NSFInitialState
                {
                    // Reset initial state to null, enforcing requirement for an NSFInitialState
                    initialState = NSFState.NullState;
                }
            }
            else // Initial state already established
            {
                if (substate is NSFInitialState)
                {
                    throw new Exception(Name + " only one initial state allowed in a region");
                }
            }
        }
        public override bool isInState(NSFState state)
        {
            if (!active)
            {
                return(false);
            }

            // Base class behavior
            if (base.isInState(state))
            {
                return(true);
            }

            // Check regions
            foreach (NSFRegion region in regions)
            {
                if (region.isInState(state))
                {
                    return(true);
                }
            }

            return(false);
        }
        public override bool isInState(NSFState state)
        {
            if (!active)
            {
                return false;
            }

            // Base class behavior
            if (base.isInState(state))
            {
                return true;
            }

            // Check regions
            foreach (NSFRegion region in regions)
            {
                if (region.isInState(state))
                {
                    return true;
                }
            }

            return false;
        }
        /// <summary>
        /// Indicates if the region's active substate is the specified state.
        /// </summary>
        /// <param name="state">The state in question.</param>
        /// <returns>True if the region's active substate is the specified state, false otherwise.</returns>
        public bool isInState(NSFState state)
        {
            if (!active)
            {
                return false;
            }

            return activeSubstate.isInState(state);
        }
        /// <summary>
        /// Sets the region's active substate.
        /// </summary>
        /// <param name="substate">The new active substate.</param>
        internal void setActiveSubstate(NSFState substate)
        {
            // Set history substate to the current, active substate whenever the active substate is about to becomes the null state,
            // except that the history substate should not be set to the null state or the initial state.
            if ((substate == NSFState.NullState) && (activeSubstate != NSFState.NullState) && (activeSubstate != initialState))
            {
                historySubstate = activeSubstate;
            }

            activeSubstate = substate;
        }
        /// <summary>
        /// Resets the region to its initial condition.
        /// </summary>
        internal void reset()
        {
            active = false;

            activeSubstate = NSFState.NullState;
            historySubstate = NSFState.NullState;

            foreach (NSFState state in substates)
            {
                state.reset();
            }
        }
        /// <summary>
        /// Adds a substate to the region's list of substates.
        /// </summary>
        /// <param name="substate">The substate to add.</param>
        internal void addSubstate(NSFState substate)
        {
            substates.Add(substate);

            // Any single state in a region can be the initial state
            // If more than one state exists in a region, there must be one and only one NSFInitialState

            // First substate is automatically registered as initial state
            if (substates.Count == 1)
            {
                initialState = substate;
                return;
            }

            // Not first state

            // If initial state is not already an NSFInitialState
            if (!(initialState is NSFInitialState))
            {
                if (substate is NSFInitialState)
                {
                    initialState = substate;
                }
                else // Not adding an NSFInitialState
                {
                    // Reset initial state to null, enforcing requirement for an NSFInitialState
                    initialState = NSFState.NullState;
                }
            }
            else // Initial state already established
            {
                if (substate is NSFInitialState)
                {
                    throw new Exception(Name + " only one initial state allowed in a region");
                }
            }
        }
 /// <summary>
 /// Re-routes a transition between a specified source and destination
 /// </summary>
 /// <param name="transition">The transition to re-route.</param>
 /// <param name="source">The new source for the transition.</param>
 /// <param name="target">The new target for the transition.</param>
 /// <remarks>
 /// This method can be used when extending state machines.
 /// Careful design consideration should be made before using this method.
 /// Never change a state machines structure while it is running.
 /// </remarks>
 protected void rerouteTransition(NSFTransition transition, NSFState source, NSFState target)
 {
     transition.Source.removeOutgoingTransition(transition);
     transition.Target.removeIncomingTransition(transition);
     transition.Source = source;
     transition.Target = target;
 }
        /// <summary>
        /// Indicates if the specified state is active, i.e. is "in" the specified state.
        /// </summary>
        /// <param name="state">State in question.</param>
        /// <returns>True if the specified state is active, otherwise false.</returns>
        public virtual bool isInState(NSFState state)
        {
            if (!active)
            {
                return false;
            }

            return (this == state);
        }
 /// <summary>
 /// Creates a local transition.
 /// </summary>
 /// <param name="source">Transition source.</param>
 /// <param name="target">Transition target.</param>
 /// <param name="trigger">Transition trigger.</param>
 /// <param name="guard">Transition guard.</param>
 /// <param name="action">Transition action.</param>
 public NSFLocalTransition(NSFCompositeState source, NSFState target, NSFEvent trigger, NSFBoolGuard<NSFStateMachineContext> guard, NSFVoidAction<NSFStateMachineContext> action)
     : this(source.Name + "To" + target.Name, source, target, trigger, guard, action)
 {
 }
 /// <summary>
 /// Creates a local transition.
 /// </summary>
 /// <param name="source">Transition source.</param>
 /// <param name="target">Transition target.</param>
 /// <param name="trigger">Transition trigger.</param>
 /// <param name="guard">Transition guard.</param>
 /// <param name="action">Transition action.</param>
 public NSFLocalTransition(NSFCompositeState source, NSFState target, NSFEvent trigger, NSFBoolGuard <NSFStateMachineContext> guard, NSFVoidAction <NSFStateMachineContext> action)
     : this(source.Name + "To" + target.Name, source, target, trigger, guard, action)
 {
 }
 /// <summary>
 /// Creates an internal transition.
 /// </summary>
 /// <param name="state">Transition state.</param>
 /// <param name="trigger">Transition trigger.</param>
 /// <param name="guard">Transition guard.</param>
 /// <param name="action">Transition action.</param>
 /// <remarks>The default name for the transition is [state.Name]ReactionsTo[trigger.Name]</remarks>
 public NSFInternalTransition(NSFState state, NSFEvent trigger, NSFBoolGuard<NSFStateMachineContext> guard, NSFVoidAction<NSFStateMachineContext> action)
     : this(state.Name + "ReactionsTo" + trigger.Name, state, trigger, guard, action)
 {
 }
 /// <summary>
 /// Creates an external transition.
 /// </summary>
 /// <param name="name">User assigned name for transition.</param>
 /// <param name="source">Transition source.</param>
 /// <param name="target">Transition target.</param>
 /// <param name="trigger">Transition trigger.</param>
 /// <param name="guard">Transition guard.</param>
 /// <param name="action">Transition action.</param>
 public NSFExternalTransition(NSFString name, NSFState source, NSFState target, NSFEvent trigger, NSFBoolGuard<NSFStateMachineContext> guard, NSFVoidAction<NSFStateMachineContext> action)
     : base(name, source, target, trigger, guard, action)
 {
     Source.addOutgoingTransition(this);
 }
 /// <summary>
 /// Determines if the queuing the an event causes a state to enter before defaultWaitTime elapses.
 /// </summary>
 /// <param name="eventToInject">The event to queue.</param>
 /// <param name="stateToWaitFor">The state to wait for.</param>
 /// <returns>
 ///     True if the stateToWaitFor is entered.
 ///     False if the stateToWaitFor is not entered before time expires.
 /// </returns>
 /// <remarks>
 /// This is a blocking call, the caller may be blocked for as long as <see cref="defaultWaitTime"/>.
 /// </remarks>
 public bool doesEventResultInState(NSFEvent eventToInject, NSFState stateToWaitFor)
 {
     return doesEventResultInState(eventToInject, stateToWaitFor, defaultWaitTime);
 }
示例#28
0
 /// <summary>
 /// Creates an internal transition.
 /// </summary>
 /// <param name="state">Transition state.</param>
 /// <param name="trigger">Transition trigger.</param>
 /// <param name="guard">Transition guard.</param>
 /// <param name="action">Transition action.</param>
 /// <remarks>The default name for the transition is [state.Name]ReactionsTo[trigger.Name]</remarks>
 public NSFInternalTransition(NSFState state, NSFEvent trigger, NSFBoolGuard <NSFStateMachineContext> guard, NSFVoidAction <NSFStateMachineContext> action)
     : this(state.Name + "ReactionsTo" + trigger.Name, state, trigger, guard, action)
 {
 }
 /// <summary>
 /// Creates a state machine context.
 /// </summary>
 /// <param name="source">The state machine.</param>
 /// <param name="enteringState">The state being entered.</param>
 /// <param name="exitingState">The state being exited.</param>
 /// <param name="transition">The associated transition.</param>
 /// <param name="trigger">The triggering event.</param>
 public NSFStateMachineContext(NSFStateMachine source, NSFState enteringState, NSFState exitingState, NSFTransition transition, NSFEvent trigger)
     : base(source)
 {
     EnteringState = enteringState;
     ExitingState = exitingState;
     Transition = transition;
     Trigger = trigger;
 }
        /// <summary>
        /// Indicates if this state is a parent of the specified substate.
        /// </summary>
        /// <param name="substate">The substate in question.</param>
        /// <returns>True if this state is a parent, false otherwise.</returns>
        internal bool isParent(NSFState substate)
        {
            NSFState substateParent = substate.ParentState;

            while (substateParent != null)
            {
                if (substateParent == this)
                {
                    return true;
                }
                else
                {
                    substateParent = substateParent.ParentState;
                }
            }

            return false;
        }
示例#31
0
 /// <summary>
 /// Creates an internal transition.
 /// </summary>
 /// <param name="name">User assigned name for transition.</param>
 /// <param name="state">Transition state.</param>
 /// <param name="trigger">Transition trigger.</param>
 /// <param name="guard">Transition guard.</param>
 /// <param name="action">Transition action.</param>
 public NSFInternalTransition(NSFString name, NSFState state, NSFEvent trigger, NSFBoolGuard <NSFStateMachineContext> guard, NSFVoidAction <NSFStateMachineContext> action)
     : base(name, state, state, trigger, guard, action)
 {
     Source.addOutgoingTransition(this);
 }
        /// <summary>
        /// Determines if the queuing the an event causes two states to enter before waitTime elapses.
        /// </summary>
        /// <param name="eventToInject">The event to queue.</param>
        /// <param name="stateToWaitFor">The first of two states to wait for.</param>
        /// <param name="secondStateToWaitFor">The second of two states to wait for.</param>
        /// <param name="waitTime">The time in ms to wait for the each state to enter.</param>
        /// <returns>
        ///     True if both states are entered.
        ///     False if either of the states fails to enter before time expires.
        /// </returns>
        /// <remarks>
        /// This is a blocking call, the caller may be blocked for as long as twice waitTime.
        /// The states may be congruently entered.
        /// </remarks>
        public bool doesEventResultInState(NSFEvent eventToInject, NSFState stateToWaitFor, NSFState secondStateToWaitFor, int waitTime)
        {
            secondSignal.clear();

            stateToWaitFor.EntryActions += secondSignal.send;

            secondStateToWaitFor.EntryActions += secondSignal.send;

            if (!doesEventResultInState(eventToInject, stateToWaitFor, waitTime))
            {
                secondStateToWaitFor.EntryActions -= secondSignal.send;
                return false;
            }

            if (secondStateToWaitFor.isActive())
            {
                secondStateToWaitFor.EntryActions -= secondSignal.send;
                return true;
            }

            if (!secondSignal.wait(waitTime))
            {
                secondStateToWaitFor.EntryActions -= secondSignal.send;
                return false;
            }

            secondStateToWaitFor.EntryActions -= secondSignal.send;
            return true;
        }