2012-08-14 18:00:48 -04:00
|
|
|
<?xml version="1.0" encoding="UTF-8"?>
|
2012-12-10 16:01:54 -05:00
|
|
|
<model version="2.2.03">
|
2012-08-14 18:00:48 -04:00
|
|
|
<documentation>Dining Philosopher Problem example</documentation>
|
2012-12-10 16:01:54 -05:00
|
|
|
<framework name="qpcpp"/>
|
2012-08-14 18:00:48 -04:00
|
|
|
<package name="Events" stereotype="0x01">
|
2012-12-10 16:01:54 -05:00
|
|
|
<class name="TableEvt" superclass="qpcpp::QEvt">
|
2012-08-14 18:00:48 -04:00
|
|
|
<attribute name="philoNum" type="uint8_t" visibility="0x00" properties="0x00"/>
|
|
|
|
</class>
|
|
|
|
</package>
|
|
|
|
<package name="AOs" stereotype="0x02">
|
|
|
|
<class name="Philo" superclass="qpcpp::QActive">
|
|
|
|
<attribute name="m_timeEvt" type="QTimeEvt" visibility="0x02" properties="0x00"/>
|
|
|
|
<operation name="Philo" type="QActive((QStateHandler)&Philo::initial), m_timeEvt(TIMEOUT_SIG)" visibility="0x00" properties="0x00"/>
|
|
|
|
<statechart>
|
|
|
|
<initial target="../1">
|
|
|
|
<action>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);</action>
|
|
|
|
<initial_glyph conn="2,3,5,1,20,5,-3">
|
|
|
|
<action box="0,-2,6,2"/>
|
|
|
|
</initial_glyph>
|
|
|
|
</initial>
|
|
|
|
<state name="thinking">
|
|
|
|
<entry>me->m_timeEvt.postIn(me, THINK_TIME);</entry>
|
|
|
|
<tran trig="TIMEOUT" target="../../2">
|
|
|
|
<action>BSP_busyDelay();</action>
|
|
|
|
<tran_glyph conn="2,12,3,1,20,18,-3">
|
|
|
|
<action box="0,-2,6,2"/>
|
|
|
|
</tran_glyph>
|
|
|
|
</tran>
|
|
|
|
<state_glyph node="2,5,17,20">
|
|
|
|
<entry box="1,2,5,2"/>
|
|
|
|
</state_glyph>
|
|
|
|
</state>
|
|
|
|
<state name="hungry">
|
|
|
|
<entry>TableEvt *pe = Q_NEW(TableEvt, HUNGRY_SIG);
|
|
|
|
pe->philoNum = PHILO_ID(me);
|
|
|
|
AO_Table->POST(pe, me);</entry>
|
|
|
|
<tran trig="EAT">
|
2012-12-10 16:01:54 -05:00
|
|
|
<choice target="../../../3">
|
|
|
|
<guard>((TableEvt const *)e)->philoNum == PHILO_ID(me)</guard>
|
2012-08-14 18:00:48 -04:00
|
|
|
<action>BSP_busyDelay();</action>
|
|
|
|
<choice_glyph conn="16,35,5,1,6,13,-3">
|
|
|
|
<action box="1,0,20,6"/>
|
|
|
|
</choice_glyph>
|
|
|
|
</choice>
|
|
|
|
<tran_glyph conn="2,35,3,-1,14">
|
|
|
|
<action box="0,-2,14,2"/>
|
|
|
|
</tran_glyph>
|
|
|
|
</tran>
|
|
|
|
<state_glyph node="2,28,17,16">
|
|
|
|
<entry box="1,2,5,2"/>
|
|
|
|
</state_glyph>
|
|
|
|
</state>
|
|
|
|
<state name="eating">
|
|
|
|
<entry>me->m_timeEvt.postIn(me, EAT_TIME);</entry>
|
|
|
|
<exit>TableEvt *pe = Q_NEW(TableEvt, DONE_SIG);
|
|
|
|
pe->philoNum = PHILO_ID(me);
|
|
|
|
AO_Table->POST(pe, me);</exit>
|
|
|
|
<tran trig="TIMEOUT" target="../../1">
|
|
|
|
<action>BSP_busyDelay();</action>
|
|
|
|
<tran_glyph conn="2,56,3,1,22,-46,-5">
|
|
|
|
<action box="0,-2,6,2"/>
|
|
|
|
</tran_glyph>
|
|
|
|
</tran>
|
|
|
|
<state_glyph node="2,46,17,21">
|
|
|
|
<entry box="1,2,5,2"/>
|
|
|
|
<exit box="1,4,5,2"/>
|
|
|
|
</state_glyph>
|
|
|
|
</state>
|
|
|
|
<state_diagram size="39,69"/>
|
|
|
|
</statechart>
|
|
|
|
</class>
|
|
|
|
<class name="Table" superclass="qpcpp::QActive">
|
|
|
|
<attribute name="m_fork[N_PHILO]" type="uint8_t" visibility="0x02" properties="0x00"/>
|
|
|
|
<attribute name="m_isHungry[N_PHILO]" type="uint8_t" visibility="0x02" properties="0x00"/>
|
|
|
|
<operation name="Table" type="QActive((QStateHandler)&Table::initial)" visibility="0x00" properties="0x00">
|
|
|
|
<code>for (uint8_t n = 0; n < N_PHILO; ++n) {
|
|
|
|
m_fork[n] = FREE;
|
|
|
|
m_isHungry[n] = 0;
|
|
|
|
}</code>
|
|
|
|
</operation>
|
|
|
|
<statechart>
|
|
|
|
<initial target="../1">
|
|
|
|
<action>(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);</action>
|
|
|
|
<initial_glyph conn="3,3,5,1,40,5,-3">
|
|
|
|
<action box="0,-2,6,2"/>
|
|
|
|
</initial_glyph>
|
|
|
|
</initial>
|
|
|
|
<state name="serving">
|
|
|
|
<tran trig="HUNGRY">
|
|
|
|
<action>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]));
|
|
|
|
|
2012-12-10 16:01:54 -05:00
|
|
|
BSP_displayPhilStat(n, "hungry ");
|
2012-08-14 18:00:48 -04:00
|
|
|
uint8_t m = LEFT(n);</action>
|
2012-12-10 16:01:54 -05:00
|
|
|
<choice>
|
|
|
|
<guard>(me->m_fork[m] == FREE) && (me->m_fork[n] == FREE)</guard>
|
2012-08-14 18:00:48 -04:00
|
|
|
<action>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);
|
2012-12-10 16:01:54 -05:00
|
|
|
BSP_displayPhilStat(n, "eating ");</action>
|
2012-08-14 18:00:48 -04:00
|
|
|
<choice_glyph conn="20,13,5,-1,10">
|
|
|
|
<action box="1,0,18,4"/>
|
|
|
|
</choice_glyph>
|
|
|
|
</choice>
|
2012-12-10 16:01:54 -05:00
|
|
|
<choice>
|
|
|
|
<guard>else</guard>
|
2012-08-14 18:00:48 -04:00
|
|
|
<action>me->m_isHungry[n] = 1;</action>
|
|
|
|
<choice_glyph conn="20,13,4,-1,5,10">
|
|
|
|
<action box="1,5,6,2"/>
|
|
|
|
</choice_glyph>
|
|
|
|
</choice>
|
|
|
|
<tran_glyph conn="3,13,3,-1,17">
|
|
|
|
<action box="0,-2,8,2"/>
|
|
|
|
</tran_glyph>
|
|
|
|
</tran>
|
|
|
|
<tran trig="DONE">
|
|
|
|
<action>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]));
|
|
|
|
|
2012-12-10 16:01:54 -05:00
|
|
|
BSP_displayPhilStat(n, "thinking");
|
2012-08-14 18:00:48 -04:00
|
|
|
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);
|
2012-12-10 16:01:54 -05:00
|
|
|
BSP_displayPhilStat(m, "eating ");
|
2012-08-14 18:00:48 -04:00
|
|
|
}
|
|
|
|
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);
|
2012-12-10 16:01:54 -05:00
|
|
|
BSP_displayPhilStat(m, "eating ");
|
2012-08-14 18:00:48 -04:00
|
|
|
}</action>
|
|
|
|
<tran_glyph conn="3,23,3,-1,17">
|
|
|
|
<action box="0,-2,6,2"/>
|
|
|
|
</tran_glyph>
|
|
|
|
</tran>
|
|
|
|
<state_glyph node="3,6,37,34"/>
|
|
|
|
</state>
|
|
|
|
<state_diagram size="46,43"/>
|
|
|
|
</statechart>
|
|
|
|
</class>
|
|
|
|
<attribute name="AO_Philo[N_PHILO]" type="QActive * const" visibility="0x00" properties="0x00"/>
|
|
|
|
<attribute name="AO_Table" type="QActive * const" visibility="0x00" properties="0x00"/>
|
|
|
|
</package>
|
2012-12-10 16:01:54 -05:00
|
|
|
<directory name=".">
|
2012-08-14 18:00:48 -04:00
|
|
|
<file name="dpp.h">
|
|
|
|
<text>#ifndef dpp_h
|
|
|
|
#define dpp_h
|
|
|
|
|
2012-12-10 16:01:54 -05:00
|
|
|
using namespace QP;
|
|
|
|
|
2012-08-14 18:00:48 -04:00
|
|
|
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</text>
|
|
|
|
</file>
|
|
|
|
<file name="philo.cpp">
|
|
|
|
<text>#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)
|
|
|
|
</text>
|
|
|
|
</file>
|
|
|
|
<file name="table.cpp">
|
|
|
|
<text>#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)</text>
|
|
|
|
</file>
|
2012-12-10 16:01:54 -05:00
|
|
|
</directory>
|
2012-08-14 18:00:48 -04:00
|
|
|
</model>
|