Dining Philosophers Problem (DPP) example for the QP active object framework. Demonstrates: event-driven programming, hierarchical state machines in C++, modeling and graphical state machine design, code generation, preemptive multitasking, software tracing, power saving mode, direct event posting, publish-subscribe. More information available in the [[/users/QL/notebook|Quantum Leaps Notebook pages]]. See also [[http://www.state-machine.com|state-machine.com]].

Dependencies:   mbed qp

Committer:
QL
Date:
Wed Sep 05 13:50:21 2012 +0000
Revision:
5:15aad9bccbbd
Parent:
4:6189d844a1a2
enabled the QK_PREEMPTIVE option

Who changed what in which revision?

UserRevisionLine numberNew contents of line
QL 0:efb9ac8d1a88 1 //////////////////////////////////////////////////////////////////////////////
QL 4:6189d844a1a2 2 // Model: dpp.qm
QL 4:6189d844a1a2 3 // File: ././philo.cpp
QL 0:efb9ac8d1a88 4 //
QL 4:6189d844a1a2 5 // This file has been generated automatically by QP Modeler (QM).
QL 4:6189d844a1a2 6 // DO NOT EDIT THIS FILE MANUALLY.
QL 0:efb9ac8d1a88 7 //
QL 4:6189d844a1a2 8 // Please visit www.state-machine.com/qm for more information.
QL 0:efb9ac8d1a88 9 //////////////////////////////////////////////////////////////////////////////
QL 0:efb9ac8d1a88 10 #include "qp_port.h"
QL 0:efb9ac8d1a88 11 #include "dpp.h"
QL 0:efb9ac8d1a88 12 #include "bsp.h"
QL 0:efb9ac8d1a88 13
QL 4:6189d844a1a2 14 namespace DPP {
QL 4:6189d844a1a2 15
QL 0:efb9ac8d1a88 16 Q_DEFINE_THIS_FILE
QL 0:efb9ac8d1a88 17
QL 0:efb9ac8d1a88 18 // Active object class -------------------------------------------------------
QL 4:6189d844a1a2 19 // @(/2/0) ...................................................................
QL 4:6189d844a1a2 20 class Philo : public QP::QActive {
QL 0:efb9ac8d1a88 21 private:
QL 4:6189d844a1a2 22 QP::QTimeEvt m_timeEvt;
QL 0:efb9ac8d1a88 23
QL 0:efb9ac8d1a88 24 public:
QL 0:efb9ac8d1a88 25 Philo();
QL 0:efb9ac8d1a88 26
QL 4:6189d844a1a2 27 protected:
QL 4:6189d844a1a2 28 static QP::QState initial(Philo * const me, QP::QEvt const * const e);
QL 4:6189d844a1a2 29 static QP::QState thinking(Philo * const me, QP::QEvt const * const e);
QL 4:6189d844a1a2 30 static QP::QState hungry(Philo * const me, QP::QEvt const * const e);
QL 4:6189d844a1a2 31 static QP::QState eating(Philo * const me, QP::QEvt const * const e);
QL 0:efb9ac8d1a88 32 };
QL 0:efb9ac8d1a88 33
QL 0:efb9ac8d1a88 34 // Local objects -------------------------------------------------------------
QL 4:6189d844a1a2 35 static Philo l_philo[N_PHILO]; // storage for all Philos
QL 0:efb9ac8d1a88 36
QL 4:6189d844a1a2 37 // helper function to provide a randomized think time for Philos
QL 4:6189d844a1a2 38 inline QP::QTimeEvtCtr think_time() {
QL 4:6189d844a1a2 39 return static_cast<QP::QTimeEvtCtr>((BSP_random() % BSP_TICKS_PER_SEC)
QL 4:6189d844a1a2 40 + (BSP_TICKS_PER_SEC/2U));
QL 4:6189d844a1a2 41 }
QL 3:81ceb3127876 42
QL 4:6189d844a1a2 43 // helper function to provide a randomized eat time for Philos
QL 4:6189d844a1a2 44 inline QP::QTimeEvtCtr eat_time() {
QL 4:6189d844a1a2 45 return static_cast<QP::QTimeEvtCtr>((BSP_random() % BSP_TICKS_PER_SEC)
QL 4:6189d844a1a2 46 + BSP_TICKS_PER_SEC);
QL 4:6189d844a1a2 47 }
QL 0:efb9ac8d1a88 48
QL 4:6189d844a1a2 49 // helper function to provide the ID of Philo "me"
QL 4:6189d844a1a2 50 inline uint8_t PHILO_ID(Philo const * const me) {
QL 4:6189d844a1a2 51 return static_cast<uint8_t>(me - l_philo);
QL 4:6189d844a1a2 52 }
QL 4:6189d844a1a2 53
QL 4:6189d844a1a2 54 enum InternalSignals { // internal signals
QL 0:efb9ac8d1a88 55 TIMEOUT_SIG = MAX_SIG
QL 0:efb9ac8d1a88 56 };
QL 4:6189d844a1a2 57
QL 0:efb9ac8d1a88 58 // Global objects ------------------------------------------------------------
QL 4:6189d844a1a2 59 QP::QActive * const AO_Philo[N_PHILO] = { // "opaque" pointers to Philo AO
QL 0:efb9ac8d1a88 60 &l_philo[0],
QL 0:efb9ac8d1a88 61 &l_philo[1],
QL 0:efb9ac8d1a88 62 &l_philo[2],
QL 0:efb9ac8d1a88 63 &l_philo[3],
QL 0:efb9ac8d1a88 64 &l_philo[4]
QL 0:efb9ac8d1a88 65 };
QL 0:efb9ac8d1a88 66
QL 4:6189d844a1a2 67 // Philo definition ----------------------------------------------------------
QL 4:6189d844a1a2 68 // @(/2/0) ...................................................................
QL 4:6189d844a1a2 69 // @(/2/0/1) .................................................................
QL 4:6189d844a1a2 70 Philo::Philo()
QL 4:6189d844a1a2 71 : QActive(Q_STATE_CAST(&Philo::initial)),
QL 4:6189d844a1a2 72 m_timeEvt(TIMEOUT_SIG)
QL 4:6189d844a1a2 73 {
QL 4:6189d844a1a2 74 }
QL 4:6189d844a1a2 75
QL 4:6189d844a1a2 76 // @(/2/0/2) .................................................................
QL 4:6189d844a1a2 77 // @(/2/0/2/0)
QL 4:6189d844a1a2 78 QP::QState Philo::initial(Philo * const me, QP::QEvt const * const e) {
QL 4:6189d844a1a2 79 static bool registered = false; // starts off with 0, per C-standard
QL 4:6189d844a1a2 80 (void)e; // suppress the compiler warning about unused parameter
QL 0:efb9ac8d1a88 81 if (!registered) {
QL 4:6189d844a1a2 82 registered = true;
QL 4:6189d844a1a2 83
QL 0:efb9ac8d1a88 84 QS_OBJ_DICTIONARY(&l_philo[0]);
QL 0:efb9ac8d1a88 85 QS_OBJ_DICTIONARY(&l_philo[0].m_timeEvt);
QL 0:efb9ac8d1a88 86 QS_OBJ_DICTIONARY(&l_philo[1]);
QL 0:efb9ac8d1a88 87 QS_OBJ_DICTIONARY(&l_philo[1].m_timeEvt);
QL 0:efb9ac8d1a88 88 QS_OBJ_DICTIONARY(&l_philo[2]);
QL 0:efb9ac8d1a88 89 QS_OBJ_DICTIONARY(&l_philo[2].m_timeEvt);
QL 0:efb9ac8d1a88 90 QS_OBJ_DICTIONARY(&l_philo[3]);
QL 0:efb9ac8d1a88 91 QS_OBJ_DICTIONARY(&l_philo[3].m_timeEvt);
QL 0:efb9ac8d1a88 92 QS_OBJ_DICTIONARY(&l_philo[4]);
QL 0:efb9ac8d1a88 93 QS_OBJ_DICTIONARY(&l_philo[4].m_timeEvt);
QL 0:efb9ac8d1a88 94
QL 0:efb9ac8d1a88 95 QS_FUN_DICTIONARY(&Philo::initial);
QL 0:efb9ac8d1a88 96 QS_FUN_DICTIONARY(&Philo::thinking);
QL 0:efb9ac8d1a88 97 QS_FUN_DICTIONARY(&Philo::hungry);
QL 0:efb9ac8d1a88 98 QS_FUN_DICTIONARY(&Philo::eating);
QL 0:efb9ac8d1a88 99 }
QL 4:6189d844a1a2 100 QS_SIG_DICTIONARY(HUNGRY_SIG, me); // signal for each Philos
QL 4:6189d844a1a2 101 QS_SIG_DICTIONARY(TIMEOUT_SIG, me); // signal for each Philos
QL 0:efb9ac8d1a88 102
QL 0:efb9ac8d1a88 103 me->subscribe(EAT_SIG);
QL 0:efb9ac8d1a88 104 return Q_TRAN(&Philo::thinking);
QL 0:efb9ac8d1a88 105 }
QL 4:6189d844a1a2 106 // @(/2/0/2/1) ...............................................................
QL 4:6189d844a1a2 107 QP::QState Philo::thinking(Philo * const me, QP::QEvt const * const e) {
QL 4:6189d844a1a2 108 QP::QState status;
QL 0:efb9ac8d1a88 109 switch (e->sig) {
QL 4:6189d844a1a2 110 // @(/2/0/2/1)
QL 0:efb9ac8d1a88 111 case Q_ENTRY_SIG: {
QL 4:6189d844a1a2 112 me->m_timeEvt.postIn(me, think_time());
QL 4:6189d844a1a2 113 status = Q_HANDLED();
QL 4:6189d844a1a2 114 break;
QL 0:efb9ac8d1a88 115 }
QL 4:6189d844a1a2 116 // @(/2/0/2/1)
QL 4:6189d844a1a2 117 case Q_EXIT_SIG: {
QL 4:6189d844a1a2 118 (void)me->m_timeEvt.disarm();
QL 4:6189d844a1a2 119 status = Q_HANDLED();
QL 4:6189d844a1a2 120 break;
QL 4:6189d844a1a2 121 }
QL 4:6189d844a1a2 122 // @(/2/0/2/1/0)
QL 0:efb9ac8d1a88 123 case TIMEOUT_SIG: {
QL 4:6189d844a1a2 124 status = Q_TRAN(&Philo::hungry);
QL 4:6189d844a1a2 125 break;
QL 0:efb9ac8d1a88 126 }
QL 4:6189d844a1a2 127 // @(/2/0/2/1/1)
QL 4:6189d844a1a2 128 case EAT_SIG: // intentionally fall through
QL 0:efb9ac8d1a88 129 case DONE_SIG: {
QL 4:6189d844a1a2 130 /* EAT or DONE must be for other Philos than this one */
QL 4:6189d844a1a2 131 Q_ASSERT(Q_EVT_CAST(TableEvt)->philoNum != PHILO_ID(me));
QL 4:6189d844a1a2 132 status = Q_HANDLED();
QL 4:6189d844a1a2 133 break;
QL 4:6189d844a1a2 134 }
QL 4:6189d844a1a2 135 default: {
QL 4:6189d844a1a2 136 status = Q_SUPER(&QHsm::top);
QL 4:6189d844a1a2 137 break;
QL 0:efb9ac8d1a88 138 }
QL 0:efb9ac8d1a88 139 }
QL 4:6189d844a1a2 140 return status;
QL 0:efb9ac8d1a88 141 }
QL 4:6189d844a1a2 142 // @(/2/0/2/2) ...............................................................
QL 4:6189d844a1a2 143 QP::QState Philo::hungry(Philo * const me, QP::QEvt const * const e) {
QL 4:6189d844a1a2 144 QP::QState status;
QL 0:efb9ac8d1a88 145 switch (e->sig) {
QL 4:6189d844a1a2 146 // @(/2/0/2/2)
QL 0:efb9ac8d1a88 147 case Q_ENTRY_SIG: {
QL 0:efb9ac8d1a88 148 TableEvt *pe = Q_NEW(TableEvt, HUNGRY_SIG);
QL 0:efb9ac8d1a88 149 pe->philoNum = PHILO_ID(me);
QL 3:81ceb3127876 150 AO_Table->POST(pe, me);
QL 4:6189d844a1a2 151 status = Q_HANDLED();
QL 4:6189d844a1a2 152 break;
QL 0:efb9ac8d1a88 153 }
QL 4:6189d844a1a2 154 // @(/2/0/2/2/0)
QL 0:efb9ac8d1a88 155 case EAT_SIG: {
QL 4:6189d844a1a2 156 // @(/2/0/2/2/0/0)
QL 4:6189d844a1a2 157 if (Q_EVT_CAST(TableEvt)->philoNum == PHILO_ID(me)) {
QL 4:6189d844a1a2 158 status = Q_TRAN(&Philo::eating);
QL 4:6189d844a1a2 159 }
QL 4:6189d844a1a2 160 else {
QL 4:6189d844a1a2 161 status = Q_UNHANDLED();
QL 0:efb9ac8d1a88 162 }
QL 0:efb9ac8d1a88 163 break;
QL 0:efb9ac8d1a88 164 }
QL 4:6189d844a1a2 165 // @(/2/0/2/2/1)
QL 0:efb9ac8d1a88 166 case DONE_SIG: {
QL 4:6189d844a1a2 167 /* DONE must be for other Philos than this one */
QL 4:6189d844a1a2 168 Q_ASSERT(Q_EVT_CAST(TableEvt)->philoNum != PHILO_ID(me));
QL 4:6189d844a1a2 169 status = Q_HANDLED();
QL 4:6189d844a1a2 170 break;
QL 4:6189d844a1a2 171 }
QL 4:6189d844a1a2 172 default: {
QL 4:6189d844a1a2 173 status = Q_SUPER(&QHsm::top);
QL 4:6189d844a1a2 174 break;
QL 0:efb9ac8d1a88 175 }
QL 0:efb9ac8d1a88 176 }
QL 4:6189d844a1a2 177 return status;
QL 0:efb9ac8d1a88 178 }
QL 4:6189d844a1a2 179 // @(/2/0/2/3) ...............................................................
QL 4:6189d844a1a2 180 QP::QState Philo::eating(Philo * const me, QP::QEvt const * const e) {
QL 4:6189d844a1a2 181 QP::QState status;
QL 0:efb9ac8d1a88 182 switch (e->sig) {
QL 4:6189d844a1a2 183 // @(/2/0/2/3)
QL 0:efb9ac8d1a88 184 case Q_ENTRY_SIG: {
QL 4:6189d844a1a2 185 me->m_timeEvt.postIn(me, eat_time());
QL 4:6189d844a1a2 186 status = Q_HANDLED();
QL 4:6189d844a1a2 187 break;
QL 0:efb9ac8d1a88 188 }
QL 4:6189d844a1a2 189 // @(/2/0/2/3)
QL 0:efb9ac8d1a88 190 case Q_EXIT_SIG: {
QL 0:efb9ac8d1a88 191 TableEvt *pe = Q_NEW(TableEvt, DONE_SIG);
QL 0:efb9ac8d1a88 192 pe->philoNum = PHILO_ID(me);
QL 4:6189d844a1a2 193 QP::QF::PUBLISH(pe, me);
QL 4:6189d844a1a2 194 (void)me->m_timeEvt.disarm();
QL 4:6189d844a1a2 195 status = Q_HANDLED();
QL 4:6189d844a1a2 196 break;
QL 0:efb9ac8d1a88 197 }
QL 4:6189d844a1a2 198 // @(/2/0/2/3/0)
QL 0:efb9ac8d1a88 199 case TIMEOUT_SIG: {
QL 4:6189d844a1a2 200 status = Q_TRAN(&Philo::thinking);
QL 4:6189d844a1a2 201 break;
QL 0:efb9ac8d1a88 202 }
QL 4:6189d844a1a2 203 // @(/2/0/2/3/1)
QL 4:6189d844a1a2 204 case EAT_SIG: // intentionally fall through
QL 0:efb9ac8d1a88 205 case DONE_SIG: {
QL 4:6189d844a1a2 206 /* EAT or DONE must be for other Philos than this one */
QL 4:6189d844a1a2 207 Q_ASSERT(Q_EVT_CAST(TableEvt)->philoNum != PHILO_ID(me));
QL 4:6189d844a1a2 208 status = Q_HANDLED();
QL 4:6189d844a1a2 209 break;
QL 4:6189d844a1a2 210 }
QL 4:6189d844a1a2 211 default: {
QL 4:6189d844a1a2 212 status = Q_SUPER(&QHsm::top);
QL 4:6189d844a1a2 213 break;
QL 0:efb9ac8d1a88 214 }
QL 0:efb9ac8d1a88 215 }
QL 4:6189d844a1a2 216 return status;
QL 0:efb9ac8d1a88 217 }
QL 4:6189d844a1a2 218
QL 4:6189d844a1a2 219
QL 4:6189d844a1a2 220 } // namespace DPP