mirror of
https://github.com/QuantumLeaps/qpcpp.git
synced 2025-02-04 06:13:00 +08:00
274 lines
10 KiB
XML
274 lines
10 KiB
XML
<?xml version="1.0" encoding="UTF-8"?>
|
|
<model version="5.0.3" links="1">
|
|
<documentation>Dining Philosopher Problem example
|
|
|
|
NOTE: Requries QP6.</documentation>
|
|
<!--${qpcpp}-->
|
|
<framework name="qpcpp"/>
|
|
<!--${Events}-->
|
|
<package name="Events" stereotype="0x01">
|
|
<!--${Events::RequestEvt}-->
|
|
<class name="RequestEvt" superclass="qpcpp::QEvt">
|
|
<!--${Events::RequestEvt::ref_num}-->
|
|
<attribute name="ref_num" type="uint8_t" visibility="0x00" properties="0x00">
|
|
<documentation>reference number of the request</documentation>
|
|
</attribute>
|
|
</class>
|
|
</package>
|
|
<!--${Components}-->
|
|
<package name="Components" stereotype="0x02">
|
|
<!--${Components::TServer}-->
|
|
<class name="TServer" superclass="qpcpp::QActive">
|
|
<documentation>"Transaction Server" AO</documentation>
|
|
<!--${Components::TServer::m_requestQueue}-->
|
|
<attribute name="m_requestQueue" type="QP::QEQueue" visibility="0x02" properties="0x00">
|
|
<documentation>// native QF queue for deferred request events</documentation>
|
|
</attribute>
|
|
<!--${Components::TServer::m_requestQSto[3]}-->
|
|
<attribute name="m_requestQSto[3]" type="QP::QEvt const *" visibility="0x02" properties="0x00">
|
|
<documentation>// storage for the deferred queue buffer</documentation>
|
|
</attribute>
|
|
<!--${Components::TServer::m_activeRequest}-->
|
|
<attribute name="m_activeRequest" type="RequestEvt const *" visibility="0x02" properties="0x00">
|
|
<documentation>// request event being processed</documentation>
|
|
</attribute>
|
|
<!--${Components::TServer::m_receivedEvt}-->
|
|
<attribute name="m_receivedEvt" type="QP::QTimeEvt" visibility="0x02" properties="0x00">
|
|
<documentation>// private time event generator</documentation>
|
|
</attribute>
|
|
<!--${Components::TServer::m_authorizedEvt}-->
|
|
<attribute name="m_authorizedEvt" type="QP::QTimeEvt" visibility="0x02" properties="0x00">
|
|
<documentation>// private time event generator</documentation>
|
|
</attribute>
|
|
<!--${Components::TServer::inst}-->
|
|
<attribute name="inst" type="TServer" visibility="0x00" properties="0x01"/>
|
|
<!--${Components::TServer::TServer}-->
|
|
<operation name="TServer" type="explicit" visibility="0x00" properties="0x02">
|
|
<specifiers>noexcept</specifiers>
|
|
<documentation>ctor</documentation>
|
|
<code> : QActive(Q_STATE_CAST(&initial)),
|
|
m_receivedEvt(this, RECEIVED_SIG),
|
|
m_authorizedEvt(this, AUTHORIZED_SIG)
|
|
|
|
m_requestQueue.init(m_requestQSto, Q_DIM(m_requestQSto));</code>
|
|
</operation>
|
|
<!--${Components::TServer::SM}-->
|
|
<statechart properties="0x02">
|
|
<!--${Components::TServer::SM::initial}-->
|
|
<initial target="../1">
|
|
<action>(void)e; // unused parameter
|
|
m_activeRequest = nullptr; // no active request yet
|
|
|
|
QS_OBJ_DICTIONARY(&TServer::inst);
|
|
QS_OBJ_DICTIONARY(&TServer::inst.m_receivedEvt);
|
|
QS_OBJ_DICTIONARY(&TServer::inst.m_authorizedEvt);
|
|
QS_OBJ_DICTIONARY(&TServer::inst.m_requestQueue);</action>
|
|
<initial_glyph conn="2,2,5,1,32,6,-2">
|
|
<action box="0,-2,6,2"/>
|
|
</initial_glyph>
|
|
</initial>
|
|
<!--${Components::TServer::SM::idle}-->
|
|
<state name="idle">
|
|
<entry brief="recall">PRINTF_S("%s\n", "idle-ENTRY;");
|
|
|
|
// recall the oldest deferred request...
|
|
if (recall(&m_requestQueue)) {
|
|
PRINTF_S("%s\n", "Request recalled");
|
|
}
|
|
else {
|
|
PRINTF_S("%s\n", "No deferred requests");
|
|
}</entry>
|
|
<!--${Components::TServer::SM::idle::NEW_REQUEST}-->
|
|
<tran trig="NEW_REQUEST" target="../../2/2">
|
|
<action>// create and save a new reference to the request event so that
|
|
// this event will be available beyond this RTC step and won't be
|
|
// recycled.
|
|
Q_NEW_REF(m_activeRequest, RequestEvt);
|
|
|
|
PRINTF_S("Processing request #%d\n",
|
|
(int)m_activeRequest->ref_num);</action>
|
|
<tran_glyph conn="2,18,3,1,56,32,-12">
|
|
<action box="0,-2,24,2"/>
|
|
</tran_glyph>
|
|
</tran>
|
|
<!--${Components::TServer::SM::idle::TERMINATE}-->
|
|
<tran trig="TERMINATE" target="../../3">
|
|
<tran_glyph conn="2,22,3,1,62,68,-32">
|
|
<action box="0,-2,10,2"/>
|
|
</tran_glyph>
|
|
</tran>
|
|
<state_glyph node="2,6,30,20">
|
|
<entry box="1,2,13,2"/>
|
|
</state_glyph>
|
|
</state>
|
|
<!--${Components::TServer::SM::busy}-->
|
|
<state name="busy">
|
|
<exit>PRINTF_S("busy-EXIT; done processing request #%d\n",
|
|
(int)m_activeRequest->ref_num);
|
|
|
|
// delete the reference to the active request, because
|
|
// it is now processed.
|
|
Q_DELETE_REF(m_activeRequest);</exit>
|
|
<!--${Components::TServer::SM::busy::NEW_REQUEST}-->
|
|
<tran trig="NEW_REQUEST">
|
|
<action brief="defer">// defer the new request event...
|
|
if (defer(&m_requestQueue, e)) {
|
|
PRINTF_S("Request #%d deferred;\n",
|
|
(int)Q_EVT_CAST(RequestEvt)->ref_num);
|
|
}
|
|
else {
|
|
// notify the request sender that his request was denied...
|
|
PRINTF_S("Request #%d IGNORED;\n",
|
|
(int)Q_EVT_CAST(RequestEvt)->ref_num);
|
|
}</action>
|
|
<tran_glyph conn="2,40,3,-1,26">
|
|
<action box="0,-2,24,2"/>
|
|
</tran_glyph>
|
|
</tran>
|
|
<!--${Components::TServer::SM::busy::TERMINATE}-->
|
|
<tran trig="TERMINATE" target="../../3">
|
|
<tran_glyph conn="2,44,3,1,60,48,-30">
|
|
<action box="0,-2,10,2"/>
|
|
</tran_glyph>
|
|
</tran>
|
|
<!--${Components::TServer::SM::busy::receiving}-->
|
|
<state name="receiving">
|
|
<entry>// inform about the first stage of processing of the request...
|
|
PRINTF_S("receiving-ENTRY; active request: #%d\n",
|
|
(int)m_activeRequest->ref_num);
|
|
|
|
// one-shot timeout in 1 second
|
|
m_receivedEvt.armX(BSP_TICKS_PER_SEC, 0U);</entry>
|
|
<exit>m_receivedEvt.disarm();</exit>
|
|
<!--${Components::TServer::SM::busy::receiving::RECEIVED}-->
|
|
<tran trig="RECEIVED" target="../../3">
|
|
<tran_glyph conn="6,58,3,1,44,10,-4">
|
|
<action box="0,-2,8,2"/>
|
|
</tran_glyph>
|
|
</tran>
|
|
<state_glyph node="6,48,40,14">
|
|
<entry box="1,2,27,2"/>
|
|
<exit box="1,4,6,2"/>
|
|
</state_glyph>
|
|
</state>
|
|
<!--${Components::TServer::SM::busy::authorizing}-->
|
|
<state name="authorizing">
|
|
<entry>// inform about the second stage of processing of the request..
|
|
PRINTF_S("authorizing-ENTRY; active request: #%d\n",
|
|
(int)m_activeRequest->ref_num);
|
|
|
|
// one-shot timeout in 2 seconds
|
|
m_authorizedEvt.armX(2U*BSP_TICKS_PER_SEC, 0U);</entry>
|
|
<exit>m_authorizedEvt.disarm();</exit>
|
|
<!--${Components::TServer::SM::busy::authorizing::AUTHORIZED}-->
|
|
<tran trig="AUTHORIZED" target="../../../1">
|
|
<tran_glyph conn="6,76,3,1,54,-62,-28">
|
|
<action box="0,-2,14,2"/>
|
|
</tran_glyph>
|
|
</tran>
|
|
<state_glyph node="6,66,40,14">
|
|
<entry box="1,2,17,2"/>
|
|
<exit box="1,4,6,2"/>
|
|
</state_glyph>
|
|
</state>
|
|
<state_glyph node="2,30,54,54">
|
|
<exit box="1,2,6,2"/>
|
|
</state_glyph>
|
|
</state>
|
|
<!--${Components::TServer::SM::final}-->
|
|
<state name="final">
|
|
<entry brief="stop">PRINTF_S("%s\n", "final-ENTRY;");
|
|
QP::QF::stop(); // terminate the application</entry>
|
|
<state_glyph node="2,88,30,10">
|
|
<entry box="1,2,6,2"/>
|
|
</state_glyph>
|
|
</state>
|
|
<state_diagram size="68,102"/>
|
|
</statechart>
|
|
</class>
|
|
</package>
|
|
<!--${.}-->
|
|
<directory name=".">
|
|
<!--${.::defer.cpp}-->
|
|
<file name="defer.cpp">
|
|
<text>#include "qpcpp.hpp"
|
|
#include "bsp.hpp"
|
|
|
|
#include "safe_std.h" // portable "safe" <stdio.h>/<string.h> facilities
|
|
|
|
Q_DEFINE_THIS_FILE
|
|
|
|
//............................................................................
|
|
enum TServerSignals {
|
|
NEW_REQUEST_SIG = QP::Q_USER_SIG, // the new request signal
|
|
RECEIVED_SIG, // the request has been received
|
|
AUTHORIZED_SIG, // the request has been authorized
|
|
TERMINATE_SIG // terminate the application
|
|
};
|
|
//............................................................................
|
|
$declare${Events::RequestEvt}
|
|
|
|
// Active object class -----------------------------------------------------..
|
|
$declare${Components::TServer}
|
|
|
|
$define${Components::TServer}
|
|
|
|
// test harness ==============================================================
|
|
|
|
// Local-scope objects -------------------------------------------------------
|
|
static QP::QEvt const *l_tserverQSto[10]; // Event queue storage for TServer
|
|
static QF_MPOOL_EL(RequestEvt) l_smlPoolSto[20]; // storage for small pool
|
|
|
|
//............................................................................
|
|
int main(int argc, char *argv[]) {
|
|
PRINTF_S("Deferred Event state pattern\nQP version: %s\n"
|
|
"Press 'n' to generate a new request\n"
|
|
"Press ESC to quit...\n",
|
|
QP_VERSION_STR);
|
|
|
|
QP::QF::init(); // initialize the framework and the underlying RTOS/OS
|
|
|
|
BSP_init(argc, argv); // initialize the BSP
|
|
|
|
|
|
// publish-subscribe not used, no call to QF_psInit()
|
|
|
|
// initialize event pools...
|
|
QP::QF::poolInit(l_smlPoolSto,
|
|
sizeof(l_smlPoolSto), sizeof(l_smlPoolSto[0]));
|
|
|
|
QS_SIG_DICTIONARY(NEW_REQUEST_SIG, nullptr); // global signals
|
|
QS_SIG_DICTIONARY(RECEIVED_SIG, nullptr);
|
|
QS_SIG_DICTIONARY(AUTHORIZED_SIG, nullptr);
|
|
QS_SIG_DICTIONARY(TERMINATE_SIG, nullptr);
|
|
|
|
// start the active objects...
|
|
TServer::inst.start(1U,
|
|
l_tserverQSto, Q_DIM(l_tserverQSto),
|
|
nullptr, 0U);
|
|
|
|
return QP::QF::run(); // run the QF application
|
|
}
|
|
//............................................................................
|
|
void BSP_onKeyboardInput(uint8_t key) {
|
|
switch (key) {
|
|
case 'n': { // 'n': new request?
|
|
static uint8_t reqCtr = 0; // count the requests
|
|
RequestEvt *e = Q_NEW(RequestEvt, NEW_REQUEST_SIG);
|
|
e->ref_num = (++reqCtr); // set the reference number
|
|
// post directly to TServer active object
|
|
TServer::inst.POST(e, (void *)0);
|
|
break;
|
|
}
|
|
case '\33': { // ESC pressed?
|
|
static QP::QEvt const terminateEvt { TERMINATE_SIG, 0U, 0U };
|
|
TServer::inst.POST(&terminateEvt, (void *)0);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
</text>
|
|
</file>
|
|
</directory>
|
|
</model>
|