Specialized time event for components. The time evnet can be owned by a component and can dispatch itself to the component.
The constructor to initialize a Component Time Event.
When creating a time event, you must commit it to a specific active object 'act', event signal 'sig', and tick rate 'tickRate'. You cannot change these attributes later.
: QTimeEvt(act, sig, tickRate)
m_comp = comp;
m_comp->dispatch(this);
Embedded component state machine objects
: QActive(Q_STATE_CAST(&Table::initial))
for (uint8_t n = 0U; n < N_PHILO; ++n) {
m_fork[n] = FREE;
m_isHungry[n] = false;
}
(void)e; // suppress the compiler warning about unused parameter
QS_OBJ_DICTIONARY(&l_table);
QS_FUN_DICTIONARY(&Table::initial);
QS_FUN_DICTIONARY(&Table::active);
QS_FUN_DICTIONARY(&Table::serving);
QS_FUN_DICTIONARY(&Table::paused);
QS_SIG_DICTIONARY(DONE_SIG, (void *)0); // global signals
QS_SIG_DICTIONARY(EAT_SIG, (void *)0);
QS_SIG_DICTIONARY(PAUSE_SIG, (void *)0);
QS_SIG_DICTIONARY(SERVE_SIG, (void *)0);
QS_SIG_DICTIONARY(TEST_SIG, (void *)0);
QS_SIG_DICTIONARY(TIMEOUT_SIG, me); // signal just for Table
QS_SIG_DICTIONARY(HUNGRY_SIG, me); // signal just for Table
me->subscribe(PAUSE_SIG);
me->subscribe(SERVE_SIG);
me->subscribe(TEST_SIG);
for (uint8_t n = 0U; n < N_PHILO; ++n) {
me->m_philo[n].init(); // top-most initial tran.
me->m_fork[n] = FREE;
me->m_isHungry[n] = false;
BSP::displayPhilStat(n, THINKING);
}
Q_EVT_CAST(CompTimeEvt)->dispatchToComp();
Q_ERROR();
for (uint8_t n = 0U; n < N_PHILO; ++n) { // give permissions to eat...
if (me->m_isHungry[n]
&& (me->m_fork[LEFT(n)] == FREE)
&& (me->m_fork[n] == FREE))
{
me->m_fork[LEFT(n)] = USED;
me->m_fork[n] = USED;
// synchronoulsy dispatch EAT event to the Philo component
TableEvt evt;
evt.sig = EAT_SIG;
evt.philo = &me->m_philo[n];
me->m_philo[n].dispatch(&evt);
me->m_isHungry[n] = false;
BSP::displayPhilStat(n, EATING);
}
}
// find the index of the Philo from the event
uint8_t n = (Q_EVT_CAST(TableEvt)->philo - &me->m_philo[0]);
// philo ID must be in range and he must be not hungry
Q_ASSERT((n < N_PHILO) && (!me->m_isHungry[n]));
BSP::displayPhilStat(n, HUNGRY);
uint8_t m = LEFT(n);
(me->m_fork[m] == FREE) && (me->m_fork[n] == FREE)
me->m_fork[m] = USED;
me->m_fork[n] = USED;
// synchronoulsy dispatch EAT event to the Philo component
TableEvt evt;
evt.sig = EAT_SIG;
evt.philo = &me->m_philo[n];
me->m_philo[n].dispatch(&evt);
BSP::displayPhilStat(n, EATING);
else
me->m_isHungry[n] = true;
// find the index of the Philo from the event
uint8_t n = (Q_EVT_CAST(TableEvt)->philo - &me->m_philo[0]);
// philo ID must be in range and he must be not hungry
Q_ASSERT((n < N_PHILO) && (!me->m_isHungry[n]));
BSP::displayPhilStat(n, THINKING);
uint8_t m = LEFT(n);
// both forks of Phil[n] must be used
Q_ASSERT((me->m_fork[n] == USED) && (me->m_fork[m] == USED));
me->m_fork[m] = FREE;
me->m_fork[n] = FREE;
m = RIGHT(n); // check the right neighbor
if (me->m_isHungry[m] && (me->m_fork[m] == FREE)) {
me->m_fork[n] = USED;
me->m_fork[m] = USED;
me->m_isHungry[m] = false;
// synchronoulsy dispatch EAT event to the Philo component
TableEvt evt;
evt.sig = EAT_SIG;
evt.philo = &me->m_philo[m];
me->m_philo[m].dispatch(&evt);
BSP::displayPhilStat(m, EATING);
}
m = LEFT(n); // check the left neighbor
n = LEFT(m); // left fork of the left neighbor
if (me->m_isHungry[m] && (me->m_fork[n] == FREE)) {
me->m_fork[m] = USED;
me->m_fork[n] = USED;
me->m_isHungry[m] = false;
// synchronoulsy dispatch EAT event to the Philo component
TableEvt evt;
evt.sig = EAT_SIG;
evt.philo = &me->m_philo[m];
me->m_philo[m].dispatch(&evt);
BSP::displayPhilStat(m, EATING);
}
Q_ERROR();
BSP::displayPaused(1U);
BSP::displayPaused(0U);
// find the index of the Philo from the event
uint8_t n = (Q_EVT_CAST(TableEvt)->philo - &me->m_philo[0]);
// philo ID must be in range and he must be not hungry
Q_ASSERT((n < N_PHILO) && (!me->m_isHungry[n]));
me->m_isHungry[n] = true;
BSP::displayPhilStat(n, HUNGRY);
// find the index of the Philo from the event
uint8_t n = (Q_EVT_CAST(TableEvt)->philo - &me->m_philo[0]);
// philo ID must be in range and he must be not hungry
Q_ASSERT((n < N_PHILO) && (!me->m_isHungry[n]));
BSP::displayPhilStat(n, THINKING);
uint8_t m = LEFT(n);
// both forks of Phil[n] must be used
Q_ASSERT((me->m_fork[n] == USED) && (me->m_fork[m] == USED));
me->m_fork[m] = FREE;
me->m_fork[n] = FREE;
#ifndef dpp_h
#define dpp_h
namespace DPP {
enum DPPSignals {
EAT_SIG = QP::Q_USER_SIG, // published by Table to let a philosopher eat
DONE_SIG, // published by Philosopher when done eating
PAUSE_SIG, // published by BSP to pause the application
SERVE_SIG, // published by BSP to serve re-start serving forks
TEST_SIG, // published by BSP to test the application
MAX_PUB_SIG, // the last published signal
HUNGRY_SIG, // posted direclty to Table from hungry Philo
TIMEOUT_SIG, // used by the component time events
MAX_SIG // the last signal
};
class Philo; // forward declaration
} // namespace DPP
enum {
N_PHILO = 5 // number of Philos
};
$declare(Cont::CompTimeEvt)
$declare(Cont::AO_Table)
$declare(Comp::Philo)
$declare(Cont::TableEvt)
#endif // dpp_h
#include "qpcpp.h"
#include "dpp.h"
#include "bsp.h"
Q_DEFINE_THIS_FILE
// Active object class -------------------------------------------------------
$declare(Cont::Table)
namespace DPP {
// helper function to provide the RIGHT neighbour of a Philo[n]
inline uint8_t RIGHT(uint8_t const n) {
return static_cast<uint8_t>((n + (N_PHILO - 1U)) % N_PHILO);
}
// helper function to provide the LEFT neighbour of a Philo[n]
inline uint8_t LEFT(uint8_t const n) {
return static_cast<uint8_t>((n + 1U) % N_PHILO);
}
static uint8_t const FREE = static_cast<uint8_t>(0);
static uint8_t const USED = static_cast<uint8_t>(1);
static char_t const * const THINKING = &"thinking"[0];
static char_t const * const HUNGRY = &"hungry "[0];
static char_t const * const EATING = &"eating "[0];
// Local objects -------------------------------------------------------------
static Table l_table; // the single instance of the Table active object
// Global-scope objects ------------------------------------------------------
QP::QActive * const AO_Table = &l_table; // "opaque" AO pointer
} // namespace DPP
//............................................................................
$define(Cont::CompTimeEvt)
$define(Cont::Table)