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:
Mon Sep 26 02:21:01 2011 +0000
Revision:
3:81ceb3127876
Parent:
0:efb9ac8d1a88
Child:
4:6189d844a1a2
Updated for QP 4.2.04

Who changed what in which revision?

UserRevisionLine numberNew contents of line
QL 0:efb9ac8d1a88 1 //////////////////////////////////////////////////////////////////////////////
QL 0:efb9ac8d1a88 2 // Product: DPP example
QL 3:81ceb3127876 3 // Last Updated for Version: 4.2.00
QL 3:81ceb3127876 4 // Date of the Last Update: Jul 15, 2011
QL 0:efb9ac8d1a88 5 //
QL 0:efb9ac8d1a88 6 // Q u a n t u m L e a P s
QL 0:efb9ac8d1a88 7 // ---------------------------
QL 0:efb9ac8d1a88 8 // innovating embedded systems
QL 0:efb9ac8d1a88 9 //
QL 3:81ceb3127876 10 // Copyright (C) 2002-2011 Quantum Leaps, LLC. All rights reserved.
QL 0:efb9ac8d1a88 11 //
QL 0:efb9ac8d1a88 12 // This software may be distributed and modified under the terms of the GNU
QL 0:efb9ac8d1a88 13 // General Public License version 2 (GPL) as published by the Free Software
QL 0:efb9ac8d1a88 14 // Foundation and appearing in the file GPL.TXT included in the packaging of
QL 0:efb9ac8d1a88 15 // this file. Please note that GPL Section 2[b] requires that all works based
QL 0:efb9ac8d1a88 16 // on this software must also be made publicly available under the terms of
QL 0:efb9ac8d1a88 17 // the GPL ("Copyleft").
QL 0:efb9ac8d1a88 18 //
QL 0:efb9ac8d1a88 19 // Alternatively, this software may be distributed and modified under the
QL 0:efb9ac8d1a88 20 // terms of Quantum Leaps commercial licenses, which expressly supersede
QL 0:efb9ac8d1a88 21 // the GPL and are specifically designed for licensees interested in
QL 0:efb9ac8d1a88 22 // retaining the proprietary status of their code.
QL 0:efb9ac8d1a88 23 //
QL 0:efb9ac8d1a88 24 // Contact information:
QL 0:efb9ac8d1a88 25 // Quantum Leaps Web site: http://www.quantum-leaps.com
QL 0:efb9ac8d1a88 26 // e-mail: info@quantum-leaps.com
QL 0:efb9ac8d1a88 27 //////////////////////////////////////////////////////////////////////////////
QL 0:efb9ac8d1a88 28 #include "qp_port.h"
QL 0:efb9ac8d1a88 29 #include "dpp.h"
QL 0:efb9ac8d1a88 30 #include "bsp.h"
QL 0:efb9ac8d1a88 31
QL 0:efb9ac8d1a88 32 Q_DEFINE_THIS_FILE
QL 0:efb9ac8d1a88 33
QL 0:efb9ac8d1a88 34 // Active object class -------------------------------------------------------
QL 0:efb9ac8d1a88 35 class Table : public QActive {
QL 0:efb9ac8d1a88 36 private:
QL 0:efb9ac8d1a88 37 uint8_t m_fork[N_PHILO];
QL 0:efb9ac8d1a88 38 uint8_t m_isHungry[N_PHILO];
QL 0:efb9ac8d1a88 39
QL 0:efb9ac8d1a88 40 public:
QL 0:efb9ac8d1a88 41 Table();
QL 0:efb9ac8d1a88 42
QL 0:efb9ac8d1a88 43 private:
QL 0:efb9ac8d1a88 44 static QState initial(Table *me, QEvent const *e);
QL 0:efb9ac8d1a88 45 static QState serving(Table *me, QEvent const *e);
QL 0:efb9ac8d1a88 46 };
QL 0:efb9ac8d1a88 47
QL 0:efb9ac8d1a88 48 #define RIGHT(n_) ((uint8_t)(((n_) + (N_PHILO - 1)) % N_PHILO))
QL 0:efb9ac8d1a88 49 #define LEFT(n_) ((uint8_t)(((n_) + 1) % N_PHILO))
QL 0:efb9ac8d1a88 50 enum ForkState { FREE, USED };
QL 0:efb9ac8d1a88 51
QL 0:efb9ac8d1a88 52 // Local objects -------------------------------------------------------------
QL 0:efb9ac8d1a88 53 static Table l_table; // local Table object
QL 0:efb9ac8d1a88 54
QL 0:efb9ac8d1a88 55 // Public-scope objects ------------------------------------------------------
QL 0:efb9ac8d1a88 56 QActive * const AO_Table = &l_table; // "opaque" AO pointer
QL 0:efb9ac8d1a88 57
QL 0:efb9ac8d1a88 58 //............................................................................
QL 0:efb9ac8d1a88 59 Table::Table() : QActive((QStateHandler)&Table::initial) {
QL 0:efb9ac8d1a88 60 uint8_t n;
QL 0:efb9ac8d1a88 61 for (n = 0; n < N_PHILO; ++n) {
QL 0:efb9ac8d1a88 62 m_fork[n] = FREE;
QL 0:efb9ac8d1a88 63 m_isHungry[n] = 0;
QL 0:efb9ac8d1a88 64 }
QL 0:efb9ac8d1a88 65 }
QL 0:efb9ac8d1a88 66 //............................................................................
QL 0:efb9ac8d1a88 67 QState Table::initial(Table *me, QEvent const *) {
QL 0:efb9ac8d1a88 68
QL 0:efb9ac8d1a88 69 QS_OBJ_DICTIONARY(&l_table);
QL 0:efb9ac8d1a88 70 QS_FUN_DICTIONARY(&QHsm::top);
QL 0:efb9ac8d1a88 71 QS_FUN_DICTIONARY(&Table::initial);
QL 0:efb9ac8d1a88 72 QS_FUN_DICTIONARY(&Table::serving);
QL 0:efb9ac8d1a88 73
QL 0:efb9ac8d1a88 74 QS_SIG_DICTIONARY(DONE_SIG, 0); // global signals
QL 0:efb9ac8d1a88 75 QS_SIG_DICTIONARY(EAT_SIG, 0);
QL 0:efb9ac8d1a88 76 QS_SIG_DICTIONARY(TERMINATE_SIG, 0);
QL 0:efb9ac8d1a88 77
QL 0:efb9ac8d1a88 78 QS_SIG_DICTIONARY(HUNGRY_SIG, me); // signal just for Table
QL 0:efb9ac8d1a88 79
QL 0:efb9ac8d1a88 80 me->subscribe(DONE_SIG);
QL 0:efb9ac8d1a88 81 me->subscribe(TERMINATE_SIG);
QL 0:efb9ac8d1a88 82
QL 0:efb9ac8d1a88 83 return Q_TRAN(&Table::serving);
QL 0:efb9ac8d1a88 84 }
QL 0:efb9ac8d1a88 85 //............................................................................
QL 0:efb9ac8d1a88 86 QState Table::serving(Table *me, QEvent const *e) {
QL 0:efb9ac8d1a88 87 uint8_t n, m;
QL 0:efb9ac8d1a88 88 TableEvt *pe;
QL 0:efb9ac8d1a88 89
QL 0:efb9ac8d1a88 90 switch (e->sig) {
QL 0:efb9ac8d1a88 91 case HUNGRY_SIG: {
QL 0:efb9ac8d1a88 92 n = ((TableEvt const *)e)->philoNum;
QL 0:efb9ac8d1a88 93 // phil ID must be in range and he must be not hungry
QL 0:efb9ac8d1a88 94 Q_ASSERT((n < N_PHILO) && (!me->m_isHungry[n]));
QL 0:efb9ac8d1a88 95
QL 0:efb9ac8d1a88 96 BSP_displyPhilStat(n, "hungry ");
QL 0:efb9ac8d1a88 97 m = LEFT(n);
QL 0:efb9ac8d1a88 98 if ((me->m_fork[m] == FREE) && (me->m_fork[n] == FREE)) {
QL 0:efb9ac8d1a88 99 me->m_fork[m] = me->m_fork[n] = USED;
QL 0:efb9ac8d1a88 100 pe = Q_NEW(TableEvt, EAT_SIG);
QL 0:efb9ac8d1a88 101 pe->philoNum = n;
QL 3:81ceb3127876 102 QF::PUBLISH(pe, me);
QL 0:efb9ac8d1a88 103 BSP_displyPhilStat(n, "eating ");
QL 0:efb9ac8d1a88 104 }
QL 0:efb9ac8d1a88 105 else {
QL 0:efb9ac8d1a88 106 me->m_isHungry[n] = 1;
QL 0:efb9ac8d1a88 107 }
QL 0:efb9ac8d1a88 108 return Q_HANDLED();
QL 0:efb9ac8d1a88 109 }
QL 0:efb9ac8d1a88 110 case DONE_SIG: {
QL 0:efb9ac8d1a88 111 n = ((TableEvt const *)e)->philoNum;
QL 0:efb9ac8d1a88 112 // phil ID must be in range and he must be not hungry
QL 0:efb9ac8d1a88 113 Q_ASSERT((n < N_PHILO) && (!me->m_isHungry[n]));
QL 0:efb9ac8d1a88 114
QL 0:efb9ac8d1a88 115 BSP_displyPhilStat(n, "thinking");
QL 0:efb9ac8d1a88 116 m = LEFT(n);
QL 0:efb9ac8d1a88 117 // both forks of Phil[n] must be used
QL 0:efb9ac8d1a88 118 Q_ASSERT((me->m_fork[n] == USED) && (me->m_fork[m] == USED));
QL 0:efb9ac8d1a88 119
QL 0:efb9ac8d1a88 120 me->m_fork[m] = me->m_fork[n] = FREE;
QL 0:efb9ac8d1a88 121 m = RIGHT(n); // check the right neighbor
QL 0:efb9ac8d1a88 122 if (me->m_isHungry[m] && (me->m_fork[m] == FREE)) {
QL 0:efb9ac8d1a88 123 me->m_fork[n] = me->m_fork[m] = USED;
QL 0:efb9ac8d1a88 124 me->m_isHungry[m] = 0;
QL 0:efb9ac8d1a88 125 pe = Q_NEW(TableEvt, EAT_SIG);
QL 0:efb9ac8d1a88 126 pe->philoNum = m;
QL 3:81ceb3127876 127 QF::PUBLISH(pe, me);
QL 0:efb9ac8d1a88 128 BSP_displyPhilStat(m, "eating ");
QL 0:efb9ac8d1a88 129 }
QL 0:efb9ac8d1a88 130 m = LEFT(n); // check the left neighbor
QL 0:efb9ac8d1a88 131 n = LEFT(m); // left fork of the left neighbor
QL 0:efb9ac8d1a88 132 if (me->m_isHungry[m] && (me->m_fork[n] == FREE)) {
QL 0:efb9ac8d1a88 133 me->m_fork[m] = me->m_fork[n] = USED;
QL 0:efb9ac8d1a88 134 me->m_isHungry[m] = 0;
QL 0:efb9ac8d1a88 135 pe = Q_NEW(TableEvt, EAT_SIG);
QL 0:efb9ac8d1a88 136 pe->philoNum = m;
QL 3:81ceb3127876 137 QF::PUBLISH(pe, me);
QL 0:efb9ac8d1a88 138 BSP_displyPhilStat(m, "eating ");
QL 0:efb9ac8d1a88 139 }
QL 0:efb9ac8d1a88 140 return Q_HANDLED();
QL 0:efb9ac8d1a88 141 }
QL 0:efb9ac8d1a88 142 case TERMINATE_SIG: {
QL 0:efb9ac8d1a88 143 QF::stop();
QL 0:efb9ac8d1a88 144 return Q_HANDLED();
QL 0:efb9ac8d1a88 145 }
QL 0:efb9ac8d1a88 146 }
QL 0:efb9ac8d1a88 147 return Q_SUPER(&QHsm::top);
QL 0:efb9ac8d1a88 148 }