Beispiel #1
0
 /// <summary>
 /// Performs a dynamic transition; i.e., the transition path is determined on the fly and not recorded.
 /// </summary>
 /// <param name="targetState">The <see cref="QState"/> to transition to.</param>
 protected void TransitionTo(QState targetState)
 {
     Debug.Assert(targetState != s_TopState);             // can't target 'top' state
     ExitUpToSourceState();
     // This is a dynamic transition. We pass in null instead of a recorder
     TransitionFromSourceToTarget(targetState, null);
 }
Beispiel #2
0
 /// <summary>
 /// DispatchException (see def on IQHsm)
 /// </summary>
 protected virtual void DoDispatchException(IQHsm hsm, Exception ex, QState state, IQEvent ev)
 {
     if (OnDispatchException(hsm, ex, state, ev))
     {
         RaiseDispatchException(DispatchException, hsm, ex, state, ev);
     }
 }
 public DispatchExceptionFailureEventArgs(Exception ex, IQHsm hsm, QState state, IQEvent ev)
 {
     _Exception     = ex;
     _Hsm           = hsm;
     _State         = state;
     _OriginalEvent = ev;
 }
Beispiel #4
0
        private void TransitionDownToTargetState(
            QState targetState,
            ArrayList statesTargetToLCA,
            int indexFirstStateToEnter,
            TransitionChainRecorder recorder)
        {
            // we enter the states in the passed in array in reverse order
            for (int stateIndex = indexFirstStateToEnter; stateIndex >= 0; stateIndex--)
            {
                Trigger((QState)statesTargetToLCA[stateIndex], QSignals.Entry, recorder);
            }

            m_MyState = targetState;

            // At last we are ready to initialize the target state.
            // If the specified target state handles init then the effective
            // target state is deeper than the target state specified in
            // the transition.
            while (Trigger(targetState, QSignals.Init, recorder) == null)
            {
                // Initial transition must be one level deep
                Debug.Assert(targetState == GetSuperState(m_MyState));
                targetState = m_MyState;
                Trigger(targetState, QSignals.Entry, recorder);
            }

            if (recorder != null)
            {
                // We always make sure that the last entry in the recorder represents the entry to the target state.
                EnsureLastTransistionStepIsEntryIntoTargetState(targetState, recorder);
                Debug.Assert(recorder.GetRecordedTransitionChain().Length > 0);
            }
        }
Beispiel #5
0
 private void TransitionToSynchronized(QState targetState, ref TransitionChain transitionChain)
 {
     //The entire method had been embedded within [MethodImpl(MethodImplOptions.Synchronized)],
     //which is not available in .NET Core, and so a lock is used instead...
     lock (this)
     {
         if (transitionChain != null)
         {
             // We encountered a race condition. The first (non-synchronized) check indicated that the transition chain
             // is null. However, a second threat beat us in getting into this synchronized method and populated
             // the transition chain in the meantime. We can execute the regular method again now.
             TransitionTo(targetState, ref transitionChain);
         }
         else
         {
             // The transition chain is not initialized yet, we need to dynamically retrieve
             // the required transition steps and record them so that we can subsequently simply
             // play them back.
             TransitionChainRecorder recorder = new TransitionChainRecorder();
             TransitionFromSourceToTarget(targetState.GetMethodInfo(), recorder);
             // We pass the recorded transition steps back to the caller:
             transitionChain = recorder.GetRecordedTransitionChain();
         }
     }
 }
Beispiel #6
0
 protected void DoUnhandledTransition(IQHsm hsm, QState state, IQEvent qEvent)
 {
     if (OnUnhandledTransition(hsm, state, qEvent))
     {
         RaiseUnhandledTransition(UnhandledTransition, hsm, state, qEvent);
     }
 }
