| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456 |
- <?xml version="1.0" encoding="UTF-8"?>
- <model version="5.2.5" links="1">
- <documentation>Dining Philosopher Problem example</documentation>
- <!--${qpc}-->
- <framework name="qpc"/>
- <!--${Shared}-->
- <package name="Shared" stereotype="0x05">
- <!--${Shared::TableEvt}-->
- <class name="TableEvt" superclass="qpc::QEvt">
- <!--${Shared::TableEvt::philoNum}-->
- <attribute name="philoNum" type="uint8_t" visibility="0x00" properties="0x00"/>
- </class>
- <!--${Shared::AO_Philo[N_PHILO]}-->
- <attribute name="AO_Philo[N_PHILO]" type="QActive * const" visibility="0x00" properties="0x00">
- <documentation>/* opaque pointers to the Philo AOs */</documentation>
- <code>= {
- &Philo_inst[0].super,
- &Philo_inst[1].super,
- &Philo_inst[2].super,
- &Philo_inst[3].super,
- &Philo_inst[4].super
- };</code>
- </attribute>
- <!--${Shared::AO_Table}-->
- <attribute name="AO_Table" type="QActive * const" visibility="0x00" properties="0x00">
- <documentation>/* opaque pointer to the Table AO */</documentation>
- <code>= &Table_inst.super;</code>
- </attribute>
- <!--${Shared::Philo_ctor}-->
- <operation name="Philo_ctor" type="void" visibility="0x00" properties="0x00">
- <!--${Shared::Philo_ctor::n}-->
- <parameter name="n" type="uint8_t"/>
- <code>Philo *me = &Philo_inst[n];
- QActive_ctor(&me->super, Q_STATE_CAST(&Philo_initial));
- QTimeEvt_ctorX(&me->timeEvt, &me->super, TIMEOUT_SIG, 0U);</code>
- </operation>
- <!--${Shared::Table_ctor}-->
- <operation name="Table_ctor" type="void" visibility="0x00" properties="0x00">
- <code>Table *me = &Table_inst;
- QActive_ctor(&me->super, Q_STATE_CAST(&Table_initial));
- for (uint8_t n = 0U; n < N_PHILO; ++n) {
- me->fork[n] = FREE;
- me->isHungry[n] = 0U;
- }</code>
- </operation>
- </package>
- <!--${AOs}-->
- <package name="AOs" stereotype="0x02">
- <!--${AOs::Philo}-->
- <class name="Philo" superclass="qpc::QActive">
- <!--${AOs::Philo::inst[N_PHILO]}-->
- <attribute name="inst[N_PHILO]" type="Philo" visibility="0x00" properties="0x01"/>
- <!--${AOs::Philo::timeEvt}-->
- <attribute name="timeEvt" type="QTimeEvt" visibility="0x02" properties="0x00"/>
- <!--${AOs::Philo::SM}-->
- <statechart properties="0x01">
- <!--${AOs::Philo::SM::initial}-->
- <initial target="../1">
- <action>(void)par; /* unused parameter */
- #ifdef Q_SPY
- uint8_t n = PHILO_ID(me);
- QS_OBJ_ARR_DICTIONARY(&Philo_inst[n], n);
- QS_OBJ_ARR_DICTIONARY(&Philo_inst[n].timeEvt, n);
- #endif
- QActive_subscribe(&me->super, EAT_SIG);
- QActive_subscribe(&me->super, TEST_SIG);
- /* the following code outputs the "fun-dictionaries" only once for
- * all Philo instances, as opposed to repeat them for every instance.
- */
- static bool registered = false;
- if (!registered) {
- registered = true;
- QS_FUN_DICTIONARY(&Philo_initial);
- QS_FUN_DICTIONARY(&Philo_thinking);
- QS_FUN_DICTIONARY(&Philo_hungry);
- QS_FUN_DICTIONARY(&Philo_eating);
- }</action>
- <initial_glyph conn="2,3,5,1,20,5,-3">
- <action box="0,-2,6,2"/>
- </initial_glyph>
- </initial>
- <!--${AOs::Philo::SM::thinking}-->
- <state name="thinking">
- <entry>QTimeEvt_armX(&me->timeEvt, THINK_TIME, 0U);</entry>
- <exit>QTimeEvt_disarm(&me->timeEvt);</exit>
- <!--${AOs::Philo::SM::thinking::TIMEOUT}-->
- <tran trig="TIMEOUT" target="../../2">
- <tran_glyph conn="2,13,3,1,20,12,-3">
- <action box="0,-2,6,2"/>
- </tran_glyph>
- </tran>
- <!--${AOs::Philo::SM::thinking::EAT, DONE}-->
- <tran trig="EAT, DONE">
- <action>/* EAT or DONE must be for other Philos than this one */
- Q_ASSERT_ID(10, Q_EVT_CAST(TableEvt)->philoNum != PHILO_ID(me));</action>
- <tran_glyph conn="2,17,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,6,2"/>
- </state_glyph>
- </state>
- <!--${AOs::Philo::SM::hungry}-->
- <state name="hungry">
- <entry>TableEvt *pe = Q_NEW(TableEvt, HUNGRY_SIG);
- pe->philoNum = PHILO_ID(me);
- QACTIVE_POST(AO_Table, &pe->super, me);</entry>
- <!--${AOs::Philo::SM::hungry::EAT}-->
- <tran trig="EAT">
- <!--${AOs::Philo::SM::hungry::EAT::[Q_EVT_CAST(TableEvt)->philoNum=~}-->
- <choice target="../../../3">
- <guard>Q_EVT_CAST(TableEvt)->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>
- <!--${AOs::Philo::SM::hungry::DONE}-->
- <tran trig="DONE">
- <action>/* DONE must be for other Philos than this one */
- Q_ASSERT_ID(20, Q_EVT_CAST(TableEvt)->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>
- <!--${AOs::Philo::SM::eating}-->
- <state name="eating">
- <entry>QTimeEvt_armX(&me->timeEvt, EAT_TIME, 0U);</entry>
- <exit>TableEvt *pe = Q_NEW(TableEvt, DONE_SIG);
- pe->philoNum = PHILO_ID(me);
- QACTIVE_PUBLISH(&pe->super, &me->super);
- QTimeEvt_disarm(&me->timeEvt);</exit>
- <!--${AOs::Philo::SM::eating::TIMEOUT}-->
- <tran trig="TIMEOUT" target="../../1">
- <tran_glyph conn="2,51,3,1,22,-41,-5">
- <action box="0,-2,6,2"/>
- </tran_glyph>
- </tran>
- <!--${AOs::Philo::SM::eating::EAT, DONE}-->
- <tran trig="EAT, DONE">
- <action>/* EAT or DONE must be for other Philos than this one */
- Q_ASSERT_ID(30, Q_EVT_CAST(TableEvt)->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>
- <!--${AOs::Table}-->
- <class name="Table" superclass="qpc::QActive">
- <!--${AOs::Table::inst}-->
- <attribute name="inst" type="Table" visibility="0x00" properties="0x01">
- <documentation>The only static instance of the Table class (Singleton pattern)</documentation>
- </attribute>
- <!--${AOs::Table::fork[N_PHILO]}-->
- <attribute name="fork[N_PHILO]" type="uint8_t" visibility="0x02" properties="0x00"/>
- <!--${AOs::Table::isHungry[N_PHILO]}-->
- <attribute name="isHungry[N_PHILO]" type="uint8_t" visibility="0x02" properties="0x00"/>
- <!--${AOs::Table::SM}-->
- <statechart properties="0x03">
- <!--${AOs::Table::SM::initial}-->
- <initial target="../1/1">
- <action>(void)par; /* unused parameter */
- QS_OBJ_DICTIONARY(&Table_inst);
- QActive_subscribe(&me->super, DONE_SIG);
- QActive_subscribe(&me->super, PAUSE_SIG);
- QActive_subscribe(&me->super, SERVE_SIG);
- QActive_subscribe(&me->super, TEST_SIG);
- for (uint8_t n = 0U; n < N_PHILO; ++n) {
- me->fork[n] = FREE;
- me->isHungry[n] = 0U;
- BSP_displayPhilStat(n, "thinking");
- }</action>
- <initial_glyph conn="3,3,5,1,44,18,-9">
- <action box="0,-2,6,2"/>
- </initial_glyph>
- </initial>
- <!--${AOs::Table::SM::active}-->
- <state name="active">
- <!--${AOs::Table::SM::active::EAT}-->
- <tran trig="EAT">
- <action>Q_ERROR_ID(60);</action>
- <tran_glyph conn="2,15,3,-1,14">
- <action box="0,-2,17,4"/>
- </tran_glyph>
- </tran>
- <!--${AOs::Table::SM::active::serving}-->
- <state name="serving">
- <entry brief="give pending permissions to eat">uint8_t n;
- for (n = 0U; n < N_PHILO; ++n) { /* give permissions to eat... */
- if ((me->isHungry[n] != 0U)
- && (me->fork[LEFT(n)] == FREE)
- && (me->fork[n] == FREE))
- {
- TableEvt *te;
- me->fork[LEFT(n)] = USED;
- me->fork[n] = USED;
- te = Q_NEW(TableEvt, EAT_SIG);
- te->philoNum = n;
- QACTIVE_PUBLISH(&te->super, &me->super);
- me->isHungry[n] = 0U;
- BSP_displayPhilStat(n, "eating ");
- }
- }</entry>
- <!--${AOs::Table::SM::active::serving::HUNGRY}-->
- <tran trig="HUNGRY">
- <action>uint8_t n, m;
- n = Q_EVT_CAST(TableEvt)->philoNum;
- /* phil ID must be in range and he must be not hungry */
- Q_ASSERT_ID(40, (n < N_PHILO) && (me->isHungry[n] == 0U));
- BSP_displayPhilStat(n, "hungry ");
- m = LEFT(n);</action>
- <!--${AOs::Table::SM::active::serving::HUNGRY::[bothfree]}-->
- <choice>
- <guard brief="both free">(me->fork[m] == FREE) && (me->fork[n] == FREE)</guard>
- <action>TableEvt *pe;
- me->fork[m] = USED;
- me->fork[n] = USED;
- pe = Q_NEW(TableEvt, EAT_SIG);
- pe->philoNum = n;
- QACTIVE_PUBLISH(&pe->super, &me->super);
- BSP_displayPhilStat(n, "eating ");</action>
- <choice_glyph conn="19,26,5,-1,10">
- <action box="1,0,10,2"/>
- </choice_glyph>
- </choice>
- <!--${AOs::Table::SM::active::serving::HUNGRY::[else]}-->
- <choice>
- <guard>else</guard>
- <action>me->isHungry[n] = 1U;</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>
- <!--${AOs::Table::SM::active::serving::DONE}-->
- <tran trig="DONE">
- <action>uint8_t n, m;
- TableEvt *pe;
- n = Q_EVT_CAST(TableEvt)->philoNum;
- /* phil ID must be in range and he must be not hungry */
- Q_ASSERT_ID(50, (n < N_PHILO) && (me->isHungry[n] == 0U));
- BSP_displayPhilStat(n, "thinking");
- m = LEFT(n);
- /* both forks of Phil[n] must be used */
- Q_ASSERT_ID(51, (me->fork[n] == USED) && (me->fork[m] == USED));
- me->fork[m] = FREE;
- me->fork[n] = FREE;
- m = RIGHT(n); /* check the right neighbor */
- if ((me->isHungry[m] != 0U) && (me->fork[m] == FREE)) {
- me->fork[n] = USED;
- me->fork[m] = USED;
- me->isHungry[m] = 0U;
- pe = Q_NEW(TableEvt, EAT_SIG);
- pe->philoNum = m;
- QACTIVE_PUBLISH(&pe->super, &me->super);
- BSP_displayPhilStat(m, "eating ");
- }
- m = LEFT(n); /* check the left neighbor */
- n = LEFT(m); /* left fork of the left neighbor */
- if ((me->isHungry[m] != 0U) && (me->fork[n] == FREE)) {
- me->fork[m] = USED;
- me->fork[n] = USED;
- me->isHungry[m] = 0U;
- pe = Q_NEW(TableEvt, EAT_SIG);
- pe->philoNum = m;
- QACTIVE_PUBLISH(&pe->super, &me->super);
- BSP_displayPhilStat(m, "eating ");
- }</action>
- <tran_glyph conn="4,34,3,-1,15">
- <action box="0,-2,6,2"/>
- </tran_glyph>
- </tran>
- <!--${AOs::Table::SM::active::serving::PAUSE}-->
- <tran trig="PAUSE" target="../../2">
- <tran_glyph conn="4,40,3,1,37,7,-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>
- <!--${AOs::Table::SM::active::paused}-->
- <state name="paused">
- <entry>BSP_displayPaused(1U);</entry>
- <exit>BSP_displayPaused(0U);</exit>
- <!--${AOs::Table::SM::active::paused::SERVE}-->
- <tran trig="SERVE" target="../../1">
- <tran_glyph conn="4,57,3,1,39,-23,-5">
- <action box="0,-2,7,2"/>
- </tran_glyph>
- </tran>
- <!--${AOs::Table::SM::active::paused::HUNGRY}-->
- <tran trig="HUNGRY">
- <action>uint8_t n = Q_EVT_CAST(TableEvt)->philoNum;
- /* philo ID must be in range and he must be not hungry */
- Q_ASSERT_ID(60, (n < N_PHILO) && (me->isHungry[n] == 0U));
- me->isHungry[n] = 1U;
- BSP_displayPhilStat(n, "hungry ");</action>
- <tran_glyph conn="4,60,3,-1,15">
- <action box="0,-2,6,2"/>
- </tran_glyph>
- </tran>
- <!--${AOs::Table::SM::active::paused::DONE}-->
- <tran trig="DONE">
- <action>uint8_t n, m;
- n = Q_EVT_CAST(TableEvt)->philoNum;
- /* phil ID must be in range and he must be not hungry */
- Q_ASSERT_ID(70, (n < N_PHILO) && (me->isHungry[n] == 0U));
- BSP_displayPhilStat(n, "thinking");
- m = LEFT(n);
- /* both forks of Phil[n] must be used */
- Q_ASSERT_ID(71, (me->fork[n] == USED) && (me->fork[m] == USED));
- me->fork[m] = FREE;
- me->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>
- </package>
- <!--${.}-->
- <directory name=".">
- <!--${.::dpp.h}-->
- <file name="dpp.h">
- <text>#ifndef DPP_H
- #define DPP_H
- enum DPPSignals {
- EAT_SIG = 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 forks */
- 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 Philosophers for time events */
- MAX_SIG /* the last signal */
- };
- enum {
- N_PHILO = 5 /* number of Philos */
- };
- $declare ${Shared}
- #ifdef QXK_H_
- void Test1_ctor(void);
- extern QXThread * const XT_Test1;
- void Test2_ctor(void);
- extern QXThread * const XT_Test2;
- #endif /* QXK_H_ */
- #endif /* DPP_H */
- </text>
- </file>
- <!--${.::philo.c}-->
- <file name="philo.c">
- <text>#include "qpc.h"
- #include "dpp.h"
- #include "bsp.h"
- Q_DEFINE_THIS_MODULE("philo")
- /* Active object class -----------------------------------------------------*/
- $declare ${AOs::Philo}
- /* helper macros to provide a randomized think time for Philos */
- #define THINK_TIME \
- (QTimeEvtCtr)((BSP_random() % BSP_TICKS_PER_SEC) + (BSP_TICKS_PER_SEC/2U))
- #define EAT_TIME \
- (QTimeEvtCtr)((BSP_random() % BSP_TICKS_PER_SEC) + BSP_TICKS_PER_SEC)
- /* helper macro to provide the ID of Philo "me_" */
- #define PHILO_ID(me_) ((uint8_t)((me_) - &Philo_inst[0]))
- /* Shared objects ----------------------------------------------------------*/
- $define ${Shared::AO_Philo[N_PHILO]}
- $define ${Shared::Philo_ctor}
- /* Philo definition --------------------------------------------------------*/
- $define ${AOs::Philo}</text>
- </file>
- <!--${.::table.c}-->
- <file name="table.c">
- <text>#include "qpc.h"
- #include "dpp.h"
- #include "bsp.h"
- Q_DEFINE_THIS_MODULE("table")
- /* Active object class -----------------------------------------------------*/
- $declare ${AOs::Table}
- #define RIGHT(n_) ((uint8_t)(((n_) + (N_PHILO - 1U)) % N_PHILO))
- #define LEFT(n_) ((uint8_t)(((n_) + 1U) % N_PHILO))
- #define FREE ((uint8_t)0)
- #define USED ((uint8_t)1)
- /* Shared objects ----------------------------------------------------------*/
- $define ${Shared::AO_Table}
- $define ${Shared::Table_ctor}
- /*..........................................................................*/
- $define ${AOs::Table}</text>
- </file>
- </directory>
- </model>
|