QP/C++  8.0.0
Real-Time Embedded Framework
Loading...
Searching...
No Matches
qf_ps.cpp
Go to the documentation of this file.
1//$file${src::qf::qf_ps.cpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
2//
3// Model: qpcpp.qm
4// File: ${src::qf::qf_ps.cpp}
5//
6// This code has been generated by QM 7.0.0 <www.state-machine.com/qm>.
7// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost.
8//
9// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
10//
11// Q u a n t u m L e a P s
12// ------------------------
13// Modern Embedded Software
14//
15// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
16//
17// The QP/C++ software is dual-licensed under the terms of the open-source
18// GNU General Public License (GPL) or under the terms of one of the closed-
19// source Quantum Leaps commercial licenses.
20//
21// Redistributions in source code must retain this top-level comment block.
22// Plagiarizing this software to sidestep the license obligations is illegal.
23//
24// NOTE:
25// The GPL does NOT permit the incorporation of this code into proprietary
26// programs. Please contact Quantum Leaps for commercial licensing options,
27// which expressly supersede the GPL and are designed explicitly for
28// closed-source distribution.
29//
30// Quantum Leaps contact information:
31// <www.state-machine.com/licensing>
32// <info@state-machine.com>
33//
34//$endhead${src::qf::qf_ps.cpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
35#define QP_IMPL // this is QP implementation
36#include "qp_port.hpp" // QP port
37#include "qp_pkg.hpp" // QP package-scope interface
38#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem
39#ifdef Q_SPY // QS software tracing enabled?
40 #include "qs_port.hpp" // QS port
41 #include "qs_pkg.hpp" // QS facilities for pre-defined trace records
42#else
43 #include "qs_dummy.hpp" // disable the QS software tracing
44#endif // Q_SPY
45
46// unnamed namespace for local definitions with internal linkage
47namespace {
48Q_DEFINE_THIS_MODULE("qf_ps")
49} // unnamed namespace
50
51//$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
52// Check for the minimum required QP version
53#if (QP_VERSION < 730U) || (QP_VERSION != ((QP_RELEASE^4294967295U)%0x2710U))
54#error qpcpp version 7.3.0 or higher required
55#endif
56//$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
57//$define${QF::QActive::subscrList_} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
58namespace QP {
59QSubscrList * QActive::subscrList_;
60
61} // namespace QP
62//$enddef${QF::QActive::subscrList_} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
63
64//$define${QF::QActive::maxPubSignal_} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
65namespace QP {
67
68} // namespace QP
69//$enddef${QF::QActive::maxPubSignal_} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
70
71//$define${QF::QActive::psInit} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
72namespace QP {
73
74//${QF::QActive::psInit} .....................................................
76 QSubscrList * const subscrSto,
77 enum_t const maxSignal) noexcept
78{
79 subscrList_ = subscrSto;
80 maxPubSignal_ = maxSignal;
81
82 // initialize the subscriber list
83 for (enum_t sig = 0; sig < maxSignal; ++sig) {
84 subscrSto[sig].m_set.setEmpty();
85 #ifndef Q_UNSAFE
86 subscrSto[sig].m_set.update_(&subscrSto[sig].m_set_dis);
87 #endif
88 }
89}
90
91} // namespace QP
92//$enddef${QF::QActive::psInit} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
93
94//$define${QF::QActive::publish_} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
95namespace QP {
96
97//${QF::QActive::publish_} ...................................................
99 QEvt const * const e,
100 void const * const sender,
101 std::uint_fast8_t const qsId) noexcept
102{
103 #ifndef Q_SPY
104 Q_UNUSED_PAR(sender);
105 Q_UNUSED_PAR(qsId);
106 #endif
107
108 QSignal const sig = e->sig;
109
112 QF_MEM_SYS();
113
114 Q_REQUIRE_INCRIT(200, sig < static_cast<QSignal>(maxPubSignal_));
116 subscrList_[sig].m_set.verify_(&subscrList_[sig].m_set_dis));
117
118 QS_BEGIN_PRE(QS_QF_PUBLISH, qsId)
119 QS_TIME_PRE(); // the timestamp
120 QS_OBJ_PRE(sender); // the sender object
121 QS_SIG_PRE(e->sig); // the signal of the event
122 QS_2U8_PRE(e->getPoolNum_(), e->refCtr_);
123 QS_END_PRE()
124
125 // is it a mutable event?
126 if (e->getPoolNum_() != 0U) {
127 // NOTE: The reference counter of a mutable event is incremented to
128 // prevent premature recycling of the event while the multicasting
129 // is still in progress. At the end of the function, the garbage
130 // collector step (QF::gc()) decrements the reference counter and
131 // recycles the event if the counter drops to zero. This covers the
132 // case when the event was published without any subscribers.
134 }
135
136 // make a local, modifiable copy of the subscriber set
137 QPSet subscrSet = subscrList_[sig].m_set;
138
139 QF_MEM_APP();
140 QF_CRIT_EXIT();
141
142 if (subscrSet.notEmpty()) { // any subscribers?
143 // highest-prio subscriber
144 std::uint_fast8_t p = subscrSet.findMax();
145
147 QF_MEM_SYS();
148
149 QActive *a = registry_[p];
150 // the AO must be registered with the framework
151 Q_ASSERT_INCRIT(210, a != nullptr);
152
153 QF_MEM_APP();
154 QF_CRIT_EXIT();
155
157 QF_SCHED_LOCK_(p); // lock the scheduler up to AO's prio
158 std::uint_fast8_t lbound = QF_MAX_ACTIVE + 1U;
159 do { // loop over all subscribers
160 --lbound;
161
162 // POST() asserts internally if the queue overflows
163 a->POST(e, sender);
164
165 subscrSet.remove(p); // remove the handled subscriber
166 if (subscrSet.notEmpty()) { // still more subscribers?
167 p = subscrSet.findMax(); // highest-prio subscriber
168
170 QF_MEM_SYS();
171
172 a = registry_[p];
173 // the AO must be registered with the framework
174 Q_ASSERT_INCRIT(220, a != nullptr);
175
176 QF_MEM_APP();
177 QF_CRIT_EXIT();
178 }
179 else {
180 p = 0U; // no more subscribers
181 }
182 } while ((p != 0U) && (lbound > 0U));
183
185 Q_ENSURE_INCRIT(290, p == 0U);
186 QF_CRIT_EXIT();
187
188 QF_SCHED_UNLOCK_(); // unlock the scheduler
189 }
190
191 // The following garbage collection step decrements the reference counter
192 // and recycles the event if the counter drops to zero. This covers both
193 // cases when the event was published with or without any subscribers.
194 #if (QF_MAX_EPOOL > 0U)
195 QF::gc(e);
196 #endif
197}
198
199} // namespace QP
200//$enddef${QF::QActive::publish_} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
201
202//$define${QF::QActive::subscribe} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
203namespace QP {
204
205//${QF::QActive::subscribe} ..................................................
206void QActive::subscribe(enum_t const sig) const noexcept {
207 std::uint_fast8_t const p = static_cast<std::uint_fast8_t>(m_prio);
208
211 QF_MEM_SYS();
212
213 Q_REQUIRE_INCRIT(300, (Q_USER_SIG <= sig)
214 && (sig < maxPubSignal_)
215 && (0U < p) && (p <= QF_MAX_ACTIVE)
216 && (registry_[p] == this));
218 subscrList_[sig].m_set.verify_(&subscrList_[sig].m_set_dis));
219
220 QS_BEGIN_PRE(QS_QF_ACTIVE_SUBSCRIBE, m_prio)
221 QS_TIME_PRE(); // timestamp
222 QS_SIG_PRE(sig); // the signal of this event
223 QS_OBJ_PRE(this); // this active object
224 QS_END_PRE()
225
226 // insert the prio. into the subscriber set
227 subscrList_[sig].m_set.insert(p);
228 #ifndef Q_UNSAFE
229 subscrList_[sig].m_set.update_(&subscrList_[sig].m_set_dis);
230 #endif
231
232 QF_MEM_APP();
233 QF_CRIT_EXIT();
234}
235
236} // namespace QP
237//$enddef${QF::QActive::subscribe} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
238
239//$define${QF::QActive::unsubscribe} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
240namespace QP {
241
242//${QF::QActive::unsubscribe} ................................................
243void QActive::unsubscribe(enum_t const sig) const noexcept {
244 std::uint_fast8_t const p = static_cast<std::uint_fast8_t>(m_prio);
245
248 QF_MEM_SYS();
249
250 Q_REQUIRE_INCRIT(400, (Q_USER_SIG <= sig)
251 && (sig < maxPubSignal_)
252 && (0U < p) && (p <= QF_MAX_ACTIVE)
253 && (registry_[p] == this));
255 subscrList_[sig].m_set.verify_(&subscrList_[sig].m_set_dis));
256
257 QS_BEGIN_PRE(QS_QF_ACTIVE_UNSUBSCRIBE, m_prio)
258 QS_TIME_PRE(); // timestamp
259 QS_SIG_PRE(sig); // the signal of this event
260 QS_OBJ_PRE(this); // this active object
261 QS_END_PRE()
262
263 // remove the prio. from the subscriber set
264 subscrList_[sig].m_set.remove(p);
265 #ifndef Q_UNSAFE
266 subscrList_[sig].m_set.update_(&subscrList_[sig].m_set_dis);
267 #endif
268
269 QF_MEM_APP();
270 QF_CRIT_EXIT();
271}
272
273} // namespace QP
274//$enddef${QF::QActive::unsubscribe} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
275
276//$define${QF::QActive::unsubscribeAll} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
277namespace QP {
278
279//${QF::QActive::unsubscribeAll} .............................................
280void QActive::unsubscribeAll() const noexcept {
283 QF_MEM_SYS();
284
285 std::uint_fast8_t const p = static_cast<std::uint_fast8_t>(m_prio);
286
287 Q_REQUIRE_INCRIT(500, (0U < p) && (p <= QF_MAX_ACTIVE)
288 && (registry_[p] == this));
289 enum_t const maxPubSig = maxPubSignal_;
290
291 QF_MEM_APP();
292 QF_CRIT_EXIT();
293
294 for (enum_t sig = Q_USER_SIG; sig < maxPubSig; ++sig) {
296 QF_MEM_SYS();
297
298 if (subscrList_[sig].m_set.hasElement(p)) {
299 subscrList_[sig].m_set.remove(p);
300 #ifndef Q_UNSAFE
301 subscrList_[sig].m_set.update_(&subscrList_[sig].m_set_dis);
302 #endif
303 QS_BEGIN_PRE(QS_QF_ACTIVE_UNSUBSCRIBE, m_prio)
304 QS_TIME_PRE(); // timestamp
305 QS_SIG_PRE(sig); // the signal of this event
306 QS_OBJ_PRE(this); // this active object
307 QS_END_PRE()
308 }
309 QF_MEM_APP();
310 QF_CRIT_EXIT();
311
312 QF_CRIT_EXIT_NOP(); // prevent merging critical sections
313 }
314}
315
316} // namespace QP
317//$enddef${QF::QActive::unsubscribeAll} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Active object class (based on the QHsm implementation strategy)
Definition qp.hpp:699
void subscribe(enum_t const sig) const noexcept
Definition qf_ps.cpp:206
static QActive * registry_[QF_MAX_ACTIVE+1U]
Definition qp.hpp:725
static QSubscrList * subscrList_
Definition qp.hpp:726
void unsubscribe(enum_t const sig) const noexcept
Definition qf_ps.cpp:243
static void publish_(QEvt const *const e, void const *const sender, std::uint_fast8_t const qsId) noexcept
Definition qf_ps.cpp:98
static void psInit(QSubscrList *const subscrSto, enum_t const maxSignal) noexcept
Definition qf_ps.cpp:75
static enum_t maxPubSignal_
Definition qp.hpp:727
std::uint8_t m_prio
Definition qp.hpp:701
void unsubscribeAll() const noexcept
Definition qf_ps.cpp:280
Event class.
Definition qp.hpp:131
Set of Active Objects of up to QF_MAX_ACTIVE elements.
Definition qp.hpp:572
std::uint_fast8_t findMax() const noexcept
Definition qp.hpp:630
void remove(std::uint_fast8_t const n) noexcept
Definition qp.hpp:618
bool notEmpty() const noexcept
Definition qp.hpp:590
void update_(QPSet *const dis) const noexcept
Definition qp.hpp:641
Subscriber List (for publish-subscribe)
Definition qp.hpp:662
QPSet m_set
Definition qp.hpp:664
void gc(QEvt const *const e) noexcept
Recycle a mutable (mutable) event.
Definition qf_dyn.cpp:213
QP/C++ framework.
Definition qequeue.hpp:42
constexpr enum_t Q_USER_SIG
Definition qp.hpp:209
void QEvt_refCtr_inc_(QEvt const *const e) noexcept
Definition qp_pkg.hpp:81
std::uint16_t QSignal
The signal of event QP::QEvt.
Definition qp.hpp:122
#define QF_SCHED_LOCK_(ceil_)
Definition qk.hpp:119
#define QF_SCHED_UNLOCK_()
Definition qk.hpp:128
#define QF_SCHED_STAT_
Definition qk.hpp:116
int enum_t
Definition qp.hpp:99
#define QF_MEM_APP()
Definition qp.hpp:1322
#define Q_UNUSED_PAR(par_)
Helper macro to clearly mark unused parameters of functions.
Definition qp.hpp:498
#define QF_MEM_SYS()
Definition qp.hpp:1317
#define QF_CRIT_EXIT_NOP()
Definition qp.hpp:1312
#define QF_MAX_ACTIVE
Maximum # Active Objects in the system (1..64)
Internal (package scope) QP/C++ interface.
Sample QP/C++ port.
#define QS_OBJ_PRE(obj_)
Definition qs_dummy.hpp:158
#define QS_SIG_PRE(sig_)
Definition qs_dummy.hpp:156
#define QS_TIME_PRE()
Definition qs_dummy.hpp:155
#define QS_2U8_PRE(data1_, data2_)
Definition qs_dummy.hpp:152
#define QS_END_PRE()
Definition qs_dummy.hpp:150
#define QS_BEGIN_PRE(rec_, qsId_)
Definition qs_dummy.hpp:149
QS/C++ port to a 32-bit CPU, generic C++ compiler.
QP Functional Safety (FuSa) Subsystem.
#define QF_CRIT_ENTRY()
Definition qsafe.h:58
#define Q_ASSERT_INCRIT(id_, expr_)
Definition qsafe.h:72
#define Q_INVARIANT_INCRIT(id_, expr_)
Definition qsafe.h:154
#define Q_ENSURE_INCRIT(id_, expr_)
Definition qsafe.h:145
#define QF_CRIT_EXIT()
Definition qsafe.h:62
#define Q_REQUIRE_INCRIT(id_, expr_)
Definition qsafe.h:136
#define QF_CRIT_STAT
Definition qsafe.h:54