Beispiel #7
0
        protected virtual void LogRestored()
        {
            Delegate stateDelegate = Delegate.CreateDelegate(typeof(QStateDelegate), this, CurrentState.Name);
            QState   currentState  = new QState(this, (QStateDelegate)stateDelegate, CurrentState.Name);

            LogStateEvent(StateLogType.Restored, currentState);
        }
Beispiel #8
0
        /// <summary>
        /// Handles the transition from the source state to the target state without the help of a previously
        /// recorded transition chain.
        /// </summary>
        /// <param name="targetState">The <see cref="QState"/> representing the state to transition to.</param>
        /// <param name="recorder">An instance of <see cref="TransitionChainRecorder"/> or <see langword="null"/></param>
        /// <remarks>
        /// Passing in <see langword="null"/> as the recorder means that we deal with a dynamic transition.
        /// If an actual instance of <see cref="TransitionChainRecorder"/> is passed in then we deal with a static
        /// transition that was not recorded yet. In this case the function will record the transition steps
        /// as they are determined.
        /// </remarks>
        private void TransitionFromSourceToTarget(QState targetState, TransitionChainRecorder recorder)
        {
            ArrayList statesTargetToLCA;
            int       indexFirstStateToEnter;

            ExitUpToLCA(targetState, out statesTargetToLCA, out indexFirstStateToEnter, recorder);
            TransitionDownToTargetState(targetState, statesTargetToLCA, indexFirstStateToEnter, recorder);
        }
Beispiel #9
0
        public void LogStateEvent(StateLogType logType, QState state)
        {
            LogStateEventArgs logEvent = new LogStateEventArgs();

            logEvent.LogType = logType;
            logEvent.State   = state;
            DoStateChange(logEvent);
        }
Beispiel #10
0
 public void DoFinalStateReached(ILQHsm hsm, QState state)
 {
     if (OnFinalStateReached(hsm, state))
     {
         LogStateEvent(StateLogType.Final, state);
         RaiseFinalStateReached(FinalStateReached, hsm, state);
     }
 }
Beispiel #11
0
        public void LogStateEvent(StateLogType logType, QState state, string action)
        {
            LogStateEventArgs logEvent = new LogStateEventArgs();

            logEvent.LogType = logType;
            logEvent.State   = state;
            logEvent.LogText = action;
            DoStateChange(logEvent);
        }
Beispiel #12
0
        public void LogStateEvent(StateLogType logType, QState state, QState initState)
        {
            System.Diagnostics.Debug.Assert(logType == StateLogType.Init);
            LogStateEventArgs logEvent = new LogStateEventArgs();

            logEvent.LogType   = logType;
            logEvent.State     = state;
            logEvent.NextState = initState;
            DoStateChange(logEvent);
        }
Beispiel #13
0
 public virtual void RaiseFinalStateReached(EventHandler handler, ILQHsm hsm, QState state)
 {
     if (handler != null)
     {
         LogStateEventArgs logEvent = new LogStateEventArgs();
         logEvent.LogType = StateLogType.Final;
         logEvent.State   = state;
         handler(hsm, logEvent);
     }
 }
Beispiel #14
0
        /// <summary>
        /// Sends the specified signal to the specified state and (optionally) records the transition
        /// </summary>
        /// <param name="receiverState">The <see cref="QState"/> that represents the state method
        /// to which to send the signal.</param>
        /// <param name="qSignal">The <see cref="QSignals"/> to send.</param>
        /// <param name="recorder">An instance of <see cref="TransitionChainRecorder"/> if the transition
        /// is to be recorded; <see langword="null"/> otherwise.</param>
        /// <returns>The <see cref="QState"/> returned by the state that recieved the signal.</returns>
        /// <remarks>
        /// Even if a recorder is specified, the transition will only be recorded if the state
        /// <see paramref="receiverState"/> actually handled it.
        /// This function is used to record the transition chain for a static transition that is executed
        /// the first time.
        /// </remarks>
        private QState Trigger(QState receiverState, string qSignal, TransitionChainRecorder recorder)
        {
            QState state = Trigger(receiverState, qSignal);

            if ((state == null) && (recorder != null))
            {
                // The receiverState handled the event
                recorder.Record(receiverState, qSignal);
            }
            return(state);
        }
