/*..........................................................................*/ void QHsm_init(QHsm * const me, QEvt const * const e) { QStateHandler t = me->state.fun; QS_CRIT_STAT_ Q_REQUIRE((me->vptr != (QMsmVtbl const *)0) /* ctor must be executed */ && (me->temp.fun != Q_STATE_CAST(0)) /* ctor must be executed */ && (t == Q_STATE_CAST(&QHsm_top))); /*initial tran. NOT taken */ /* the top-most initial transition must be taken */ Q_ALLEGE((*me->temp.fun)(me, e) == (QState)Q_RET_TRAN); do { /* drill into the target... */ QStateHandler path[QEP_MAX_NEST_DEPTH_]; int_t ip = (int_t)0; /* transition entry path index */ QS_BEGIN_(QS_QEP_STATE_INIT, QS_priv_.smObjFilter, me) QS_OBJ_(me); /* this state machine object */ QS_FUN_(t); /* the source state */ QS_FUN_(me->temp.fun); /* the target of the initial transition */ QS_END_() path[0] = me->temp.fun; (void)QEP_TRIG_(me->temp.fun, QEP_EMPTY_SIG_); while (me->temp.fun != t) { ++ip; path[ip] = me->temp.fun; (void)QEP_TRIG_(me->temp.fun, QEP_EMPTY_SIG_); } me->temp.fun = path[0]; /* entry path must not overflow */ Q_ASSERT(ip < (int_t)QEP_MAX_NEST_DEPTH_); do { /* retrace the entry path in reverse (desired) order... */ QEP_ENTER_(path[ip]); /* enter path[ip] */ --ip; } while (ip >= (int_t)0); t = path[0]; /* current state becomes the new source */ } while (QEP_TRIG_(t, Q_INIT_SIG) == (QState)Q_RET_TRAN); QS_BEGIN_(QS_QEP_INIT_TRAN, QS_priv_.smObjFilter, me) QS_TIME_(); /* time stamp */ QS_OBJ_(me); /* this state machine object */ QS_FUN_(t); /* the new active state */ QS_END_() me->state.fun = t; /* change the current active state */ me->temp.fun = t; /* mark the configuration as stable */ }
//............................................................................ void QHsm::init(QEvent const *e) { QStateHandler t; QS_INT_LOCK_KEY_ // the top-most initial transition must be taken Q_ALLEGE((*m_state)(this, e) == Q_RET_TRAN); t = (QStateHandler)&QHsm::top; // HSM starts in the top state do { // drill into the target... QStateHandler path[QEP_MAX_NEST_DEPTH_]; int8_t ip = (int8_t)0; // transition entry path index QS_BEGIN_(QS_QEP_STATE_INIT, QS::smObj_, this) QS_OBJ_(this); // this state machine object QS_FUN_(t); // the source state QS_FUN_(m_state); // the target of the initial transition QS_END_() path[0] = m_state; (void)QEP_TRIG_(m_state, QEP_EMPTY_SIG_); while (m_state != t) { ++ip; path[ip] = m_state; (void)QEP_TRIG_(m_state, QEP_EMPTY_SIG_); } m_state = path[0]; // entry path must not overflow Q_ASSERT(ip < (int8_t)QEP_MAX_NEST_DEPTH_); do { // retrace the entry path in reverse (desired) order... QEP_ENTER_(path[ip]); // enter path[ip] --ip; } while (ip >= (int8_t)0); t = path[0]; // current state becomes the new source } while (QEP_TRIG_(t, Q_INIT_SIG) == Q_RET_TRAN); m_state = t; QS_BEGIN_(QS_QEP_INIT_TRAN, QS::smObj_, this) QS_TIME_(); // time stamp QS_OBJ_(this); // this state machine object QS_FUN_(m_state); // the new active state QS_END_() }
/*..........................................................................*/ void QHsm_dispatch(QHsm *me, QEvent const *e) { QStateHandler path[QEP_MAX_NEST_DEPTH_]; QStateHandler s; QStateHandler t; QState r; QS_INT_LOCK_KEY_ t = me->state; /* save the current state */ QS_BEGIN_(QS_QEP_DISPATCH, QS_smObj_, me) QS_TIME_(); /* time stamp */ QS_SIG_(e->sig); /* the signal of the event */ QS_OBJ_(me); /* this state machine object */ QS_FUN_(t); /* the current state */ QS_END_() do { /* process the event hierarchically... */ s = me->state; r = (*s)(me, e); /* invoke state handler s */ } while (r == Q_RET_SUPER); if (r == Q_RET_TRAN) { /* transition taken? */ #ifdef Q_SPY QStateHandler src = s; /* save the transition source for tracing */ #endif int8_t ip = (int8_t)(-1); /* transition entry path index */ int8_t iq; /* helper transition entry path index */ path[0] = me->state; /* save the target of the transition */ path[1] = t; while (t != s) { /* exit current state to transition source s... */ if (QEP_TRIG_(t, Q_EXIT_SIG) == Q_RET_HANDLED) {/*exit handled? */ QS_BEGIN_(QS_QEP_STATE_EXIT, QS_smObj_, me) QS_OBJ_(me); /* this state machine object */ QS_FUN_(t); /* the exited state */ QS_END_() (void)QEP_TRIG_(t, QEP_EMPTY_SIG_); /* find superstate of t */ } t = me->state; /* me->state holds the superstate */ } t = path[0]; /* target of the transition */ if (s == t) { /* (a) check source==target (transition to self) */ QEP_EXIT_(s) /* exit the source */ ip = (int8_t)0; /* enter the target */ } else { (void)QEP_TRIG_(t, QEP_EMPTY_SIG_); /* superstate of target */ t = me->state; if (s == t) { /* (b) check source==target->super */ ip = (int8_t)0; /* enter the target */ } else { (void)QEP_TRIG_(s, QEP_EMPTY_SIG_); /* superstate of src */ /* (c) check source->super==target->super */ if (me->state == t) { QEP_EXIT_(s) /* exit the source */ ip = (int8_t)0; /* enter the target */ } else { /* (d) check source->super==target */ if (me->state == path[0]) { QEP_EXIT_(s) /* exit the source */ } else { /* (e) check rest of source==target->super->super.. * and store the entry path along the way */ iq = (int8_t)0; /* indicate that LCA not found */ ip = (int8_t)1; /* enter target and its superstate */ path[1] = t; /* save the superstate of target */ t = me->state; /* save source->super */ /* find target->super->super */ r = QEP_TRIG_(path[1], QEP_EMPTY_SIG_); while (r == Q_RET_SUPER) { ++ip; path[ip] = me->state; /* store the entry path */ if (me->state == s) { /* is it the source? */ iq = (int8_t)1; /* indicate that LCA found */ /* entry path must not overflow */ Q_ASSERT(ip < (int8_t)QEP_MAX_NEST_DEPTH_); --ip; /* do not enter the source */ r = Q_RET_HANDLED; /* terminate the loop */ } else { /* it is not the source, keep going up */ r = QEP_TRIG_(me->state, QEP_EMPTY_SIG_); } } if (iq == (int8_t)0) { /* the LCA not found yet? */ /* entry path must not overflow */ Q_ASSERT(ip < (int8_t)QEP_MAX_NEST_DEPTH_); QEP_EXIT_(s) /* exit the source */ /* (f) check the rest of source->super * == target->super->super... */ iq = ip; r = Q_RET_IGNORED; /* indicate LCA NOT found */ do { if (t == path[iq]) { /* is this the LCA? */ r = Q_RET_HANDLED;/* indicate LCA found */ ip = (int8_t)(iq - 1);/*do not enter LCA*/ iq = (int8_t)(-1);/* terminate the loop */ } else { --iq; /* try lower superstate of target */ } } while (iq >= (int8_t)0); if (r != Q_RET_HANDLED) { /* LCA not found yet? */ /* (g) check each source->super->... * for each target->super... */ r = Q_RET_IGNORED; /* keep looping */ do { /* exit t unhandled? */ if (QEP_TRIG_(t, Q_EXIT_SIG) == Q_RET_HANDLED) { QS_BEGIN_(QS_QEP_STATE_EXIT, QS_smObj_, me) QS_OBJ_(me); QS_FUN_(t); QS_END_() (void)QEP_TRIG_(t, QEP_EMPTY_SIG_); } t = me->state; /* set to super of t */ iq = ip; do { if (t == path[iq]) {/* is this LCA? */ /* do not enter LCA */ ip = (int8_t)(iq - 1); iq = (int8_t)(-1);/*break inner */ r = Q_RET_HANDLED;/*break outer */ } else { --iq; } } while (iq >= (int8_t)0); } while (r != Q_RET_HANDLED); } } } } } } /* retrace the entry path in reverse (desired) order... */ for (; ip >= (int8_t)0; --ip) { QEP_ENTER_(path[ip]) /* enter path[ip] */ } t = path[0]; /* stick the target into register */ me->state = t; /* update the current state */ /* drill into the target hierarchy... */ while (QEP_TRIG_(t, Q_INIT_SIG) == Q_RET_TRAN) { QS_BEGIN_(QS_QEP_STATE_INIT, QS_smObj_, me) QS_OBJ_(me); /* this state machine object */ QS_FUN_(t); /* the source (pseudo)state */ QS_FUN_(me->state); /* the target of the transition */ QS_END_() ip = (int8_t)0; path[0] = me->state; (void)QEP_TRIG_(me->state, QEP_EMPTY_SIG_); /* find superstate */ while (me->state != t) { ++ip; path[ip] = me->state; (void)QEP_TRIG_(me->state, QEP_EMPTY_SIG_);/*find superstate*/ } me->state = path[0]; /* entry path must not overflow */ Q_ASSERT(ip < (int8_t)QEP_MAX_NEST_DEPTH_); do { /* retrace the entry path in reverse (correct) order... */ QEP_ENTER_(path[ip]) /* enter path[ip] */ --ip; } while (ip >= (int8_t)0); t = path[0]; } QS_BEGIN_(QS_QEP_TRAN, QS_smObj_, me) QS_TIME_(); /* time stamp */ QS_SIG_(e->sig); /* the signal of the event */ QS_OBJ_(me); /* this state machine object */ QS_FUN_(src); /* the source of the transition */ QS_FUN_(t); /* the new active state */ QS_END_() }