QP/C++
Public Member Functions | Protected Member Functions | Friends
QActive Class Reference

Base class for derivation of application-level active object classes. More...

#include <qf.h>

List of all members.

Public Member Functions

void start (uint8_t const prio, QEvt const *qSto[], uint32_t const qLen, void *const stkSto, uint32_t const stkSize, QEvt const *const ie=static_cast< QEvt * >(0))
 Starts execution of an active object and registers the object with the framework.
void postFIFO (QEvt const *const e, void const *const sender)
 Posts an event e directly to the event queue of the active object me using the First-In-First-Out (FIFO) policy.
void unsubscribeAll (void) const
 Un-subscribes from the delivery of all signals to the active object.

Protected Member Functions

 QActive (QF_ACTIVE_STATE_ const initial)
 protected constructor
void postLIFO (QEvt const *const e)
 Posts an event directly to the event queue of the active object me using the Last-In-First-Out (LIFO) policy.
void stop (void)
 Stops execution of an active object and removes it from the framework's supervision.
void subscribe (enum_t const sig) const
 Subscribes for delivery of signal sig to the active object.
void unsubscribe (enum_t const sig) const
 Un-subscribes from the delivery of signal sig to the active object.
void defer (QEQueue *const eq, QEvt const *const e) const
 Defer an event to a given separate event queue.
bool recall (QEQueue *const eq)
 Recall a deferred event from a given event queue.

Friends

class QF
class QTimeEvt

Detailed Description

Base class for derivation of application-level active object classes.

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.

Note:
QActive is not intended to be instantiated directly, but rather serves as the base class for derivation of active objects in the application code.

The following example illustrates how to derive an active object from QActive.

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);
};
See also:
#QF_ACTIVE_SUPER_ defines the base class for QActive

Definition at line 158 of file qf.h.


Constructor & Destructor Documentation

QActive::QActive ( QF_ACTIVE_STATE_ const  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.

Note:
The constructor is protected to prevent direct instantiation of QActive objects. This class is intended only for derivation (abstract class).

Definition at line 283 of file qf.h.


Member Function Documentation

QP_BEGIN_ void QActive::defer ( QEQueue *const  eq,
QEvt const *const  e 
) const [protected]

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.

See also:
QActive::recall(), QEQueue

Definition at line 48 of file qa_defer.cpp.

References postFIFO().

QP_BEGIN_ void QActive::postFIFO ( QEvt const *const  e,
void const *const  sender 
)

Posts an event e directly to the event queue of the active 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 object 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);
}
Note:
The producer of the event (Philosopher in this case) must only "know" the recipient (Table) by a generic (QActive *QDPP_table) pointer, but the specific definition of the Table class is not required.
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 53 of file qa_fifo.cpp.

References QS::aoObj_, Q_ASSERT, QACTIVE_EQUEUE_SIGNAL_, QF_EVT_POOL_ID_(), QF_EVT_REF_CTR_(), QF_EVT_REF_CTR_INC_(), QF_PTR_AT_, QS_BEGIN_NOCRIT_, QS_END_NOCRIT_, QS_EQC_, QS_OBJ_, QS_QF_ACTIVE_POST_FIFO, QS_TIME_, QS_U8_, and u8_0.

Referenced by defer().

QP_BEGIN_ void QActive::postLIFO ( QEvt const *const  e) [protected]

Posts an event directly to the event queue of the active object me using the Last-In-First-Out (LIFO) policy.

Note:
The LIFO policy should be used only for self-posting and with great caution because it alters order of events in the queue.
See also:
QActive::postFIFO()

Definition at line 50 of file qa_lifo.cpp.

References QS::aoObj_, Q_ASSERT, QACTIVE_EQUEUE_SIGNAL_, QEQueueCtr, QF_EVT_POOL_ID_(), QF_EVT_REF_CTR_(), QF_EVT_REF_CTR_INC_(), QF_PTR_AT_, QS_BEGIN_NOCRIT_, QS_END_NOCRIT_, QS_EQC_, QS_OBJ_, QS_QF_ACTIVE_POST_LIFO, QS_TIME_, QS_U8_, and u8_0.

