Dining Philosopher Problem example
static uint8_t registered; // starts off with 0, per C-standard
(void)e; // suppress the compiler warning about unused parameter
if (!registered) {
QS_OBJ_DICTIONARY(&l_philo[0]);
QS_OBJ_DICTIONARY(&l_philo[0].m_timeEvt);
QS_OBJ_DICTIONARY(&l_philo[1]);
QS_OBJ_DICTIONARY(&l_philo[1].m_timeEvt);
QS_OBJ_DICTIONARY(&l_philo[2]);
QS_OBJ_DICTIONARY(&l_philo[2].m_timeEvt);
QS_OBJ_DICTIONARY(&l_philo[3]);
QS_OBJ_DICTIONARY(&l_philo[3].m_timeEvt);
QS_OBJ_DICTIONARY(&l_philo[4]);
QS_OBJ_DICTIONARY(&l_philo[4].m_timeEvt);
QS_FUN_DICTIONARY(&Philo::initial);
QS_FUN_DICTIONARY(&Philo::thinking);
QS_FUN_DICTIONARY(&Philo::hungry);
QS_FUN_DICTIONARY(&Philo::eating);
registered = (uint8_t)1;
}
QS_SIG_DICTIONARY(HUNGRY_SIG, me); // signal for each Philos
QS_SIG_DICTIONARY(TIMEOUT_SIG, me); // signal for each Philos
//me->subscribe(EAT_SIG);
me->m_timeEvt.postIn(me, THINK_TIME);
BSP_busyDelay();
TableEvt *pe = Q_NEW(TableEvt, HUNGRY_SIG);
pe->philoNum = PHILO_ID(me);
AO_Table->POST(pe, me);
BSP_busyDelay();
me->m_timeEvt.postIn(me, EAT_TIME);
TableEvt *pe = Q_NEW(TableEvt, DONE_SIG);
pe->philoNum = PHILO_ID(me);
AO_Table->POST(pe, me);
BSP_busyDelay();
for (uint8_t n = 0; n < N_PHILO; ++n) {
m_fork[n] = FREE;
m_isHungry[n] = 0;
}
(void)e; // suppress the compiler warning about unused parameter
QS_OBJ_DICTIONARY(&l_table);
QS_FUN_DICTIONARY(&QHsm::top);
QS_FUN_DICTIONARY(&Table::initial);
QS_FUN_DICTIONARY(&Table::serving);
QS_SIG_DICTIONARY(DONE_SIG, 0); // global signals
QS_SIG_DICTIONARY(EAT_SIG, 0);
QS_SIG_DICTIONARY(TERMINATE_SIG, 0);
QS_SIG_DICTIONARY(HUNGRY_SIG, me); // signal just for Table
//me->subscribe(DONE_SIG);
//me->subscribe(TERMINATE_SIG);
BSP_busyDelay();
uint8_t n = ((TableEvt const *)e)->philoNum;
// phil ID must be in range and he must be not hungry
Q_ASSERT((n < N_PHILO) && (!me->m_isHungry[n]));
BSP_displyPhilStat(n, "hungry ");
uint8_t m = LEFT(n);
me->m_fork[m] = me->m_fork[n] = USED;
TableEvt *pe = Q_NEW(TableEvt, EAT_SIG);
pe->philoNum = n;
AO_Philo[n]->POST(pe, me);
BSP_displyPhilStat(n, "eating ");
me->m_isHungry[n] = 1;
uint8_t n, m;
TableEvt *pe;
BSP_busyDelay();
n = ((TableEvt const *)e)->philoNum;
// phil ID must be in range and he must be not hungry
Q_ASSERT((n < N_PHILO) && (!me->m_isHungry[n]));
BSP_displyPhilStat(n, "thinking");
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] = 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] = me->m_fork[m] = USED;
me->m_isHungry[m] = 0;
pe = Q_NEW(TableEvt, EAT_SIG);
pe->philoNum = m;
AO_Philo[m]->POST(pe, me);
BSP_displyPhilStat(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] = me->m_fork[n] = USED;
me->m_isHungry[m] = 0;
pe = Q_NEW(TableEvt, EAT_SIG);
pe->philoNum = m;
AO_Philo[m]->POST(pe, me);
BSP_displyPhilStat(m, "eating ");
}
#ifndef dpp_h
#define dpp_h
enum DPPSignals {
EAT_SIG = Q_USER_SIG, // published by Table to let a philosopher eat
DONE_SIG, // published by Philosopher when done eating
TERMINATE_SIG, // published by BSP to terminate the application
MAX_PUB_SIG, // the last published signal
HUNGRY_SIG, // posted direclty to Table from hungry Philosopher
MAX_SIG // the last signal
};
$declare(Events::TableEvt)
enum { N_PHILO = 5 }; // number of philosophers
$declare(AOs::AO_Philo[N_PHILO])
$declare(AOs::AO_Table)
#endif // dpp_h
#include "qp_port.h"
#include "dpp.h"
#include "bsp.h"
//Q_DEFINE_THIS_FILE
/* Active object class -----------------------------------------------------*/
$declare(AOs::Philo)
/* Local objects -----------------------------------------------------------*/
static Philo l_philo[N_PHILO]; /* storage for all Philos */
#define THINK_TIME ((BSP_TICKS_PER_SEC) / 2)
#define EAT_TIME ((BSP_TICKS_PER_SEC) / 5)
/* helper macro to provide the ID of Philo "me_" */
#define PHILO_ID(me_) ((uint8_t)((me_) - l_philo))
enum InternalSignals { /* internal signals */
TIMEOUT_SIG = MAX_SIG
};
/* Global objects ----------------------------------------------------------*/
QActive * const AO_Philo[N_PHILO] = { /* "opaque" pointers to Philo AO */
(QActive *)&l_philo[0],
(QActive *)&l_philo[1],
(QActive *)&l_philo[2],
(QActive *)&l_philo[3],
(QActive *)&l_philo[4]
};
/* Philo definition --------------------------------------------------------*/
$define(AOs::Philo)
#include "qp_port.h"
#include "dpp.h"
#include "bsp.h"
Q_DEFINE_THIS_FILE
/* Active object class -----------------------------------------------------*/
$declare(AOs::Table)
#define RIGHT(n_) ((uint8_t)(((n_) + (N_PHILO - 1)) % N_PHILO))
#define LEFT(n_) ((uint8_t)(((n_) + 1) % N_PHILO))
enum ForkState { FREE, USED };
/* Local objects -----------------------------------------------------------*/
static Table l_table; /* the single instance of the Table active object */
/* Global-scope objects ----------------------------------------------------*/
QActive * const AO_Table = (QActive *)&l_table; /* "opaque" AO pointer */
/*..........................................................................*/
$define(AOs::Table)