Quantum Leaps 56d4f80c47 5.8.0
2016-12-01 10:31:49 -05:00

591 lines
24 KiB
XML

<?xml version="1.0" encoding="UTF-8"?>
<model version="4.0.0" links="0">
<documentation>Dining Philosopher Problem example for Qt with GUI</documentation>
<framework name="qpcpp"/>
<package name="Qt-port" stereotype="0x00" namespace="QP::">
<class name="GuiQActive" superclass="qpcpp::QActive">
<operation name="GuiQActive" type="QActive(initial)" visibility="0x00" properties="0x00">
<parameter name="initial" type="QStateHandler"/>
</operation>
<operation name="start" type="void" visibility="0x00" properties="0x00">
<documentation>Starts execution of an active object and registers the object with the framework. This function is strongly OS-dependent and must be defined in the QP port to a particular platform.
The function takes six arguments:
'prio' is the priority of the active object. QP allows you to start up to 63 active objects, each one having a *unique* priority number between 1 and 63 inclusive, where higher numerical values correspond to higher priority (urgency) of the active object relative to the others.
'qSto[]' and 'qLen' arguments are the storage and size of the event queue used by this active object.
'stkSto' and 'stkSize' are the stack storage and size in bytes. Please note that a per-active object stack is used only when the underlying OS requies it. If the stack is not required, or the underlying OS allocates the stack internally, the stkSto should be NULL and/or stkSize should be 0.
'ie' is an optional initialization event that can be used to pass additional startup data to the active object. (Pass NULL if your active object does not expect the initialization event).</documentation>
<parameter name="prio" type="uint8_t"/>
<parameter name="qSto[]" type="QEvt const *"/>
<parameter name="qLen" type="uint32_t"/>
<parameter name="stkSto" type="void *"/>
<parameter name="stkSize" type="uint32_t"/>
<parameter name="ie" type="QEvt const *"/>
<code>// Example:
static Table l_table; // Table active object instance
static QEvt const *l_tableQueueSto[N]; // storage for Table queue
static int l_tableStk[256]; // storage for the stack for Table AO
. . .
int main() {
TableEvt ie; // initialization event for the Table AO
. . .
ie.philNum = n; // build the initialization event
. . .
l_table.start(
6, // unique priority (1..QF_MAX_ACTIVE)
l_tableQueueSto, // event queue of the active object
Q_DIM(l_tableQueueSto),// the depth of the event queue
l_tableStk, // the stack of the acitve object (optional)
sizeof(l_tableStk), // the size of the stack in bytes (optional)
&amp;ie); // initialization event (optional)
. . .
}</code>
</operation>
<operation name="postFIFO" type="void" visibility="0x00" properties="0x00">
<documentation>Posts an event e directly to the event queue of the acitve object me using the First-In-First-Out (FIFO) policy.
Direct event posting is the simplest asynchronous communication method available in QP.
NOTE: Direct event posting should not be confused with direct event dispatching. In contrast to asynchronous event posting through event queues, direct event dispatching is synchronous. Direct event dispatching occurs when you call QHsm::dispatch() or QFsm::dispatch() function.</documentation>
<parameter name="e" type="QEvt const *"/>
<code>// Example:
extern QActive *AO_Table;
. . .
pe = Q_NEW(TableEvt, HUNGRY_SIG); // dynamically allocate event
pe-&gt;philNum = me-&gt;num;
AO_Table-&gt;postFIFO(pe); // &lt;==</code>
</operation>
<operation name="postLIFO" type="void" visibility="0x00" properties="0x00">
<documentation>Posts an event e directly to the event queue of the acitve object me using the Last-In-First-Out (LIFO) policy.
Direct event posting is the simplest asynchronous communication method available in QP.
NOTE: You should be very careful with the LIFO (Last In First Out) policy, because it *reverses* the order of events in the queue. Typically, the QActive_postLIFO() operation shuould be only used for self-posting of events as reminders (see the &quot;Reminder&quot; state pattern) for continuing a processing. The postLIFO() operation is also used in the QActive::recall() operation.
NOTE: Direct event posting should not be confused with direct event dispatching. In contrast to asynchronous event posting through event queues, direct event dispatching is synchronous. Direct event dispatching occurs when you call QHsm::dispatch() or QFsm::dispatch() function.</documentation>
<parameter name="e" type="QEvt const *"/>
<code>// Example:
. . .
pe = Q_NEW(TableEvt, HUNGRY_SIG); // dynamically allocate event
pe-&gt;philNum = me-&gt;num;
. . .
me-&gt;postLIFO(pe); // &lt;==</code>
</operation>
</class>
<class name="GuiQMActive" superclass="qpcpp::QMActive">
<operation name="GuiQMActive" type="QMActive(initial)" visibility="0x00" properties="0x00">
<parameter name="initial" type="QStateHandler"/>
</operation>
<operation name="start" type="void" visibility="0x00" properties="0x00">
<documentation>Starts execution of an active object and registers the object with the framework. This function is strongly OS-dependent and must be defined in the QP port to a particular platform.
The function takes six arguments:
'prio' is the priority of the active object. QP allows you to start up to 63 active objects, each one having a *unique* priority number between 1 and 63 inclusive, where higher numerical values correspond to higher priority (urgency) of the active object relative to the others.
'qSto[]' and 'qLen' arguments are the storage and size of the event queue used by this active object.
'stkSto' and 'stkSize' are the stack storage and size in bytes. Please note that a per-active object stack is used only when the underlying OS requies it. If the stack is not required, or the underlying OS allocates the stack internally, the stkSto should be NULL and/or stkSize should be 0.
'ie' is an optional initialization event that can be used to pass additional startup data to the active object. (Pass NULL if your active object does not expect the initialization event).</documentation>
<parameter name="prio" type="uint8_t"/>
<parameter name="qSto[]" type="QEvt const *"/>
<parameter name="qLen" type="uint32_t"/>
<parameter name="stkSto" type="void *"/>
<parameter name="stkSize" type="uint32_t"/>
<parameter name="ie" type="QEvt const *"/>
<code>// Example:
static Table l_table; // Table active object instance
static QEvt const *l_tableQueueSto[N]; // storage for Table queue
static int l_tableStk[256]; // storage for the stack for Table AO
. . .
int main() {
TableEvt ie; // initialization event for the Table AO
. . .
ie.philNum = n; // build the initialization event
. . .
l_table.start(
6, // unique priority (1..QF_MAX_ACTIVE)
l_tableQueueSto, // event queue of the active object
Q_DIM(l_tableQueueSto),// the depth of the event queue
l_tableStk, // the stack of the acitve object (optional)
sizeof(l_tableStk), // the size of the stack in bytes (optional)
&amp;ie); // initialization event (optional)
. . .
}</code>
</operation>
<operation name="postFIFO" type="void" visibility="0x00" properties="0x00">
<documentation>Posts an event e directly to the event queue of the acitve object me using the First-In-First-Out (FIFO) policy.
Direct event posting is the simplest asynchronous communication method available in QP.
NOTE: Direct event posting should not be confused with direct event dispatching. In contrast to asynchronous event posting through event queues, direct event dispatching is synchronous. Direct event dispatching occurs when you call QHsm::dispatch() or QFsm::dispatch() function.</documentation>
<parameter name="e" type="QEvt const *"/>
<code>// Example:
extern QActive *AO_Table;
. . .
pe = Q_NEW(TableEvt, HUNGRY_SIG); // dynamically allocate event
pe-&gt;philNum = me-&gt;num;
AO_Table-&gt;postFIFO(pe); // &lt;==</code>
</operation>
<operation name="postLIFO" type="void" visibility="0x00" properties="0x00">
<documentation>Posts an event e directly to the event queue of the acitve object me using the Last-In-First-Out (LIFO) policy.
Direct event posting is the simplest asynchronous communication method available in QP.
NOTE: You should be very careful with the LIFO (Last In First Out) policy, because it *reverses* the order of events in the queue. Typically, the QActive_postLIFO() operation shuould be only used for self-posting of events as reminders (see the &quot;Reminder&quot; state pattern) for continuing a processing. The postLIFO() operation is also used in the QActive::recall() operation.
NOTE: Direct event posting should not be confused with direct event dispatching. In contrast to asynchronous event posting through event queues, direct event dispatching is synchronous. Direct event dispatching occurs when you call QHsm::dispatch() or QFsm::dispatch() function.</documentation>
<parameter name="e" type="QEvt const *"/>
<code>// Example:
. . .
pe = Q_NEW(TableEvt, HUNGRY_SIG); // dynamically allocate event
pe-&gt;philNum = me-&gt;num;
. . .
me-&gt;postLIFO(pe); // &lt;==</code>
</operation>
</class>
</package>
<package name="Events" stereotype="0x01" namespace="DPP::">
<class name="TableEvt" superclass="qpcpp::QEvt">
<attribute name="philoNum" type="uint8_t" visibility="0x00" properties="0x00"/>
<operation name="TableEvt" type="QEvt(sig), philoNum(n)" visibility="0x00" properties="0x02">
<parameter name="sig" type="QP::QSignal"/>
<parameter name="n" type="uint8_t"/>
</operation>
</class>
</package>
<package name="AOs" stereotype="0x02" namespace="DPP::">
<class name="Philo" superclass="qpcpp::QActive">
<attribute name="m_timeEvt" type="QP::QTimeEvt" visibility="0x02" properties="0x00"/>
<operation name="Philo" type="" visibility="0x00" properties="0x00">
<code> : QActive(Q_STATE_CAST(&amp;Philo::initial)),
m_timeEvt(this, TIMEOUT_SIG, 0U)</code>
</operation>
<statechart>
<initial target="../1">
<action>static bool registered = false; // starts off with 0, per C-standard
(void)e; // suppress the compiler warning about unused parameter
if (!registered) {
registered = true;
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);
}
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>
<exit>(void)me-&gt;m_timeEvt.disarm();</exit>
<tran trig="TIMEOUT" target="../../2">
<tran_glyph conn="2,14,3,1,20,11,-3">
<action box="0,-2,6,2"/>
</tran_glyph>
</tran>
<tran trig="EAT, DONE">
<action>/* EAT or DONE must be for other Philos than this one */
Q_ASSERT(Q_EVT_CAST(TableEvt)-&gt;philoNum != PHILO_ID(me));</action>
<tran_glyph conn="2,18,3,-1,13">
<action box="0,-2,14,2"/>
</tran_glyph>
</tran>
<state_glyph node="2,5,17,16">
<entry box="1,2,5,2"/>
<exit box="1,4,5,2"/>
</state_glyph>
</state>
<state name="hungry">
<entry>AO_Table-&gt;POST(Q_NEW(TableEvt, HUNGRY_SIG, PHILO_ID(me)), me);</entry>
<tran trig="EAT">
<choice target="../../../3">
<guard>Q_EVT_CAST(TableEvt)-&gt;philoNum == PHILO_ID(me)</guard>
<choice_glyph conn="15,30,5,1,7,13,-3">
<action box="1,0,19,4"/>
</choice_glyph>
</choice>
<tran_glyph conn="2,30,3,-1,13">
<action box="0,-2,14,2"/>
</tran_glyph>
</tran>
<tran trig="DONE">
<action>/* DONE must be for other Philos than this one */
Q_ASSERT(Q_EVT_CAST(TableEvt)-&gt;philoNum != PHILO_ID(me));</action>
<tran_glyph conn="2,36,3,-1,14">
<action box="0,-2,14,2"/>
</tran_glyph>
</tran>
<state_glyph node="2,23,17,16">
<entry box="1,2,5,2"/>
</state_glyph>
</state>
<state name="eating">
<entry>me-&gt;m_timeEvt.postIn(me, think_time());</entry>
<exit>QP::QF::PUBLISH(Q_NEW(TableEvt, DONE_SIG, PHILO_ID(me)), me);
(void)me-&gt;m_timeEvt.disarm();</exit>
<tran trig="TIMEOUT" target="../../1">
<tran_glyph conn="2,51,3,1,22,-41,-5">
<action box="0,-2,6,2"/>
</tran_glyph>
</tran>
<tran trig="EAT, DONE">
<action>/* EAT or DONE must be for other Philos than this one */
Q_ASSERT(Q_EVT_CAST(TableEvt)-&gt;philoNum != PHILO_ID(me));</action>
<tran_glyph conn="2,55,3,-1,13">
<action box="0,-2,14,2"/>
</tran_glyph>
</tran>
<state_glyph node="2,41,17,18">
<entry box="1,2,5,2"/>
<exit box="1,4,5,2"/>
</state_glyph>
</state>
<state_diagram size="37,61"/>
</statechart>
</class>
<class name="Table" superclass="Qt-port::GuiQActive">
<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> : GuiQActive(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/2">
<action>(void)e; // suppress the compiler warning about unused parameter
QS_OBJ_DICTIONARY(&amp;l_table);
QS_FUN_DICTIONARY(&amp;QP::QHsm::top);
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(TERMINATE_SIG, (void *)0);
QS_SIG_DICTIONARY(HUNGRY_SIG, me); // signal just for Table
me-&gt;subscribe(DONE_SIG);
me-&gt;subscribe(PAUSE_SIG);
me-&gt;subscribe(TERMINATE_SIG);
for (uint8_t n = 0U; n &lt; N_PHILO; ++n) {
me-&gt;m_fork[n] = FREE;
me-&gt;m_isHungry[n] = false;
BSP_displayPhilStat(n, THINKING);
}</action>
<initial_glyph conn="3,3,5,1,44,18,-9">
<action box="0,-2,6,2"/>
</initial_glyph>
</initial>
<state name="active">
<tran trig="TERMINATE">
<action>BSP_terminate(0);</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>
<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;
QP::QF::PUBLISH(Q_NEW(TableEvt, EAT_SIG, n), me);
me-&gt;m_isHungry[n] = false;
BSP_displayPhilStat(n, EATING);
}
}</entry>
<tran trig="HUNGRY">
<action>uint8_t n = Q_EVT_CAST(TableEvt)-&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, 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;
QP::QF::PUBLISH(Q_NEW(TableEvt, EAT_SIG, n), me);
BSP_displayPhilStat(n, EATING);</action>
<choice_glyph conn="19,26,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,26,4,-1,5,10">
<action box="1,5,6,2"/>
</choice_glyph>
</choice>
<tran_glyph conn="4,26,3,-1,15">
<action box="0,-2,8,2"/>
</tran_glyph>
</tran>
<tran trig="DONE">
<action>uint8_t n = Q_EVT_CAST(TableEvt)-&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, 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;
QP::QF::PUBLISH(Q_NEW(TableEvt, EAT_SIG, m), me);
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;
QP::QF::PUBLISH(Q_NEW(TableEvt, EAT_SIG, m), me);
BSP_displayPhilStat(m, EATING);
}</action>
<tran_glyph conn="4,34,3,-1,15">
<action box="0,-2,6,2"/>
</tran_glyph>
</tran>
<tran trig="EAT">
<action>Q_ERROR();</action>
<tran_glyph conn="4,37,3,-1,15">
<action box="0,-2,12,4"/>
</tran_glyph>
</tran>
<tran trig="PAUSE" target="../../3">
<tran_glyph conn="4,41,3,1,37,6,-3">
<action box="0,-2,7,2"/>
</tran_glyph>
</tran>
<state_glyph node="4,19,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="PAUSE" target="../../2">
<tran_glyph conn="4,57,3,1,39,-20,-5">
<action box="0,-2,7,2"/>
</tran_glyph>
</tran>
<tran trig="HUNGRY">
<action>uint8_t n = Q_EVT_CAST(TableEvt)-&gt;philoNum;
// 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,60,3,-1,15">
<action box="0,-2,6,2"/>
</tran_glyph>
</tran>
<tran trig="DONE">
<action>uint8_t n = Q_EVT_CAST(TableEvt)-&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, 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,63,3,-1,15">
<action box="0,-2,6,2"/>
</tran_glyph>
</tran>
<state_glyph node="4,45,34,20">
<entry box="1,2,18,4"/>
<exit box="1,6,18,4"/>
</state_glyph>
</state>
<state_glyph node="2,5,43,62"/>
</state>
<state_diagram size="49,69"/>
</statechart>
</class>
<attribute name="AO_Philo[N_PHILO]" type="QP::QActive * const" visibility="0x00" properties="0x00"/>
<attribute name="AO_Table" type="QP::QActive * const" visibility="0x00" properties="0x00"/>
</package>
<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 serving the forks
SERVE_SIG, // published by BSP to re-start serving the forks
TERMINATE_SIG, // published by BSP to terminate the application
MAX_PUB_SIG, // the last published signal
HUNGRY_SIG, // posted direclty to Table from hungry Philo
MAX_SIG // the last signal
};
} // namespace DPP
$declare(Events::TableEvt)
// number of philosophers
#define N_PHILO ((uint8_t)5)
$declare(AOs::AO_Philo[N_PHILO])
$declare(AOs::AO_Table)
#endif // dpp_h</text>
</file>
<file name="philo.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(AOs::Philo)
namespace DPP {
// Local objects -------------------------------------------------------------
static Philo l_philo[N_PHILO]; // storage for all Philos
// helper function to provide a randomized think time for Philos
inline QP::QTimeEvtCtr think_time() {
return static_cast&lt;QP::QTimeEvtCtr&gt;((BSP_random() % BSP_TICKS_PER_SEC)
+ (BSP_TICKS_PER_SEC/2U));
}
// helper function to provide a randomized eat time for Philos
inline QP::QTimeEvtCtr eat_time() {
return static_cast&lt;QP::QTimeEvtCtr&gt;((BSP_random() % BSP_TICKS_PER_SEC)
+ BSP_TICKS_PER_SEC);
}
// helper function to provide the ID of Philo &quot;me&quot;
inline uint8_t PHILO_ID(Philo const * const me) {
return static_cast&lt;uint8_t&gt;(me - l_philo);
}
enum InternalSignals { // internal signals
TIMEOUT_SIG = MAX_SIG
};
// Global objects ------------------------------------------------------------
QP::QActive * const AO_Philo[N_PHILO] = { // &quot;opaque&quot; pointers to Philo AO
&amp;l_philo[0],
&amp;l_philo[1],
&amp;l_philo[2],
&amp;l_philo[3],
&amp;l_philo[4]
};
} // namespace DPP
// Philo definition ----------------------------------------------------------
$define(AOs::Philo)</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(AOs::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(AOs::Table)</text>
</file>
</directory>
</model>