Referenced by recall().

bool QActive::recall ( QEQueue *const  eq) [protected]

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 true if an event has been recalled. Otherwise the function returns false.

An active object can use multiple event queues to defer events of different kinds.

See also:
QActive::defer(), QEQueue, QActive::postLIFO()

Definition at line 52 of file qa_defer.cpp.

References QEQueue::get(), postLIFO(), Q_ASSERT, QF_EVT_POOL_ID_(), QF_EVT_REF_CTR_(), QF_EVT_REF_CTR_DEC_(), u8_0, and u8_1.

void QActive::start ( uint8_t const  prio,
QEvt const *  qSto[],
uint32_t const  qLen,
void *const  stkSto,
uint32_t const  stkSize,
QEvt const *const  ie = static_cast<QEvt *>(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).

Note:
This function is strongly OS-dependent and must be defined in the QF port to a particular platform.

The following example shows starting of the Philosopher object when a per-task stack is required:

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 93 of file qvanilla.cpp.

References Q_REQUIRE, QF_MAX_ACTIVE, QS_FLUSH, and u8_0.

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.

Note:
This function is strongly OS-dependent and should be defined in the QF port to a particular platform. This function is optional in embedded systems where active objects never need to be stopped.

Definition at line 109 of file qvanilla.cpp.

References QF::remove_().

QP_BEGIN_ void QActive::subscribe ( enum_t const  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);
}
See also:
QF::publish(), QActive::unsubscribe(), and QActive::unsubscribeAll()

Definition at line 47 of file qa_sub.cpp.

References QF::active_, QS::aoObj_, Q_REQUIRE, Q_USER_SIG, QF_div8Lkup, QF_MAX_ACTIVE, QF_maxSignal_, QF_PTR_AT_, QF_pwr2Lkup, QF_subscrList_, QS_BEGIN_NOCRIT_, QS_END_NOCRIT_, QS_OBJ_, QS_QF_ACTIVE_SUBSCRIBE, QS_TIME_, and u8_0.

QP_BEGIN_ void QActive::unsubscribe ( enum_t const  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.

Note:
Due to the latency of event queues, an active object should NOT assume that a given signal sig will never be dispatched to the state machine of the active object after un-subscribing from that signal. The event might be already in the queue, or just about to be posted and the un-subscribe operation will not flush such events.
Un-subscribing from a signal that has never been subscribed in the first place is considered an error and QF will rise an assertion.
See also:
QF::publish(), QActive::subscribe(), and QActive::unsubscribeAll()

Definition at line 47 of file qa_usub.cpp.

References QF::active_, QS::aoObj_, Q_REQUIRE, Q_USER_SIG, QF_div8Lkup, QF_invPwr2Lkup, QF_MAX_ACTIVE, QF_maxSignal_, QF_PTR_AT_, QF_subscrList_, QS_BEGIN_NOCRIT_, QS_END_NOCRIT_, QS_OBJ_, QS_QF_ACTIVE_UNSUBSCRIBE, QS_TIME_, and u8_0.

QP_BEGIN_ 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.

Note:
Due to the latency of event queues, an active object should NOT assume that no events will ever be dispatched to the state machine of the active object after un-subscribing from all events. The events might be already in the queue, or just about to be posted and the un-subscribe operation will not flush such events. Also, the alternative event-delivery mechanisms, such as direct event posting or time events, can be still delivered to the event queue of the active object.
See also:
QF::publish(), QActive::subscribe(), and QActive::unsubscribe()

Definition at line 47 of file qa_usuba.cpp.

References QF::active_, QS::aoObj_, Q_REQUIRE, Q_USER_SIG, QF_div8Lkup, QF_invPwr2Lkup, QF_MAX_ACTIVE, QF_maxSignal_, QF_PTR_AT_, QF_pwr2Lkup, QF_subscrList_, QS_BEGIN_NOCRIT_, QS_END_NOCRIT_, QS_OBJ_, QS_QF_ACTIVE_UNSUBSCRIBE, QS_TIME_, and u8_0.


The documentation for this class was generated from the following files: