#include <qf.h>
Public Member Functions | |
| void | start (uint8_t prio, QEvent const *qSto[], uint32_t qLen, void *stkSto, uint32_t stkSize, QEvent const *ie=(QEvent *) 0) |
| Starts execution of an active object and registers the object with the framework. | |
| void | postFIFO (QEvent const *e) |
| Posts an event e directly to the event queue of the acitve object me using the First-In-First-Out (FIFO) policy. | |
| void | postLIFO (QEvent const *e) |
| Posts an event directly to the event queue of the active object me using the Last-In-First-Out (LIFO) policy. | |
| void | run (void) |
| Traditional loop-structured thread routine for an active object. | |
| QEvent const * | get_ (void) |
| Get an event from the event queue of an active object. | |
| void | unsubscribeAll (void) const |
| Un-subscribes from the delivery of all signals to the active object. | |
Public Attributes | |
| uint8_t | m_prio |
| QF priority associated with the active object. | |
| uint8_t | m_running |
| The Boolean loop variable determining if the thread routine of the active object is running. | |
Protected Member Functions | |
| QActive (QF_ACTIVE_STATE_ initial) | |
| protected constructor | |
| void | stop (void) |
| Stops execution of an active object and removes it from the framework's supervision. | |
| void | subscribe (QSignal sig) const |
| Subscribes for delivery of signal sig to the active object. | |
| void | unsubscribe (QSignal sig) const |
| Un-subscribes from the delivery of signal sig to the active object. | |
| void | defer (QEQueue *eq, QEvent const *e) |
| Defer an event to a given separate event queue. | |
| QEvent const * | recall (QEQueue *eq) |
| Recall a deferred event from a given event queue. | |
Friends | |
| class | QF |
| class | QTimeEvt |
QActive is the base class for derivation of active objects. Active objects in QF are encapsulated tasks (each embedding a state machine and an event queue) that communicate with one another asynchronously by sending and receiving events. Within an active object, events are processed sequentially in a run-to-completion (RTC) fashion, while QF encapsulates all the details of thread-safe event exchange and queuing.
class Philosopher : public QActive { private: uint8_t m_num; // number of this philosopher QTimeEvt m_timeEvt; // to timeout thining or eating public: Philosopher::Philosopher() : QActive((QStateHandler)&Philosopher::initial), m_timeEvt(TIMEOUT_SIG) {} protected: static QState initial (Philosopher *me, QEvent const *e); static QState thinking(Philosopher *me, QEvent const *e); static QState hungry (Philosopher *me, QEvent const *e); static QState eating (Philosopher *me, QEvent const *e); };
Definition at line 112 of file qf.h.
| QActive::QActive | ( | QF_ACTIVE_STATE_ | initial | ) | [inline, protected] |
protected constructor
Performs the first step of active object initialization by assigning the initial pseudostate to the currently active state of the state machine.
| void QActive::start | ( | uint8_t | prio, | |
| QEvent const * | qSto[], | |||
| uint32_t | qLen, | |||
| void * | stkSto, | |||
| uint32_t | stkSize, | |||
| QEvent const * | ie = (QEvent *)0 | |||
| ) |
Starts execution of an active object and registers the object with the framework.
The function takes six arguments. prio is the priority of the active object. QF allows you to start up to 63 active objects, each one having a unique priority number between 1 and 63 inclusive, where higher numerical values correspond to higher priority (urgency) of the active object relative to the others. qSto[] and qLen arguments are the storage and size of the event queue used by this active object. stkSto and stkSize are the stack storage and size in bytes. Please note that a per-active object stack is used only when the underlying OS requies it. If the stack is not required, or the underlying OS allocates the stack internally, the stkSto should be NULL and/or stkSize should be 0. ie is an optional initialization event that can be used to pass additional startup data to the active object. (Pass NULL if your active object does not expect the initialization event).
static Philosopher l_philo[N]; // N Philosopher active objects static QEvent const *l_philQueueSto[N][N]; // storage for Philo event queues static int l_philoStk[N][256]; // stacks for the Philosopher active objects main() { . . . for (n = 0; n < N; ++n) { TableEvt ie; // initialization event for the Philosopher HSM ie.philNum = n; l_philo[n].start((uint8_t)(n*10 + 1), // priority l_philoQueueSto[n], Q_DIM(l_philoQueueSto[n]), // queue l_philoStk[n], sizeof(l_philoStk[n]), // uC/OS-II stack &ie); // initialization event } . . . }
Definition at line 85 of file qvanilla.cpp.
References m_prio, Q_REQUIRE, QF_MAX_ACTIVE, and QS_FLUSH.
| void QActive::postFIFO | ( | QEvent const * | e | ) |
Posts an event e directly to the event queue of the acitve object me using the First-In-First-Out (FIFO) policy.
Direct event posting is the simplest asynchronous communication method available in QF. The following example illustrates how the Philosopher active obejct posts directly the HUNGRY event to the Table active object.
extern QActive *AO_Table; QState Philosopher::hungry(Philosopher *me, QEvent const *e) { TableEvt *pe; switch (e->sig) { case Q_ENTRY_SIG: { pe = Q_NEW(TableEvt, HUNGRY_SIG); // dynamically allocate event pe->philNum = me->num_; AO_Table->postFIFO(pe); // post the event directly return Q_HANDLED(); } . . . } return Q_SUPER(&QHsm::top); }
Direct event posting should not be confused with direct event dispatching. In contrast to asynchronous event posting through event queues, direct event dispatching is synchronous. Direct event dispatching occurs when you call QHsm::dispatch(), or QFsm::dispatch() function.
Definition at line 41 of file qa_fifo.cpp.
References QS::aoObj_, Q_ASSERT, QACTIVE_EQUEUE_SIGNAL_, QS_BEGIN_NOLOCK_, QS_END_NOLOCK_, QS_EQC_, QS_OBJ_, QS_QF_ACTIVE_POST_FIFO, QS_SIG_, QS_TIME_, and QS_U8_.
Referenced by QF::tick().
| void QActive::postLIFO | ( | QEvent const * | e | ) |
Posts an event directly to the event queue of the active object me using the Last-In-First-Out (LIFO) policy.
Definition at line 41 of file qa_lifo.cpp.
References QS::aoObj_, Q_ASSERT, QACTIVE_EQUEUE_SIGNAL_, QS_BEGIN_NOLOCK_, QS_END_NOLOCK_, QS_EQC_, QS_OBJ_, QS_QF_ACTIVE_POST_LIFO, QS_SIG_, QS_TIME_, and QS_U8_.
Referenced by recall().
| void QActive::run | ( | void | ) |
Traditional loop-structured thread routine for an active object.
This function is only used when QF is ported to a traditional RTOS/Kernel. QActive::run() is structured as a typical endless loop, which blocks on the event queue get() operation of an active object. When an event becomes available, it's dispatched to the active object's state machine and after this recycled with QF::gc(). The loop might optionally use the QActive::m_running flag to terminate and cause QActive::run() to return which is often the cleanest way to terminate the thread.
Definition at line 35 of file qa_run.cpp.
| QEvent const * QActive::get_ | ( | void | ) |
Get an event from the event queue of an active object.
This function is used internally by a QF port to extract events from the event queue of an active object. This function depends on the event queue implementation and is sometimes implemented in the QF port (qf_port.cpp file). Depending on the underlying OS or kernel, the function might block the calling thread when no events are available.
Definition at line 41 of file qa_get_.cpp.
References QS::aoObj_, QEvent::dynamic_, QACTIVE_EQUEUE_ONEMPTY_, QACTIVE_EQUEUE_WAIT_, QS_BEGIN_NOLOCK_, QS_END_NOLOCK_, QS_EQC_, QS_OBJ_, QS_QF_ACTIVE_GET, QS_QF_ACTIVE_GET_LAST, QS_SIG_, QS_TIME_, QS_U8_, and QEvent::sig.
| void QActive::stop | ( | void | ) | [protected] |
Stops execution of an active object and removes it from the framework's supervision.
The preferred way of calling this function is from within the active object that needs to stop (that's why this function is protected). In other words, an active object should stop itself rather than being stopped by some other entity. This policy works best, because only the active object itself "knows" when it has reached the appropriate state for the shutdown.
Definition at line 101 of file qvanilla.cpp.
References QF::remove_().
| void QActive::subscribe | ( | QSignal | sig | ) | const [protected] |
Subscribes for delivery of signal sig to the active object.
This function is part of the Publish-Subscribe event delivery mechanism available in QF. Subscribing to an event means that the framework will start posting all published events with a given signal sig to the event queue of the active object.
The following example shows how the Table active object subscribes to three signals in the initial transition:
QState Table::initial(Table *me, QEvent const *) { uint8_t n; me->subscribe(HUNGRY_SIG); // subscribe to HUNGRY me->subscribe(DONE_SIG); // subscribe to DONE me->subscribe(TERMINATE_SIG); // subscribe to TERMINATE for (n = 0; n < N; ++n) { me->fork_[n] = FREE; me->isHungry_[n] = 0; } return Q_TRAN(&Table::serving); }
Definition at line 38 of file qa_sub.cpp.
References QF::active_, QS::aoObj_, QSubscrList::m_bits, Q_REQUIRE, Q_ROM_BYTE, Q_USER_SIG, QF_div8Lkup, QF_MAX_ACTIVE, QF_maxSignal_, QF_pwr2Lkup, QF_subscrList_, QS_BEGIN_NOLOCK_, QS_END_NOLOCK_, QS_OBJ_, QS_QF_ACTIVE_SUBSCRIBE, QS_SIG_, and QS_TIME_.
| void QActive::unsubscribe | ( | QSignal | sig | ) | const [protected] |
Un-subscribes from the delivery of signal sig to the active object.
This function is part of the Publish-Subscribe event delivery mechanism available in QF. Un-subscribing from an event means that the framework will stop posting published events with a given signal sig to the event queue of the active object.
Un-subscribing from a signal that has never been subscribed in the first place is considered an error and QF will rise an assertion.
Definition at line 38 of file qa_usub.cpp.
References QF::active_, QS::aoObj_, QSubscrList::m_bits, Q_REQUIRE, Q_ROM_BYTE, Q_USER_SIG, QF_div8Lkup, QF_invPwr2Lkup, QF_MAX_ACTIVE, QF_maxSignal_, QF_subscrList_, QS_BEGIN_NOLOCK_, QS_END_NOLOCK_, QS_OBJ_, QS_QF_ACTIVE_UNSUBSCRIBE, QS_SIG_, and QS_TIME_.
Defer an event to a given separate event queue.
This function is part of the event deferral support. An active object uses this function to defer an event e to the QF-supported native event queue eq. QF correctly accounts for another outstanding reference to the event and will not recycle the event at the end of the RTC step. Later, the active object might recall one event at a time from the event queue.
An active object can use multiple event queues to defer events of different kinds.
Definition at line 39 of file qa_defer.cpp.
Recall a deferred event from a given event queue.
This function is part of the event deferral support. An active object uses this function to recall a deferred event from a given QF event queue. Recalling an event means that it is removed from the deferred event queue eq and posted (LIFO) to the event queue of the active object.
QActive::recall() returns the pointer to the recalled event to the caller. The function returns NULL if no event has been recalled.
An active object can use multiple event queues to defer events of different kinds.
Definition at line 43 of file qa_defer.cpp.
References QEvent::dynamic_, QEQueue::get(), postLIFO(), and Q_ASSERT.
| void QActive::unsubscribeAll | ( | void | ) | const |
Un-subscribes from the delivery of all signals to the active object.
This function is part of the Publish-Subscribe event delivery mechanism available in QF. Un-subscribing from all events means that the framework will stop posting any published events to the event queue of the active object.
Definition at line 38 of file qa_usuba.cpp.
References QF::active_, QS::aoObj_, QSubscrList::m_bits, Q_REQUIRE, Q_ROM_BYTE, Q_USER_SIG, QF_div8Lkup, QF_invPwr2Lkup, QF_MAX_ACTIVE, QF_maxSignal_, QF_pwr2Lkup, QF_subscrList_, QS_BEGIN_NOLOCK_, QS_END_NOLOCK_, QS_OBJ_, QS_QF_ACTIVE_UNSUBSCRIBE, QS_SIG_, and QS_TIME_.
QF priority associated with the active object.
Definition at line 149 of file qf.h.
Referenced by start().
The Boolean loop variable determining if the thread routine of the active object is running.
This flag is only used with the traditional loop-structured thread routines. Clearing this flag breaks out of the thread loop, which is often the cleanest way to terminate the thread. The following example illustrates the thread routine for Win32:
void QActive::run(void) { do { QEvent const *e; QACTIVE_GET_(this, e); // wait for event dispatch(e); // dispatch event to the active object's state machine QF::gc(e); // check if the event is garbage, and collect it if so } while (m_running); unsubscribeAll(); // unsubscribe from all signals QF::remove_(this); // remove this object from any subscriptions }
Definition at line 159 of file qf.h.
Referenced by run().
1.5.4