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); ((TableEvt const *)e)->philoNum == PHILO_ID(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_displayPhilStat(n, "hungry "); uint8_t m = LEFT(n); (me->m_fork[m] == FREE) && (me->m_fork[n] == FREE) 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_displayPhilStat(n, "eating "); else 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_displayPhilStat(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_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] = 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_displayPhilStat(m, "eating "); } #ifndef dpp_h #define dpp_h using namespace QP; 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)