qhsm_dis.cpp

Go to the documentation of this file.
00001 
00002 // Product: QEP/C++
00003 // Last Updated for Version: 4.0.00
00004 // Date of the Last Update:  Apr 06, 2008
00005 //
00006 //                    Q u a n t u m     L e a P s
00007 //                    ---------------------------
00008 //                    innovating embedded systems
00009 //
00010 // Copyright (C) 2002-2008 Quantum Leaps, LLC. All rights reserved.
00011 //
00012 // This software may be distributed and modified under the terms of the GNU
00013 // General Public License version 2 (GPL) as published by the Free Software
00014 // Foundation and appearing in the file GPL.TXT included in the packaging of
00015 // this file. Please note that GPL Section 2[b] requires that all works based
00016 // on this software must also be made publicly available under the terms of
00017 // the GPL ("Copyleft").
00018 //
00019 // Alternatively, this software may be distributed and modified under the
00020 // terms of Quantum Leaps commercial licenses, which expressly supersede
00021 // the GPL and are specifically designed for licensees interested in
00022 // retaining the proprietary status of their code.
00023 //
00024 // Contact information:
00025 // Quantum Leaps Web site:  http://www.quantum-leaps.com
00026 // e-mail:                  info@quantum-leaps.com
00028 #include "qep_pkg.h"
00029 #include "qassert.h"
00030 
00031 Q_DEFINE_THIS_MODULE(qhsm_dis)
00032 
00033 
00034 
00035 
00036 
00037 //............................................................................
00038 void QHsm::dispatch(QEvent const *e) {
00039     QStateHandler path[QEP_MAX_NEST_DEPTH_];
00040     QStateHandler s;
00041     QStateHandler t;
00042     QState r;
00043     QS_INT_LOCK_KEY_
00044 
00045     t = m_state;                                     // save the current state
00046 
00047     do {                                // process the event hierarchically...
00048         s = m_state;
00049         r = (*s)(this, e);                           // invoke state handler s
00050     } while (r == Q_RET_SUPER);
00051 
00052     if (r == Q_RET_TRAN) {                                // transition taken?
00053 #ifdef Q_SPY
00054         QStateHandler src = s;       // save the transition source for tracing
00055 #endif
00056         int8_t ip = (int8_t)(-1);               // transition entry path index
00057         int8_t iq;                       // helper transition entry path index
00058 
00059         path[0] = m_state;                // save the target of the transition
00060         path[1] = t;
00061 
00062         while (t != s) {       // exit current state to transition source s...
00063             if (QEP_TRIG_(t, Q_EXIT_SIG) == Q_RET_HANDLED) {   //exit handled?
00064                 QS_BEGIN_(QS_QEP_STATE_EXIT, QS::smObj_, this)
00065                     QS_OBJ_(this);                // this state machine object
00066                     QS_FUN_(t);                            // the exited state
00067                 QS_END_()
00068 
00069                 (void)QEP_TRIG_(t, QEP_EMPTY_SIG_);    // find superstate of t
00070             }
00071             t = m_state;                       // m_state holds the superstate
00072         }
00073 
00074         t = path[0];                               // target of the transition
00075 
00076         if (s == t) {         // (a) check source==target (transition to self)
00077             QEP_EXIT_(s)                                    // exit the source
00078             ip = (int8_t)0;                                // enter the target
00079         }
00080         else {
00081             (void)QEP_TRIG_(t, QEP_EMPTY_SIG_);        // superstate of target
00082             t = m_state;
00083             if (s == t) {                   // (b) check source==target->super
00084                 ip = (int8_t)0;                            // enter the target
00085             }
00086             else {
00087                 (void)QEP_TRIG_(s, QEP_EMPTY_SIG_);       // superstate of src
00088                                      // (c) check source->super==target->super
00089                 if (m_state == t) {
00090                     QEP_EXIT_(s)                            // exit the source
00091                     ip = (int8_t)0;                        // enter the target
00092                 }
00093                 else {
00094                                             // (d) check source->super==target
00095                     if (m_state == path[0]) {
00096                         QEP_EXIT_(s)                        // exit the source
00097                     }
00098                     else { // (e) check rest of source==target->super->super..
00099                            // and store the entry path along the way
00100                            //
00101                         iq = (int8_t)0;         // indicate that LCA not found
00102                         ip = (int8_t)1;     // enter target and its superstate
00103                         path[1] = t;          // save the superstate of target
00104                         t = m_state;                     // save source->super
00105                                                   // find target->super->super
00106                         r = QEP_TRIG_(path[1], QEP_EMPTY_SIG_);
00107                         while (r == Q_RET_SUPER) {
00108                             path[++ip] = m_state;      // store the entry path
00109                             if (m_state == s) {           // is it the source?
00110                                 iq = (int8_t)1;     // indicate that LCA found
00111                                                // entry path must not overflow
00112                                 Q_ASSERT(ip < (int8_t)QEP_MAX_NEST_DEPTH_);
00113                                 --ip;               // do not enter the source
00114                                 r = Q_RET_HANDLED;       // terminate the loop
00115                             }
00116                             else {      // it is not the source, keep going up
00117                                 r = QEP_TRIG_(m_state, QEP_EMPTY_SIG_);
00118                             }
00119                         }
00120                         if (iq == (int8_t)0) {       // the LCA not found yet?
00121 
00122                                                // entry path must not overflow
00123                             Q_ASSERT(ip < (int8_t)QEP_MAX_NEST_DEPTH_);
00124 
00125                             QEP_EXIT_(s)                   // exit the source
00126 
00127                             // (f) check the rest of source->super
00128                             //                  == target->super->super...
00129                             //
00130                             iq = ip;
00131                             r = Q_RET_IGNORED;       // indicate LCA NOT found
00132                             do {
00133                                 if (t == path[iq]) {       // is this the LCA?
00134                                     r = Q_RET_HANDLED;   // indicate LCA found
00135                                     ip = (int8_t)(iq - 1); // do not enter LCA
00136                                     iq = (int8_t)(-1);   // terminate the loop
00137                                 }
00138                                 else {
00139                                     --iq;    // try lower superstate of target
00140                                 }
00141                             } while (iq >= (int8_t)0);
00142 
00143                             if (r != Q_RET_HANDLED) {    // LCA not found yet?
00144                                 // (g) check each source->super->...
00145                                 // for each target->super...
00146                                 //
00147                                 r = Q_RET_IGNORED;             // keep looping
00148                                 do {
00149                                                           // exit t unhandled?
00150                                     if (QEP_TRIG_(t, Q_EXIT_SIG)
00151                                         == Q_RET_HANDLED)
00152                                     {
00153                                         QS_BEGIN_(QS_QEP_STATE_EXIT,
00154                                                   QS::smObj_, this)
00155                                             QS_OBJ_(this);
00156                                             QS_FUN_(t);
00157                                         QS_END_()
00158 
00159                                         (void)QEP_TRIG_(t, QEP_EMPTY_SIG_);
00160                                     }
00161                                     t = m_state;         //  set to super of t
00162                                     iq = ip;
00163                                     do {
00164                                         if (t == path[iq]) {   // is this LCA?
00165                                                            // do not enter LCA
00166                                             ip = (int8_t)(iq - 1);
00167                                             iq = (int8_t)(-1);   //break inner
00168                                             r = Q_RET_HANDLED;   //break outer
00169                                         }
00170                                         else {
00171                                             --iq;
00172                                         }
00173                                     } while (iq >= (int8_t)0);
00174                                 } while (r != Q_RET_HANDLED);
00175                             }
00176                         }
00177                     }
00178                 }
00179             }
00180         }
00181                        // retrace the entry path in reverse (desired) order...
00182         for (; ip >= (int8_t)0; --ip) {
00183             QEP_ENTER_(path[ip])                             // enter path[ip]
00184         }
00185         t = path[0];                         // stick the target into register
00186         m_state = t;                               // update the current state
00187 
00188                                          // drill into the target hierarchy...
00189         while (QEP_TRIG_(t, Q_INIT_SIG) == Q_RET_TRAN) {
00190 
00191             QS_BEGIN_(QS_QEP_STATE_INIT, QS::smObj_, this)
00192                 QS_OBJ_(this);                    // this state machine object
00193                 QS_FUN_(t);                        // the source (pseudo)state
00194                 QS_FUN_(m_state);              // the target of the transition
00195             QS_END_()
00196 
00197             ip = (int8_t)0;
00198             path[0] = m_state;
00199             (void)QEP_TRIG_(m_state, QEP_EMPTY_SIG_);       // find superstate
00200             while (m_state != t) {
00201                 path[++ip] = m_state;
00202                 (void)QEP_TRIG_(m_state, QEP_EMPTY_SIG_);   // find superstate
00203             }
00204             m_state = path[0];
00205                                                // entry path must not overflow
00206             Q_ASSERT(ip < (int8_t)QEP_MAX_NEST_DEPTH_);
00207 
00208             do {       // retrace the entry path in reverse (correct) order...
00209                 QEP_ENTER_(path[ip])                         // enter path[ip]
00210             } while ((--ip) >= (int8_t)0);
00211 
00212             t = path[0];
00213         }
00214 
00215         QS_BEGIN_(QS_QEP_TRAN, QS::smObj_, this)
00216             QS_TIME_();                                          // time stamp
00217             QS_SIG_(e->sig);                        // the signal of the event
00218             QS_OBJ_(this);                        // this state machine object
00219             QS_FUN_(src);                      // the source of the transition
00220             QS_FUN_(t);                                // the new active state
00221         QS_END_()
00222 
00223     }
00224     else {                                             // transition not taken
00225 #ifdef Q_SPY
00226         if (r == Q_RET_IGNORED) {                            // event ignored?
00227 
00228             QS_BEGIN_(QS_QEP_IGNORED, QS::smObj_, this)
00229                 QS_TIME_();                                      // time stamp
00230                 QS_SIG_(e->sig);                    // the signal of the event
00231                 QS_OBJ_(this);                    // this state machine object
00232                 QS_FUN_(t);                               // the current state
00233             QS_END_()
00234 
00235         }
00236         else {                                                // event handled
00237 
00238             QS_BEGIN_(QS_QEP_INTERN_TRAN, QS::smObj_, this)
00239                 QS_TIME_();                                      // time stamp
00240                 QS_SIG_(e->sig);                    // the signal of the event
00241                 QS_OBJ_(this);                    // this state machine object
00242                 QS_FUN_(s);                // the state that handled the event
00243             QS_END_()
00244 
00245         }
00246 #endif
00247     }
00248     m_state = t;                 // set new state or restore the current state
00249 }

Generated on Sat Dec 27 21:35:25 2008 for QP/C++ by  doxygen 1.5.4