Beispiel #15
0
        public void PreInit()
        {
            _startState = TopState;
            if (_hsmS.StateMachineInfo.Name != null)
            {
                _name = _hsmS.StateMachineInfo.Name;
            }

            GQHSMManager.Instance.RegisterHsm(this);

            if (States != null)
            {
                foreach (GQHSMState gs in States)
                {
                    gs.PreInit(this);
                    if (gs.IsStartState)
                    {
                        _startState = gs.GetStateHandler();
                    }
                }
            }

            if (Transitions != null)
            {
                foreach (GQHSMTransition gt in Transitions)
                {
                    gt.PreInit(this);
                }
            }

            if (Components != null)
            {
                foreach (GQHSMComponent gc in Components)
                {
                    gc.PreInit(this);
                }
            }

            if (PortLinks != null)
            {
                foreach (GQHSMPortLink gpl in PortLinks)
                {
                    gpl.PreInit(this);
                }
            }

            if (Ports != null)
            {
                foreach (GQHSMPort gp in Ports)
                {
                    gp.PreInit(this);
                }
            }
        }
Beispiel #16
0
        public void LogStateEvent(StateLogType logType, QState state, QState toState, string eventName, string eventDescription)
        {
            LogStateEventArgs logEvent = new LogStateEventArgs();

            logEvent.LogType          = logType;
            logEvent.State            = state;
            logEvent.NextState        = toState;
            logEvent.EventName        = eventName;
            logEvent.EventDescription = eventDescription;
            DoStateChange(logEvent);
        }
Beispiel #17
0
        ///<summary>
        /// Retrieves the super state (parent state) of the specified
        /// state by sending it the empty signal.
        ///</summary>
        private MethodInfo GetSuperStateMethod(MethodInfo stateMethod)
        {
            QState superState = (QState)stateMethod.Invoke(this, new object[] { new QEvent((int)QSignals.Empty) });

            if (superState != null)
            {
                return(superState.GetMethodInfo());
            }
            else
            {
                return(null);
            }
        }
Beispiel #18
0
        private QState Trigger(QState state, string qSignal)
        {
            QState newState = (QState)state.Method.Invoke(state.calleeObject, new object[] { (IQEvent) new QEvent(qSignal) });

            if (newState == null)
            {
                return(null);
            }
            else
            {
                return(newState);
            }
        }
Beispiel #19
0
        /// <summary>
        /// Determines whether the state machine is in the state specified by <see paramref="inquiredState"/>.
        /// </summary>
        /// <param name="inquiredState">The state to check for.</param>
        /// <returns>
        /// <see langword="true"/> if the state machine is in the specified state;
        /// <see langword="false"/> otherwise.
        /// </returns>
        /// <remarks>
        /// If the currently active state of a hierarchical state machine is s then it is in the
        /// state s AND all its parent states.
        /// </remarks>
        public bool IsInState(QState inquiredState)
        {
            MethodInfo stateMethod;

            for (stateMethod = m_MyStateMethod;
                 stateMethod != null;
                 stateMethod = GetSuperStateMethod(stateMethod))
            {
                if (stateMethod == inquiredState.GetMethodInfo()) // do the states match?
                {
                    return(true);
                }
            }
            return(false); // no match found
        }
Beispiel #20
0
        /// <summary>
        /// Determines whether the state machine is in the state specified by <see paramref="inquiredState"/>.
        /// </summary>
        /// <param name="inquiredState">The state to check for.</param>
        /// <returns>
        /// <see langword="true"/> if the state machine is in the specified state;
        /// <see langword="false"/> otherwise.
        /// </returns>
        /// <remarks>
        /// If the currently active state of a hierarchical state machine is s then it is in the
        /// state s AND all its parent states.
        /// </remarks>
        public bool IsInState(QState inquiredState)
        {
            QState state;

            for (state = m_MyState;
                 state != null;
                 state = GetSuperState(state))
            {
                if (state == inquiredState)                 // do the states match?
                {
                    return(true);
                }
            }
            return(false);            // no match found
        }
