QP/C++
qf.h
Go to the documentation of this file.
00001 
00002 // Product: QP/C++
00003 // Last Updated for Version: 4.5.04
00004 // Date of the Last Update:  Feb 04, 2013
00005 //
00006 //                    Q u a n t u m     L e a P s
00007 //                    ---------------------------
00008 //                    innovating embedded systems
00009 //
00010 // Copyright (C) 2002-2013 Quantum Leaps, LLC. All rights reserved.
00011 //
00012 // This program is open source software: you can redistribute it and/or
00013 // modify it under the terms of the GNU General Public License as published
00014 // by the Free Software Foundation, either version 2 of the License, or
00015 // (at your option) any later version.
00016 //
00017 // Alternatively, this program may be distributed and modified under the
00018 // terms of Quantum Leaps commercial licenses, which expressly supersede
00019 // the GNU General Public License and are specifically designed for
00020 // licensees interested in retaining the proprietary status of their code.
00021 //
00022 // This program is distributed in the hope that it will be useful,
00023 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00024 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00025 // GNU General Public License for more details.
00026 //
00027 // You should have received a copy of the GNU General Public License
00028 // along with this program. If not, see <http://www.gnu.org/licenses/>.
00029 //
00030 // Contact information:
00031 // Quantum Leaps Web sites: http://www.quantum-leaps.com
00032 //                          http://www.state-machine.com
00033 // e-mail:                  info@quantum-leaps.com
00035 #ifndef qf_h
00036 #define qf_h
00037 
00044 
00046 #ifdef Q_EVT_CTOR
00047 #include <new>                                            // for placement new
00048 #endif
00049 
00051 // apply defaults for all undefined configuration parameters
00052 //
00053 #ifndef QF_EVENT_SIZ_SIZE
00054 
00055     #define QF_EVENT_SIZ_SIZE    2
00056 #endif
00057 
00058 #ifndef QF_MAX_EPOOL
00059 
00060     #define QF_MAX_EPOOL         3
00061 #endif
00062 
00063 #ifndef QF_TIMEEVT_CTR_SIZE
00064 
00065 
00066     #define QF_TIMEEVT_CTR_SIZE  2
00067 #endif
00068 
00069 #if (QF_MAX_ACTIVE < 1) || (63 < QF_MAX_ACTIVE)
00070     #error "QF_MAX_ACTIVE not defined or out of range. Valid range is 1..63"
00071 #endif
00072 
00073 #ifndef QF_ACTIVE_SUPER_
00074 
00090     #define QF_ACTIVE_SUPER_  QHsm
00091 
00093     #define QF_ACTIVE_STATE_  QStateHandler
00094 
00095 #endif
00096 
00098 QP_BEGIN_
00099 
00101 #if (QF_EVENT_SIZ_SIZE == 1)
00102 
00108     typedef uint8_t QEvtSize;
00109 #elif (QF_EVENT_SIZ_SIZE == 2)
00110     typedef uint16_t QEvtSize;
00111 #elif (QF_EVENT_SIZ_SIZE == 4)
00112     typedef uint32_t QEvtSize;
00113 #else
00114     #error "QF_EVENT_SIZ_SIZE defined incorrectly, expected 1, 2, or 4"
00115 #endif
00116 
00118 #if (QF_TIMEEVT_CTR_SIZE == 1)
00119 
00120 
00121 
00122 
00123 
00124 
00125 
00126 
00127     typedef uint8_t QTimeEvtCtr;
00128 #elif (QF_TIMEEVT_CTR_SIZE == 2)
00129     typedef uint16_t QTimeEvtCtr;
00130 #elif (QF_TIMEEVT_CTR_SIZE == 4)
00131     typedef uint32_t QTimeEvtCtr;
00132 #else
00133     #error "QF_TIMEEVT_CTR_SIZE defined incorrectly, expected 1, 2, or 4"
00134 #endif
00135 
00136 class QEQueue;                                          // forward declaration
00137 
00158 class QActive : public QF_ACTIVE_SUPER_ {
00159 
00160 #ifdef QF_EQUEUE_TYPE
00161 
00162 
00163 
00164 
00165 
00166 
00167 
00168 
00169 
00170     QF_EQUEUE_TYPE m_eQueue;
00171 #endif
00172 
00173 #ifdef QF_OS_OBJECT_TYPE
00174 
00175 
00176 
00177 
00178 
00179 
00180     QF_OS_OBJECT_TYPE m_osObject;
00181 #endif
00182 
00183 #ifdef QF_THREAD_TYPE
00184 
00185 
00186 
00187 
00188 
00189 
00190     QF_THREAD_TYPE m_thread;
00191 #endif
00192 
00195     uint8_t m_prio;
00196 
00197 public:
00224     void start(uint8_t const prio,
00225                QEvt const *qSto[], uint32_t const qLen,
00226                void * const stkSto, uint32_t const stkSize,
00227                QEvt const * const ie = static_cast<QEvt *>(0));
00228 
00247 #ifndef Q_SPY
00248     void postFIFO(QEvt const * const e);
00249 #else
00250     void postFIFO(QEvt const * const e, void const * const sender);
00251 #endif
00252 
00271     void unsubscribeAll(void) const;
00272 
00273 protected:
00283     QActive(QF_ACTIVE_STATE_ const initial) : QF_ACTIVE_SUPER_(initial) {
00284     }
00285 
00293     void postLIFO(QEvt const * const e);
00294 
00308     void stop(void);
00309 
00323     void subscribe(enum_t const sig) const;
00324 
00343     void unsubscribe(enum_t const sig) const;
00344 
00358     void defer(QEQueue * const eq, QEvt const * const e) const;
00359 
00375     bool recall(QEQueue * const eq);
00376 
00377 private:
00378 
00392     QEvt const *get_(void);
00393 
00394     friend class QF;
00395     friend class QTimeEvt;
00396 
00397 #ifdef qk_h                                                // is this QK port?
00398     friend void ::QK_schedExt_(uint8_t p);
00399     friend void ::QK_sched_(uint8_t p);
00400 #endif
00401 
00402 };
00403 
00435 class QTimeEvt : public QEvt {
00436 private:
00437 
00439     QTimeEvt *m_next;
00440 
00442     QActive *m_act;
00443 
00447     QTimeEvtCtr m_ctr;
00448 
00453     QTimeEvtCtr m_interval;
00454 
00455 public:
00456 
00469     QTimeEvt(enum_t const s);
00470 
00488     void postIn(QActive * const act, QTimeEvtCtr const nTicks) {
00489         m_interval = static_cast<QTimeEvtCtr>(0);
00490         arm_(act, nTicks);
00491     }
00492 
00513     void postEvery(QActive * const act, QTimeEvtCtr const nTicks) {
00514         m_interval = nTicks;
00515         arm_(act, nTicks);
00516     }
00517 
00528     bool disarm(void);
00529 
00546     bool rearm(QTimeEvtCtr const nTicks);
00547 
00555     QTimeEvtCtr ctr(void) const;
00556 
00557 private:
00558 
00564     void arm_(QActive * const act, QTimeEvtCtr const nTicks);
00565 
00566     friend class QF;
00567 };
00568 
00569 
00575 uint8_t const QF_SUBSCR_LIST_SIZE =
00576     static_cast<uint8_t>(((QF_MAX_ACTIVE - 1) / 8) + 1);
00577 
00583 class QSubscrList {
00584 private:
00585 
00594     uint8_t m_bits[QF_SUBSCR_LIST_SIZE];
00595 
00596     friend class QF;
00597     friend class QActive;
00598 };
00599 
00605 class QF {
00606 public:
00607 
00612     static void init(void);
00613 
00639     static void psInit(QSubscrList * const subscrSto,
00640                        uint32_t const maxSignal);
00641 
00674     static void poolInit(void * const poolSto, uint32_t const poolSize,
00675                          uint32_t const evtSize);
00676 
00699     static int16_t run(void);
00700 
00706     static void onStartup(void);
00707 
00720     static void onCleanup(void);
00721 
00746     static void onIdle(void);
00747 
00765     static void stop(void);
00766 
00778 #ifndef Q_SPY
00779     static void publish(QEvt const *e);
00780 #else
00781     static void publish(QEvt const *e, void const *sender);
00782 #endif
00783 
00798 #ifndef Q_SPY
00799     static void tick(void);
00800 #else
00801     static void tick(void const * const sender);
00802 #endif
00803 
00808     static bool noTimeEvtsActive(void);
00809 
00819     static char_t const Q_ROM * Q_ROM_VAR getVersion(void);
00820 
00833     static uint32_t getPoolMargin(uint8_t const poolId);
00834 
00846     static uint32_t getQueueMargin(uint8_t const prio);
00847 
00852     static QEvt *new_(QEvtSize const evtSize, enum_t const sig);
00853 
00875     static void gc(QEvt const *e);
00876 
00877 private:                              // functions to be used in QF ports only
00878 
00889     static void add_(QActive * const a);
00890 
00891 public:
00903     static void remove_(QActive const * const a);
00904 
00908     static QActive *active_[];
00909 
00914     static void thread_(QActive *act);
00915 
00916     friend class QActive;
00917 };
00918 
00919 QP_END_
00920 
00922 #ifdef Q_EVT_CTOR               // Provide the constructor for the QEvt class?
00923 
00938     #define Q_NEW(evtT_, sig_, ...) \
00939         (new(QP_ QF::new_( \
00940             static_cast<QP_ QEvtSize>(sizeof(evtT_)), (sig_))) \
00941             evtT_((sig_),  ##__VA_ARGS__))
00942 #else                                    // QEvt is a POD (Plain Old Datatype)
00943 
00944     #define Q_NEW(evtT_, sig_) \
00945         (static_cast<evtT_ *>( \
00946             QP_ QF::new_(static_cast<QP_ QEvtSize>(sizeof(evtT_)), (sig_))))
00947 #endif
00948 
00950 // QS software tracing integration, only if enabled
00951 #ifdef Q_SPY                                   // QS software tracing enabled?
00952 
00972     #define TICK(sender_)                  tick(sender_)
00973 
00992     #define PUBLISH(e_, sender_)           publish((e_), (sender_))
00993 
01012     #define POST(e_, sender_)              postFIFO((e_), (sender_))
01013 
01014 #else
01015 
01016     #define TICK(dummy_)                   tick()
01017     #define PUBLISH(e_, dummy_)            publish(e_)
01018     #define POST(e_, dummy_)               postFIFO(e_)
01019 
01020 #endif                                                                // Q_SPY
01021 
01022 #endif                                                                 // qf_h