Beispiel #1
0
/*..........................................................................*/
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 */
}
Beispiel #2
0
//............................................................................
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_()
}
Beispiel #3
0
/*..........................................................................*/
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_()

    }