Beispiel #21
0
        protected void ComplainIfUnhandled(QState state, IQEvent qEvent)
        {
            switch (qEvent.QSignal)
            {
            case QSignals.Init:
            case QSignals.Entry:
            case QSignals.Exit:
            case QSignals.Empty:
                break;

            default:
                DoUnhandledTransition(this, state, qEvent);
                break;
            }
        }
Beispiel #22
0
        /// <summary>
        /// Do a internal transition to another state using signalName
        /// </summary>
        /// <returns>
        /// true if handled
        /// </returns>
        /// <param name='signalName'>
        /// The name of the signal that will transition to another state
        /// </param>
        /// <param name='data'>
        /// any object that is passed between states
        /// </param>
        public bool StateTransitionInternal(string stateName, GQHSMParameters Params, string signalName)
        {
            GQHSMTransition transition         = null;
            string          fullTransitionName = stateName + "." + signalName;
            // if we know about the transition
            bool retVal = false;

            retVal = GetGuardedTransition(fullTransitionName, Params, ref transition);

            if (transition != null)
            {
                GQHSMState toState      = GetState(transition.GetDestinationStateID());
                GQHSMState fromState    = GetState(transition.GetSourceStateID());
                QState     stateHandler = GetTopState();
                if (toState != null)
                {
                    stateHandler = toState.GetStateHandler();
                }

                if (_instrument && !transition.DoNotInstrument)
                {
                    LogStateEvent(StateLogType.EventTransition, GetCurrentState(), stateHandler, transition.Name, signalName);
                }

                if (!transition.IsInnerTransition)
                {
                    DoTransitionTo(stateHandler, transition.GetSlot());
                }

                // still execute actions on this inner transition
                transition.InvokeActions();

                retVal = true;
            }
            else if (signalName == "Internal.TransitionTo")
            {
                if (Params.Count == 1)
                {
                    GQHSMState state = (GQHSMState)Params[0].Value;
                    DoTransitionTo(state.GetStateHandler());
                    return(true);
                }

                return(false);
            }

            return(retVal);
        }
Beispiel #23
0
        /// <summary>
        /// Get a QState delegate for a particular state
        /// </summary>
        /// <param name="Id"></param>
        /// <returns></returns>
        public QState GetStateHandler(Guid Id)
        {
            QState     returnState = GetTopState();
            GQHSMState foundState;

            if (Id != Guid.Empty)
            {
                foundState = GetState(Id);
                if (foundState != null)
                {
                    returnState = foundState.GetStateHandler();
                }
            }

            return(returnState);
        }
Beispiel #24
0
        private MethodInfo Trigger(MethodInfo stateMethod, QSignals qSignal)
        {
            var evt = new QEvent((int)qSignal);

            OnEvent(stateMethod, evt);
            QState state = (QState)stateMethod.Invoke(this, new object[] { evt });

            if (state == null)
            {
                return(null);
            }
            else
            {
                return(state.GetMethodInfo());
            }
        }
