Dining Philosopher Problem example = { /* "opaque" pointers to Philo AO */ &Philo_inst[0].super, &Philo_inst[1].super, &Philo_inst[2].super, &Philo_inst[3].super, &Philo_inst[4].super }; = &Table_inst.super; /* "opaque" pointer to Table AO */ uint8_t n; for (n = 0U; n < N_PHILO; ++n) { Philo_ctor(&Philo_inst[n]); } Table_ctor(&Table_inst); The array of static insts of the Philo class (Singleton pattern) constructor QActive_ctor(&me->super, Q_STATE_CAST(&Philo_initial)); QTimeEvt_ctorX(&me->timeEvt, &me->super, TIMEOUT_SIG, 0U); static uint8_t registered = (uint8_t)0; /* starts off with 0, per C-standard */ (void)par; /* unused parameter */ if (registered == (uint8_t)0) { registered = (uint8_t)1; QS_OBJ_DICTIONARY(&Philo_inst[0]); QS_OBJ_DICTIONARY(&Philo_inst[0].timeEvt); QS_OBJ_DICTIONARY(&Philo_inst[1]); QS_OBJ_DICTIONARY(&Philo_inst[1].timeEvt); QS_OBJ_DICTIONARY(&Philo_inst[2]); QS_OBJ_DICTIONARY(&Philo_inst[2].timeEvt); QS_OBJ_DICTIONARY(&Philo_inst[3]); QS_OBJ_DICTIONARY(&Philo_inst[3].timeEvt); QS_OBJ_DICTIONARY(&Philo_inst[4]); QS_OBJ_DICTIONARY(&Philo_inst[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->super); /* EAT or DONE must be for other Philos than this one */ Q_ASSERT(Q_EVT_CAST(TableEvt)->philoNum != PHILO_ID(me)); The only static inst of the Table class (Singleton pattern) constructor uint8_t n; QActive_ctor(&me->super, Q_STATE_CAST(&Table_initial)); for (n = 0U; n < N_PHILO; ++n) { me->fork[n] = FREE; me->isHungry[n] = 0U; } uint8_t n; (void)par; /* unused parameter */ QS_OBJ_DICTIONARY(&Table_inst); 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->super); 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->super); 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->super); 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->super); 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; #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 */ }; /* number of philosophers */ #define N_PHILO ((uint8_t)5) $declare${Shared} #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} #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_) - &Philo_inst[0])) $define${Shared::AO_Philo[N_PHILO]} $define${Shared::Philo_ctor_call} $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) $define${Shared::AO_Table} $define${Shared::Table_ctor_call} $define${AOs::Table}