338 lines
11 KiB
Plaintext
Raw Normal View History

2017-11-12 21:35:04 -05:00
<?xml version="1.0" encoding="UTF-8"?>
<package name="Cont" stereotype="0x02" namespace="DPP::">
<class name="TableEvt" superclass="qpcpp::QEvt">
<attribute name="philo" type="DPP::Philo *" visibility="0x00" properties="0x00"/>
</class>
<class name="CompTimeEvt" superclass="qpcpp::QTimeEvt">
<documentation>Specialized time event for components. The time evnet can be owned by a component and can dispatch itself to the component.</documentation>
<attribute name="m_comp" type="QP::QHsm *" visibility="0x00" properties="0x00"/>
<operation name="CompTimeEvt" type="" visibility="0x00" properties="0x00">
<documentation>The constructor to initialize a Component Time Event.
When creating a time event, you must commit it to a specific active object 'act', event signal 'sig', and tick rate 'tickRate'. You cannot change these attributes later.</documentation>
<parameter name="act" type="QP::QActive *"/>
<parameter name="comp" type="QP::QHsm *"/>
<parameter name="sig" type="enum_t const"/>
<parameter name="tickRate" type="uint_fast8_t const"/>
<code> : QTimeEvt(act, sig, tickRate)
m_comp = comp;</code>
</operation>
<operation name="dispatchToComp" type="void" visibility="0x00" properties="0x0a">
<code>m_comp-&gt;dispatch(this);</code>
</operation>
</class>
<class name="Table" superclass="qpcpp::QActive">
<attribute name="m_philo[N_PHILO]" type="Philo" visibility="0x02" properties="0x00">
<documentation>Embedded component state machine objects</documentation>
</attribute>
<attribute name="m_fork[N_PHILO]" type="uint8_t" visibility="0x02" properties="0x00"/>
<attribute name="m_isHungry[N_PHILO]" type="bool" visibility="0x02" properties="0x00"/>
<operation name="Table" type="" visibility="0x00" properties="0x00">
<code> : QActive(Q_STATE_CAST(&amp;Table::initial))
for (uint8_t n = 0U; n &lt; N_PHILO; ++n) {
m_fork[n] = FREE;
m_isHungry[n] = false;
}</code>
</operation>
<statechart>
<initial target="../1/3">
<action>(void)e; // suppress the compiler warning about unused parameter
QS_OBJ_DICTIONARY(&amp;l_table);
QS_FUN_DICTIONARY(&amp;Table::initial);
QS_FUN_DICTIONARY(&amp;Table::active);
QS_FUN_DICTIONARY(&amp;Table::serving);
QS_FUN_DICTIONARY(&amp;Table::paused);
QS_SIG_DICTIONARY(DONE_SIG, (void *)0); // global signals
QS_SIG_DICTIONARY(EAT_SIG, (void *)0);
QS_SIG_DICTIONARY(PAUSE_SIG, (void *)0);
QS_SIG_DICTIONARY(SERVE_SIG, (void *)0);
QS_SIG_DICTIONARY(TEST_SIG, (void *)0);
QS_SIG_DICTIONARY(TIMEOUT_SIG, me); // signal just for Table
QS_SIG_DICTIONARY(HUNGRY_SIG, me); // signal just for Table
me-&gt;subscribe(PAUSE_SIG);
me-&gt;subscribe(SERVE_SIG);
me-&gt;subscribe(TEST_SIG);
for (uint8_t n = 0U; n &lt; N_PHILO; ++n) {
me-&gt;m_philo[n].init(); // top-most initial tran.
me-&gt;m_fork[n] = FREE;
me-&gt;m_isHungry[n] = false;
BSP::displayPhilStat(n, THINKING);
}</action>
<initial_glyph conn="3,3,5,1,45,23,-10">
<action box="0,-2,6,2"/>
</initial_glyph>
</initial>
<state name="active">
<tran trig="TIMEOUT">
<action>Q_EVT_CAST(CompTimeEvt)-&gt;dispatchToComp();</action>
<tran_glyph conn="2,11,3,-1,14">
<action box="0,-2,11,4"/>
</tran_glyph>
</tran>
<tran trig="EAT">
<action>Q_ERROR();</action>
<tran_glyph conn="2,15,3,-1,14">
<action box="0,-2,10,4"/>
</tran_glyph>
</tran>
<tran trig="TEST">
<tran_glyph conn="2,20,3,-1,14">
<action box="0,-2,10,2"/>
</tran_glyph>
</tran>
<state name="serving">
<entry brief="give pending permitions to eat">for (uint8_t n = 0U; n &lt; N_PHILO; ++n) { // give permissions to eat...
if (me-&gt;m_isHungry[n]
&amp;&amp; (me-&gt;m_fork[LEFT(n)] == FREE)
&amp;&amp; (me-&gt;m_fork[n] == FREE))
{
me-&gt;m_fork[LEFT(n)] = USED;
me-&gt;m_fork[n] = USED;
// synchronoulsy dispatch EAT event to the Philo component
TableEvt evt;
evt.sig = EAT_SIG;
evt.philo = &amp;me-&gt;m_philo[n];
me-&gt;m_philo[n].dispatch(&amp;evt);
me-&gt;m_isHungry[n] = false;
BSP::displayPhilStat(n, EATING);
}
}</entry>
<tran trig="HUNGRY">
<action>// find the index of the Philo from the event
uint8_t n = (Q_EVT_CAST(TableEvt)-&gt;philo - &amp;me-&gt;m_philo[0]);
// philo 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, HUNGRY);
uint8_t m = LEFT(n);</action>
<choice>
<guard brief="both free">(me-&gt;m_fork[m] == FREE) &amp;&amp; (me-&gt;m_fork[n] == FREE)</guard>
<action>me-&gt;m_fork[m] = USED;
me-&gt;m_fork[n] = USED;
// synchronoulsy dispatch EAT event to the Philo component
TableEvt evt;
evt.sig = EAT_SIG;
evt.philo = &amp;me-&gt;m_philo[n];
me-&gt;m_philo[n].dispatch(&amp;evt);
BSP::displayPhilStat(n, EATING);</action>
<choice_glyph conn="19,31,5,-1,10">
<action box="1,0,10,2"/>
</choice_glyph>
</choice>
<choice>
<guard>else</guard>
<action>me-&gt;m_isHungry[n] = true;</action>
<choice_glyph conn="19,31,4,-1,5,10">
<action box="1,5,6,2"/>
</choice_glyph>
</choice>
<tran_glyph conn="4,31,3,-1,15">
<action box="0,-2,8,2"/>
</tran_glyph>
</tran>
<tran trig="DONE">
<action>// find the index of the Philo from the event
uint8_t n = (Q_EVT_CAST(TableEvt)-&gt;philo - &amp;me-&gt;m_philo[0]);
// philo 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, THINKING);
uint8_t 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] = FREE;
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] = USED;
me-&gt;m_fork[m] = USED;
me-&gt;m_isHungry[m] = false;
// synchronoulsy dispatch EAT event to the Philo component
TableEvt evt;
evt.sig = EAT_SIG;
evt.philo = &amp;me-&gt;m_philo[m];
me-&gt;m_philo[m].dispatch(&amp;evt);
BSP::displayPhilStat(m, EATING);
}
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] = USED;
me-&gt;m_fork[n] = USED;
me-&gt;m_isHungry[m] = false;
// synchronoulsy dispatch EAT event to the Philo component
TableEvt evt;
evt.sig = EAT_SIG;
evt.philo = &amp;me-&gt;m_philo[m];
me-&gt;m_philo[m].dispatch(&amp;evt);
BSP::displayPhilStat(m, EATING);
}</action>
<tran_glyph conn="4,39,3,-1,15">
<action box="0,-2,6,2"/>
</tran_glyph>
</tran>
<tran trig="EAT">
<action>Q_ERROR();</action>
<tran_glyph conn="4,42,3,-1,15">
<action box="0,-2,12,4"/>
</tran_glyph>
</tran>
<tran trig="PAUSE" target="../../4">
<tran_glyph conn="4,46,3,1,37,6,-3">
<action box="0,-2,7,2"/>
</tran_glyph>
</tran>
<state_glyph node="4,24,34,24">
<entry box="1,2,27,2"/>
</state_glyph>
</state>
<state name="paused">
<entry>BSP::displayPaused(1U);</entry>
<exit>BSP::displayPaused(0U);</exit>
<tran trig="SERVE" target="../../3">
<tran_glyph conn="4,62,3,1,39,-29,-5">
<action box="0,-2,12,2"/>
</tran_glyph>
</tran>
<tran trig="HUNGRY">
<action>// find the index of the Philo from the event
uint8_t n = (Q_EVT_CAST(TableEvt)-&gt;philo - &amp;me-&gt;m_philo[0]);
// philo ID must be in range and he must be not hungry
Q_ASSERT((n &lt; N_PHILO) &amp;&amp; (!me-&gt;m_isHungry[n]));
me-&gt;m_isHungry[n] = true;
BSP::displayPhilStat(n, HUNGRY);</action>
<tran_glyph conn="4,65,3,-1,15">
<action box="0,-2,9,2"/>
</tran_glyph>
</tran>
<tran trig="DONE">
<action>// find the index of the Philo from the event
uint8_t n = (Q_EVT_CAST(TableEvt)-&gt;philo - &amp;me-&gt;m_philo[0]);
// philo 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, THINKING);
uint8_t 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] = FREE;
me-&gt;m_fork[n] = FREE;</action>
<tran_glyph conn="4,68,3,-1,15">
<action box="0,-2,6,2"/>
</tran_glyph>
</tran>
<state_glyph node="4,50,34,20">
<entry box="1,2,18,4"/>
<exit box="1,6,18,4"/>
</state_glyph>
</state>
<state_glyph node="2,5,44,67"/>
</state>
<state_diagram size="50,74"/>
</statechart>
</class>
<attribute name="AO_Table" type="QP::QActive * const" visibility="0x00" properties="0x00"/>
<directory name=".">
<file name="dpp.h">
<text>#ifndef dpp_h
#define dpp_h
namespace DPP {
enum DPPSignals {
EAT_SIG = QP::Q_USER_SIG, // published by Table to let a philosopher eat
DONE_SIG, // published by Philosopher 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
HUNGRY_SIG, // posted direclty to Table from hungry Philo
TIMEOUT_SIG, // used by the component time events
MAX_SIG // the last signal
};
class Philo; // forward declaration
} // namespace DPP
enum {
N_PHILO = 5 // number of Philos
};
$declare(Cont::CompTimeEvt)
$declare(Cont::AO_Table)
$declare(Comp::Philo)
$declare(Cont::TableEvt)
#endif // dpp_h</text>
</file>
<file name="table.cpp">
<text>#include &quot;qpcpp.h&quot;
#include &quot;dpp.h&quot;
#include &quot;bsp.h&quot;
Q_DEFINE_THIS_FILE
// Active object class -------------------------------------------------------
$declare(Cont::Table)
namespace DPP {
// helper function to provide the RIGHT neighbour of a Philo[n]
inline uint8_t RIGHT(uint8_t const n) {
return static_cast&lt;uint8_t&gt;((n + (N_PHILO - 1U)) % N_PHILO);
}
// helper function to provide the LEFT neighbour of a Philo[n]
inline uint8_t LEFT(uint8_t const n) {
return static_cast&lt;uint8_t&gt;((n + 1U) % N_PHILO);
}
static uint8_t const FREE = static_cast&lt;uint8_t&gt;(0);
static uint8_t const USED = static_cast&lt;uint8_t&gt;(1);
static char_t const * const THINKING = &amp;&quot;thinking&quot;[0];
static char_t const * const HUNGRY = &amp;&quot;hungry &quot;[0];
static char_t const * const EATING = &amp;&quot;eating &quot;[0];
// Local objects -------------------------------------------------------------
static Table l_table; // the single instance of the Table active object
// Global-scope objects ------------------------------------------------------
QP::QActive * const AO_Table = &amp;l_table; // &quot;opaque&quot; AO pointer
} // namespace DPP
//............................................................................
$define(Cont::CompTimeEvt)
$define(Cont::Table)</text>
</file>
</directory>
</package>