Beispiel #25
0
        /// <summary>
        /// Performs the transition from the current state to the specified target state.
        /// </summary>
        /// <param name="targetState">The <see cref="QState"/> to transition to.</param>
        /// <param name="transitionChain">A <see cref="TransitionChain"/> used to hold the transition chain that
        /// needs to be executed to perform the transition to the target state.</param>
        /// <remarks>
        /// The very first time that a given static transition is executed, the <see paramref="transitionChain"/>
        /// reference will point to <see langword="null"/>. In this case a new <see cref="TransitionChain"/>
        /// instance is created. As the complete transition is performed the individual transition steps are
        /// recorded in the new <see cref="TransitionChain"/> instance. At the end of the call the new
        /// (and now filled) <see cref="TransitionChain"/> is handed back to the caller.
        /// If the same transition needs to be performed later again, the caller needs to pass
        /// in the filled <see cref="TransitionChain"/> instance. The recorded transition path will then be
        /// played back very efficiently.
        /// </remarks>
        protected void TransitionTo(QState targetState, ref TransitionChain transitionChain)
        {
            Debug.Assert(targetState != s_TopState);             // can't target 'top' state
            ExitUpToSourceState();

            if (transitionChain == null)             // for efficiency the first check is not thread-safe
            {
                // We implement the double-checked locking pattern
                TransitionToSynchronized(targetState, ref transitionChain);
            }
            else
            {
                // We just need to 'replay' the transition chain that is stored in the transitions chain.
                ExecuteTransitionChain(transitionChain);
            }
        }
Beispiel #26
0
        ///<summary>
        /// Retrieves the super state (parent state) of the specified
        /// state by sending it the empty signal.
        ///</summary>
        private QState GetSuperState(QState state)
        {
            QState superState;

            // don't care what type of object takes the method invocation
            superState = (QState)state.Method.Invoke(state.calleeObject, new object[] { new QEvent(QSignals.Empty) });

            if (superState != null)
            {
                return(superState);
            }
            else
            {
                return(null);
            }
        }
Beispiel #27
0
        private void ExecuteTransitionChain(TransitionChain transitionChain)
        {
            // There must always be at least one transition step in the provided transition chain
            Debug.Assert(transitionChain.Length > 0);

            TransitionStep transitionStep = transitionChain[0];             // to shut up the compiler;

            // without it we would get the following error on the line
            //       m_MyState = transitionStep.State;
            // at the end of this method: Use of possibly unassigned field 'State'
            for (int i = 0; i < transitionChain.Length; i++)
            {
                transitionStep = transitionChain[i];
                Trigger(transitionStep.State, transitionStep.QSignal);
            }
            m_MyState = transitionStep.State;
        }
Beispiel #28
0
        public override void PreInit(GQHSM parentHSM)
        {
            base.PreInit(parentHSM);
            _fullName = _parentHSM.RegisterState(this);
            if (ChildStates != null)
            {
                foreach (GQHSMState gs in ChildStates)
                {
                    gs.PreInit(parentHSM);
                    if (gs.IsStartState)
                    {
                        _childStartState = gs;
                    }
                }
            }

            _stateHandler = new QState(this, StateHandler, Name);
        }
Beispiel #29
0
 /// <summary>
 /// Dispatches the specified event to this state machine
 /// </summary>
 /// <param name="qEvent">The <see cref="IQEvent"/> to dispatch.</param>
 protected void CoreDispatch(IQEvent qEvent)
 {
     // We let the event bubble up the chain until it is handled by a state handler
     m_MySourceStateMethod = m_MyStateMethod;
     do
     {
         OnEvent(m_MySourceStateMethod, qEvent);
         QState state = (QState)m_MySourceStateMethod.Invoke(this, new object[] { qEvent });
         if (state != null)
         {
             m_MySourceStateMethod = state.GetMethodInfo();
         }
         else
         {
             m_MySourceStateMethod = null;
         }
     } while (m_MySourceStateMethod != null);
 }
Beispiel #30
0
 private void ExitUpToSourceState()
 {
     for (QState state = m_MyState; state != m_MySourceState;)
     {
         Debug.Assert(state != null);
         QState stateToHandleExit = Trigger(state, QSignals.Exit);
         if (stateToHandleExit != null)
         {
             // state did not handle the Exit signal itself
             state = stateToHandleExit;
         }
         else
         {
             // state handled the Exit signal. We need to elicit
             // the superstate explicitly.
             state = GetSuperState(state);
         }
     }
 }