Dining Philosopher Problem example application : QP::QSignal { EAT_SIG = QP::Q_USER_SIG, // published by Table to let a Philo eat DONE_SIG, // published by Philo 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 TIMEOUT_SIG, // posted by time event to Philo HUNGRY_SIG, // posted by hungry Philo to Table MAX_SIG // the last signal }; QS_SIG_DICTIONARY(EAT_SIG, nullptr); QS_SIG_DICTIONARY(DONE_SIG, nullptr); QS_SIG_DICTIONARY(PAUSE_SIG, nullptr); QS_SIG_DICTIONARY(SERVE_SIG, nullptr); QS_SIG_DICTIONARY(TEST_SIG, nullptr); QS_SIG_DICTIONARY(TIMEOUT_SIG, nullptr); QS_SIG_DICTIONARY(HUNGRY_SIG, nullptr); {5}; : QEvt(sig), philoId(id) : QEvt(QP::QEvt::DYNAMIC), philoId(id) = { &Philo::inst[0], &Philo::inst[1], &Philo::inst[2], &Philo::inst[3], &Philo::inst[4] }; = &Table::inst; The Philo AO and the N_PHILO instances : QActive(Q_STATE_CAST(&initial)), m_timeEvt(this, TIMEOUT_SIG, 0U), m_id(0xFFU) Q_UNUSED_PAR(e); m_id = static_cast<std::uint8_t>(this - &inst[0]); QS_OBJ_ARR_DICTIONARY(&Philo::inst[m_id], m_id); QS_OBJ_ARR_DICTIONARY(&Philo::inst[m_id].m_timeEvt, m_id); subscribe(EAT_SIG); subscribe(TEST_SIG); m_timeEvt.armX(think_time(), 0U); m_timeEvt.disarm(); // EAT or DONE must be for other Philos than this one Q_ASSERT(Q_EVT_CAST(TableEvt)->philoId != m_id); #ifdef QEVT_DYN_CTOR TableEvt const *pe = Q_NEW(TableEvt, HUNGRY_SIG, m_id); #else TableEvt *pe = Q_NEW(TableEvt, HUNGRY_SIG); pe->philoId = m_id; #endif AO_Table->POST(pe, this); Q_EVT_CAST(TableEvt)->philoId == m_id // DONE must be for other Philos than this one Q_ASSERT(Q_EVT_CAST(TableEvt)->philoId != m_id); m_timeEvt.armX(eat_time(), 0U); m_timeEvt.disarm(); #ifdef QEVT_DYN_CTOR TableEvt const *pe = Q_NEW(TableEvt, DONE_SIG, m_id); #else TableEvt *pe = Q_NEW(TableEvt, DONE_SIG); pe->philoId = m_id; #endif QP::QActive::PUBLISH(pe, this); // EAT or DONE must be for other Philos than this one Q_ASSERT(Q_EVT_CAST(TableEvt)->philoId != m_id); : QActive(Q_STATE_CAST(&initial)) for (std::uint8_t n = 0U; n < N_PHILO; ++n) { m_fork[n] = FREE; m_isHungry[n] = false; } Q_UNUSED_PAR(e); QS_OBJ_DICTIONARY(&Table::inst); subscribe(DONE_SIG); subscribe(PAUSE_SIG); subscribe(SERVE_SIG); subscribe(TEST_SIG); for (std::uint8_t n = 0U; n < N_PHILO; ++n) { m_fork[n] = FREE; m_isHungry[n] = false; BSP::displayPhilStat(n, THINKING); } Q_ERROR(); // give permissions to eat... for (std::uint8_t n = 0U; n < N_PHILO; ++n) { if (m_isHungry[n] && (m_fork[left(n)] == FREE) && (m_fork[n] == FREE)) { m_fork[left(n)] = USED; m_fork[n] = USED; #ifdef QEVT_DYN_CTOR TableEvt const *te = Q_NEW(TableEvt, EAT_SIG, n); #else TableEvt *te = Q_NEW(TableEvt, EAT_SIG); te->philoId = n; #endif QP::QActive::PUBLISH(te, this); m_isHungry[n] = false; BSP::displayPhilStat(n, EATING); } } std::uint8_t n = Q_EVT_CAST(TableEvt)->philoId; // phil ID must be in range and he must be not hungry Q_ASSERT((n < N_PHILO) && (!m_isHungry[n])); BSP::displayPhilStat(n, HUNGRY); std::uint8_t m = left(n); (m_fork[m] == FREE) && (m_fork[n] == FREE) m_fork[m] = USED; m_fork[n] = USED; #ifdef QEVT_DYN_CTOR TableEvt const *pe = Q_NEW(TableEvt, EAT_SIG, n); #else TableEvt *pe = Q_NEW(TableEvt, EAT_SIG); pe->philoId = n; #endif QP::QActive::PUBLISH(pe, this); BSP::displayPhilStat(n, EATING); else m_isHungry[n] = true; std::uint8_t n = Q_EVT_CAST(TableEvt)->philoId; // phil ID must be in range and he must be not hungry Q_ASSERT((n < N_PHILO) && (!m_isHungry[n])); BSP::displayPhilStat(n, THINKING); std::uint8_t m = left(n); // both forks of Phil[n] must be used Q_ASSERT((m_fork[n] == USED) && (m_fork[m] == USED)); m_fork[m] = FREE; m_fork[n] = FREE; m = right(n); // check the right neighbor if (m_isHungry[m] && (m_fork[m] == FREE)) { m_fork[n] = USED; m_fork[m] = USED; m_isHungry[m] = false; #ifdef QEVT_DYN_CTOR TableEvt const *pe = Q_NEW(TableEvt, EAT_SIG, m); #else TableEvt *pe = Q_NEW(TableEvt, EAT_SIG); pe->philoId = m; #endif QP::QActive::PUBLISH(pe, this); BSP::displayPhilStat(m, EATING); } m = left(n); // check the left neighbor n = left(m); // left fork of the left neighbor if (m_isHungry[m] && (m_fork[n] == FREE)) { m_fork[m] = USED; m_fork[n] = USED; m_isHungry[m] = false; #ifdef QEVT_DYN_CTOR TableEvt const *pe = Q_NEW(TableEvt, EAT_SIG, m); #else TableEvt *pe = Q_NEW(TableEvt, EAT_SIG); pe->philoId = m; #endif QP::QActive::PUBLISH(pe, this); BSP::displayPhilStat(m, EATING); } Q_ERROR(); BSP::displayPaused(1U); BSP::displayPaused(0U); std::uint8_t n = Q_EVT_CAST(TableEvt)->philoId; // philo ID must be in range and he must be not hungry Q_ASSERT((n < N_PHILO) && (!m_isHungry[n])); m_isHungry[n] = true; BSP::displayPhilStat(n, HUNGRY); std::uint8_t n = Q_EVT_CAST(TableEvt)->philoId; // phil ID must be in range and he must be not hungry Q_ASSERT((n < N_PHILO) && (!m_isHungry[n])); BSP::displayPhilStat(n, THINKING); std::uint8_t m = left(n); // both forks of Phil[n] must be used Q_ASSERT((m_fork[n] == USED) && (m_fork[m] == USED)); m_fork[m] = FREE; m_fork[n] = FREE; #ifndef DPP_HPP_ #define DPP_HPP_ $declare ${Shared} #ifdef QXK_HPP_ namespace APP { extern QP::QXThread * const TH_XThread1; extern QP::QXThread * const TH_XThread2; extern QP::QXSemaphore TH_sema; extern QP::QXMutex TH_mutex; } // namespace APP #endif // QXK_HPP_ #endif // DPP_HPP_ #include "qpcpp.hpp" // QP/C++ real-time embedded framework #include "dpp.hpp" // DPP Application interface #include "bsp.hpp" // Board Support Package //---------------------------------------------------------------------------- namespace { // unnamed namespace for local definitions with internal linkage Q_DEFINE_THIS_FILE // helper function to provide a randomized think time for Philos static inline QP::QTimeEvtCtr think_time() { return static_cast<QP::QTimeEvtCtr>((BSP::random() % BSP::TICKS_PER_SEC) + (BSP::TICKS_PER_SEC/2U)); } // helper function to provide a randomized eat time for Philos static inline QP::QTimeEvtCtr eat_time() { return static_cast<QP::QTimeEvtCtr>((BSP::random() % BSP::TICKS_PER_SEC) + BSP::TICKS_PER_SEC); } } // unnamed namespace //---------------------------------------------------------------------------- $declare ${AOs::Philo} $define ${Shared::AO_Philo[N_PHILO]} $define ${AOs::Philo} #include "qpcpp.hpp" // QP/C++ real-time embedded framework #include "dpp.hpp" // DPP Application interface #include "bsp.hpp" // Board Support Package $declare ${AOs::Table} //---------------------------------------------------------------------------- // unnamed namespace for local definitions with internal linkage namespace { Q_DEFINE_THIS_FILE // helper function to provide the RIGHT neighbour of a Philo[n] static inline std::uint8_t right(std::uint8_t const n) { return static_cast<std::uint8_t>((n + (APP::N_PHILO - 1U)) % APP::N_PHILO); } // helper function to provide the LEFT neighbour of a Philo[n] static inline std::uint8_t left(std::uint8_t const n) { return static_cast<std::uint8_t>((n + 1U) % APP::N_PHILO); } static constexpr std::uint8_t FREE {0U}; static constexpr std::uint8_t USED {1U}; static constexpr char const * const THINKING {"thinking"}; static constexpr char const * const HUNGRY {"hungry "}; static constexpr char const * const EATING {"eating "}; } // unnamed namespace //---------------------------------------------------------------------------- $define ${Shared::AO_Table} $define ${AOs::Table}