2020-08-24 16:42:48 -04:00

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>&quot;Transaction Server&quot; 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(&amp;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(&amp;TServer::inst);
QS_OBJ_DICTIONARY(&amp;TServer::inst.m_receivedEvt);
QS_OBJ_DICTIONARY(&amp;TServer::inst.m_authorizedEvt);
QS_OBJ_DICTIONARY(&amp;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(&quot;%s\n&quot;, &quot;idle-ENTRY;&quot;);
// recall the oldest deferred request...
if (recall(&amp;m_requestQueue)) {
PRINTF_S(&quot;%s\n&quot;, &quot;Request recalled&quot;);
}
else {
PRINTF_S(&quot;%s\n&quot;, &quot;No deferred requests&quot;);
}</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(&quot;Processing request #%d\n&quot;,
(int)m_activeRequest-&gt;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(&quot;busy-EXIT; done processing request #%d\n&quot;,
(int)m_activeRequest-&gt;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(&amp;m_requestQueue, e)) {
PRINTF_S(&quot;Request #%d deferred;\n&quot;,
(int)Q_EVT_CAST(RequestEvt)-&gt;ref_num);
}
else {
// notify the request sender that his request was denied...
PRINTF_S(&quot;Request #%d IGNORED;\n&quot;,
(int)Q_EVT_CAST(RequestEvt)-&gt;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(&quot;receiving-ENTRY; active request: #%d\n&quot;,
(int)m_activeRequest-&gt;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(&quot;authorizing-ENTRY; active request: #%d\n&quot;,
(int)m_activeRequest-&gt;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(&quot;%s\n&quot;, &quot;final-ENTRY;&quot;);
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 &quot;qpcpp.hpp&quot;
#include &quot;bsp.hpp&quot;
#include &quot;safe_std.h&quot; // portable &quot;safe&quot; &lt;stdio.h&gt;/&lt;string.h&gt; 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(&quot;Deferred Event state pattern\nQP version: %s\n&quot;
&quot;Press 'n' to generate a new request\n&quot;
&quot;Press ESC to quit...\n&quot;,
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-&gt;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(&amp;terminateEvt, (void *)0);
break;
}
}
}
</text>
</file>
</directory>
</model>