Dining Philosopher Problem example
NOTE: Requries QP5.
static uint8_t registered = (uint8_t)0; /* starts off with 0, per C-standard */
(void)e; /* suppress the compiler warning about unused parameter */
if (registered == (uint8_t)0) {
registered = (uint8_t)1;
QS_OBJ_DICTIONARY(&l_philo[0]);
QS_OBJ_DICTIONARY(&l_philo[0].timeEvt);
QS_OBJ_DICTIONARY(&l_philo[1]);
QS_OBJ_DICTIONARY(&l_philo[1].timeEvt);
QS_OBJ_DICTIONARY(&l_philo[2]);
QS_OBJ_DICTIONARY(&l_philo[2].timeEvt);
QS_OBJ_DICTIONARY(&l_philo[3]);
QS_OBJ_DICTIONARY(&l_philo[3].timeEvt);
QS_OBJ_DICTIONARY(&l_philo[4]);
QS_OBJ_DICTIONARY(&l_philo[4].timeEvt);
QS_FUN_DICTIONARY(&Philo_initial);
QS_FUN_DICTIONARY(&Philo_thinking);
QS_FUN_DICTIONARY(&Philo_hungry);
QS_FUN_DICTIONARY(&Philo_eating);
}
QS_SIG_DICTIONARY(HUNGRY_SIG, me); /* signal for each Philos */
QS_SIG_DICTIONARY(TIMEOUT_SIG, me); /* signal for each Philos */
QActive_subscribe(&me->super, EAT_SIG);
QActive_subscribe(&me->super, TEST_SIG);
QTimeEvt_armX(&me->timeEvt, THINK_TIME, 0U);
QTimeEvt_disarm(&me->timeEvt);
/* EAT or DONE must be for other Philos than this one */
Q_ASSERT(Q_EVT_CAST(TableEvt)->philoNum != PHILO_ID(me));
TableEvt *pe = Q_NEW(TableEvt, HUNGRY_SIG);
pe->philoNum = PHILO_ID(me);
QACTIVE_POST(AO_Table, &pe->super, me);
Q_EVT_CAST(TableEvt)->philoNum == PHILO_ID(me)
/* DONE must be for other Philos than this one */
Q_ASSERT(Q_EVT_CAST(TableEvt)->philoNum != PHILO_ID(me));
QTimeEvt_armX(&me->timeEvt, EAT_TIME, 0U);
TableEvt *pe = Q_NEW(TableEvt, DONE_SIG);
pe->philoNum = PHILO_ID(me);
QF_PUBLISH(&pe->super, me);
/* EAT or DONE must be for other Philos than this one */
Q_ASSERT(Q_EVT_CAST(TableEvt)->philoNum != PHILO_ID(me));
uint8_t n;
(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_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(HUNGRY_SIG, me); /* signal just for Table */
QActive_subscribe(&me->super, DONE_SIG);
QActive_subscribe(&me->super, PAUSE_SIG);
QActive_subscribe(&me->super, SERVE_SIG);
QActive_subscribe(&me->super, TEST_SIG);
for (n = 0U; n < N_PHILO; ++n) {
me->fork[n] = FREE;
me->isHungry[n] = 0U;
BSP_displayPhilStat(n, "thinking");
}
Q_ERROR();
uint8_t n;
for (n = 0U; n < N_PHILO; ++n) { /* give permissions to eat... */
if ((me->isHungry[n] != 0U)
&& (me->fork[LEFT(n)] == FREE)
&& (me->fork[n] == FREE))
{
TableEvt *te;
me->fork[LEFT(n)] = USED;
me->fork[n] = USED;
te = Q_NEW(TableEvt, EAT_SIG);
te->philoNum = n;
QF_PUBLISH(&te->super, me);
me->isHungry[n] = 0U;
BSP_displayPhilStat(n, "eating ");
}
}
uint8_t n, m;
n = Q_EVT_CAST(TableEvt)->philoNum;
/* phil ID must be in range and he must be not hungry */
Q_ASSERT((n < N_PHILO) && (me->isHungry[n] == 0U));
BSP_displayPhilStat(n, "hungry ");
m = LEFT(n);
(me->fork[m] == FREE) && (me->fork[n] == FREE)
TableEvt *pe;
me->fork[m] = USED;
me->fork[n] = USED;
pe = Q_NEW(TableEvt, EAT_SIG);
pe->philoNum = n;
QF_PUBLISH(&pe->super, me);
BSP_displayPhilStat(n, "eating ");
else
me->isHungry[n] = 1U;
uint8_t n, m;
TableEvt *pe;
n = Q_EVT_CAST(TableEvt)->philoNum;
/* phil ID must be in range and he must be not hungry */
Q_ASSERT((n < N_PHILO) && (me->isHungry[n] == 0U));
BSP_displayPhilStat(n, "thinking");
m = LEFT(n);
/* both forks of Phil[n] must be used */
Q_ASSERT((me->fork[n] == USED) && (me->fork[m] == USED));
me->fork[m] = FREE;
me->fork[n] = FREE;
m = RIGHT(n); /* check the right neighbor */
if ((me->isHungry[m] != 0U) && (me->fork[m] == FREE)) {
me->fork[n] = USED;
me->fork[m] = USED;
me->isHungry[m] = 0U;
pe = Q_NEW(TableEvt, EAT_SIG);
pe->philoNum = m;
QF_PUBLISH(&pe->super, me);
BSP_displayPhilStat(m, "eating ");
}
m = LEFT(n); /* check the left neighbor */
n = LEFT(m); /* left fork of the left neighbor */
if ((me->isHungry[m] != 0U) && (me->fork[n] == FREE)) {
me->fork[m] = USED;
me->fork[n] = USED;
me->isHungry[m] = 0U;
pe = Q_NEW(TableEvt, EAT_SIG);
pe->philoNum = m;
QF_PUBLISH(&pe->super, me);
BSP_displayPhilStat(m, "eating ");
}
Q_ERROR();
BSP_displayPaused(1U);
BSP_displayPaused(0U);
uint8_t n = Q_EVT_CAST(TableEvt)->philoNum;
/* philo ID must be in range and he must be not hungry */
Q_ASSERT((n < N_PHILO) && (me->isHungry[n] == 0U));
me->isHungry[n] = 1U;
BSP_displayPhilStat(n, "hungry ");
uint8_t n, m;
n = Q_EVT_CAST(TableEvt)->philoNum;
/* phil ID must be in range and he must be not hungry */
Q_ASSERT((n < N_PHILO) && (me->isHungry[n] == 0U));
BSP_displayPhilStat(n, "thinking");
m = LEFT(n);
/* both forks of Phil[n] must be used */
Q_ASSERT((me->fork[n] == USED) && (me->fork[m] == USED));
me->fork[m] = FREE;
me->fork[n] = FREE;
uint8_t n;
Philo *me;
for (n = 0U; n < N_PHILO; ++n) {
me = &l_philo[n];
QActive_ctor(&me->super, Q_STATE_CAST(&Philo_initial));
QTimeEvt_ctorX(&me->timeEvt, &me->super, TIMEOUT_SIG, 0U);
}
uint8_t n;
Table *me = &l_table;
QActive_ctor(&me->super, Q_STATE_CAST(&Table_initial));
for (n = 0U; n < N_PHILO; ++n) {
me->fork[n] = FREE;
me->isHungry[n] = 0U;
}
#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 */
PAUSE_SIG, /* published by BSP to pause serving forks */
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 Philosophers for time events */
MAX_SIG /* the last signal */
};
$declare(Events::TableEvt)
/* number of philosophers */
#define N_PHILO ((uint8_t)5)
$declare(AOs::Philo_ctor)
$declare(AOs::AO_Philo[N_PHILO])
$declare(AOs::Table_ctor)
$declare(AOs::AO_Table)
#ifdef qxk_h
void Test1_ctor(void);
extern QXThread * const XT_Test1;
void Test2_ctor(void);
extern QXThread * const XT_Test2;
#endif /* qxk_h */
#endif /* dpp_h */
#include "qpc.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 \
(QTimeEvtCtr)((BSP_random() % BSP_TICKS_PER_SEC) + (BSP_TICKS_PER_SEC/2U))
#define EAT_TIME \
(QTimeEvtCtr)((BSP_random() % BSP_TICKS_PER_SEC) + BSP_TICKS_PER_SEC)
/* helper macro to provide the ID of Philo "me_" */
#define PHILO_ID(me_) ((uint8_t)((me_) - l_philo))
/* Global objects ----------------------------------------------------------*/
QMActive * const AO_Philo[N_PHILO] = { /* "opaque" pointers to Philo AO */
&l_philo[0].super,
&l_philo[1].super,
&l_philo[2].super,
&l_philo[3].super,
&l_philo[4].super
};
/* Philo definition --------------------------------------------------------*/
$define(AOs::Philo_ctor)
$define(AOs::Philo)
#include "qpc.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 - 1U)) % N_PHILO))
#define LEFT(n_) ((uint8_t)(((n_) + 1U) % N_PHILO))
#define FREE ((uint8_t)0)
#define USED ((uint8_t)1)
/* Local objects -----------------------------------------------------------*/
static Table l_table; /* the single instance of the Table active object */
/* Global-scope objects ----------------------------------------------------*/
QMActive * const AO_Table = &l_table.super; /* "opaque" AO pointer */
/*..........................................................................*/
$define(AOs::Table_ctor)
$define(AOs::Table)