Quantum Leaps e4269e3b15 4.5.03
2012-12-10 16:01:54 -05:00

291 lines
9.7 KiB
XML

<?xml version="1.0" encoding="UTF-8"?>
<model version="2.2.03">
<documentation>Dining Philosopher Problem example</documentation>
<framework name="qpcpp"/>
<package name="Events" stereotype="0x01">
<class name="TableEvt" superclass="qpcpp::QEvt">
<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)&amp;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(&amp;l_philo[0]);
QS_OBJ_DICTIONARY(&amp;l_philo[0].m_timeEvt);
QS_OBJ_DICTIONARY(&amp;l_philo[1]);
QS_OBJ_DICTIONARY(&amp;l_philo[1].m_timeEvt);
QS_OBJ_DICTIONARY(&amp;l_philo[2]);
QS_OBJ_DICTIONARY(&amp;l_philo[2].m_timeEvt);
QS_OBJ_DICTIONARY(&amp;l_philo[3]);
QS_OBJ_DICTIONARY(&amp;l_philo[3].m_timeEvt);
QS_OBJ_DICTIONARY(&amp;l_philo[4]);
QS_OBJ_DICTIONARY(&amp;l_philo[4].m_timeEvt);
QS_FUN_DICTIONARY(&amp;Philo::initial);
QS_FUN_DICTIONARY(&amp;Philo::thinking);
QS_FUN_DICTIONARY(&amp;Philo::hungry);
QS_FUN_DICTIONARY(&amp;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-&gt;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-&gt;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-&gt;philoNum = PHILO_ID(me);
AO_Table-&gt;POST(pe, me);</entry>
<tran trig="EAT">
<choice target="../../../3">
<guard>((TableEvt const *)e)-&gt;philoNum == PHILO_ID(me)</guard>
<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-&gt;m_timeEvt.postIn(me, EAT_TIME);</entry>
<exit>TableEvt *pe = Q_NEW(TableEvt, DONE_SIG);
pe-&gt;philoNum = PHILO_ID(me);
AO_Table-&gt;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)&amp;Table::initial)" visibility="0x00" properties="0x00">
<code>for (uint8_t n = 0; n &lt; 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(&amp;l_table);
QS_FUN_DICTIONARY(&amp;QHsm::top);
QS_FUN_DICTIONARY(&amp;Table::initial);
QS_FUN_DICTIONARY(&amp;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-&gt;subscribe(DONE_SIG);
//me-&gt;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)-&gt;philoNum;
// phil ID must be in range and he must be not hungry
Q_ASSERT((n &lt; N_PHILO) &amp;&amp; (!me-&gt;m_isHungry[n]));
BSP_displayPhilStat(n, &quot;hungry &quot;);
uint8_t m = LEFT(n);</action>
<choice>
<guard>(me-&gt;m_fork[m] == FREE) &amp;&amp; (me-&gt;m_fork[n] == FREE)</guard>
<action>me-&gt;m_fork[m] = me-&gt;m_fork[n] = USED;
TableEvt *pe = Q_NEW(TableEvt, EAT_SIG);
pe-&gt;philoNum = n;
AO_Philo[n]-&gt;POST(pe, me);
BSP_displayPhilStat(n, &quot;eating &quot;);</action>
<choice_glyph conn="20,13,5,-1,10">
<action box="1,0,18,4"/>
</choice_glyph>
</choice>
<choice>
<guard>else</guard>
<action>me-&gt;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)-&gt;philoNum;
// phil ID must be in range and he must be not hungry
Q_ASSERT((n &lt; N_PHILO) &amp;&amp; (!me-&gt;m_isHungry[n]));
BSP_displayPhilStat(n, &quot;thinking&quot;);
m = LEFT(n);
// both forks of Phil[n] must be used
Q_ASSERT((me-&gt;m_fork[n] == USED) &amp;&amp; (me-&gt;m_fork[m] == USED));
me-&gt;m_fork[m] = me-&gt;m_fork[n] = FREE;
m = RIGHT(n); // check the right neighbor
if (me-&gt;m_isHungry[m] &amp;&amp; (me-&gt;m_fork[m] == FREE)) {
me-&gt;m_fork[n] = me-&gt;m_fork[m] = USED;
me-&gt;m_isHungry[m] = 0;
pe = Q_NEW(TableEvt, EAT_SIG);
pe-&gt;philoNum = m;
AO_Philo[m]-&gt;POST(pe, me);
BSP_displayPhilStat(m, &quot;eating &quot;);
}
m = LEFT(n); // check the left neighbor
n = LEFT(m); // left fork of the left neighbor
if (me-&gt;m_isHungry[m] &amp;&amp; (me-&gt;m_fork[n] == FREE)) {
me-&gt;m_fork[m] = me-&gt;m_fork[n] = USED;
me-&gt;m_isHungry[m] = 0;
pe = Q_NEW(TableEvt, EAT_SIG);
pe-&gt;philoNum = m;
AO_Philo[m]-&gt;POST(pe, me);
BSP_displayPhilStat(m, &quot;eating &quot;);
}</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>
<directory name=".">
<file name="dpp.h">
<text>#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</text>
</file>
<file name="philo.cpp">
<text>#include &quot;qp_port.h&quot;
#include &quot;dpp.h&quot;
#include &quot;bsp.h&quot;
//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 &quot;me_&quot; */
#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] = { /* &quot;opaque&quot; pointers to Philo AO */
(QActive *)&amp;l_philo[0],
(QActive *)&amp;l_philo[1],
(QActive *)&amp;l_philo[2],
(QActive *)&amp;l_philo[3],
(QActive *)&amp;l_philo[4]
};
/* Philo definition --------------------------------------------------------*/
$define(AOs::Philo)
</text>
</file>
<file name="table.cpp">
<text>#include &quot;qp_port.h&quot;
#include &quot;dpp.h&quot;
#include &quot;bsp.h&quot;
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 *)&amp;l_table; /* &quot;opaque&quot; AO pointer */
/*..........................................................................*/
$define(AOs::Table)</text>
</file>
</directory>
</model>