QP/C++  7.3.3
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 6.1.1 <www.state-machine.com/qm>.
7// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost.
8//
9// This code is covered by the following QP license:
10// License # : LicenseRef-QL-dual
11// Issued to : Any user of the QP/C++ real-time embedded framework
12// Framework(s) : qpcpp
13// Support ends : 2024-12-31
14// License scope:
15//
16// Copyright (C) 2005 Quantum Leaps, LLC <state-machine.com>.
17//
18// Q u a n t u m L e a P s
19// ------------------------
20// Modern Embedded Software
21//
22// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
23//
24// This software is dual-licensed under the terms of the open source GNU
25// General Public License version 3 (or any later version), or alternatively,
26// under the terms of one of the closed source Quantum Leaps commercial
27// licenses.
28//
29// The terms of the open source GNU General Public License version 3
30// can be found at: <www.gnu.org/licenses/gpl-3.0>
31//
32// The terms of the closed source Quantum Leaps commercial licenses
33// can be found at: <www.state-machine.com/licensing>
34//
35// Redistributions in source code must retain this top-level comment block.
36// Plagiarizing this software to sidestep the license obligations is illegal.
37//
38// Contact information:
39// <www.state-machine.com/licensing>
40// <info@state-machine.com>
41//
42//$endhead${src::qf::qf_ps.cpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
43#define QP_IMPL // this is QP implementation
44#include "qp_port.hpp" // QP port
45#include "qp_pkg.hpp" // QP package-scope interface
46#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem
47#ifdef Q_SPY // QS software tracing enabled?
48 #include "qs_port.hpp" // QS port
49 #include "qs_pkg.hpp" // QS facilities for pre-defined trace records
50#else
51 #include "qs_dummy.hpp" // disable the QS software tracing
52#endif // Q_SPY
53
54// unnamed namespace for local definitions with internal linkage
55namespace {
56Q_DEFINE_THIS_MODULE("qf_ps")
57} // unnamed namespace
58
59//$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
60// Check for the minimum required QP version
61#if (QP_VERSION < 730U) || (QP_VERSION != ((QP_RELEASE^4294967295U) % 0x3E8U))
62#error qpcpp version 7.3.0 or higher required
63#endif
64//$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
65
66//$define${QF::QActive::subscrList_} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
67namespace QP {
68QSubscrList * QActive::subscrList_;
69
70} // namespace QP
71//$enddef${QF::QActive::subscrList_} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
72
73//$define${QF::QActive::maxPubSignal_} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
74namespace QP {
76
77} // namespace QP
78//$enddef${QF::QActive::maxPubSignal_} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
79
80//$define${QF::QActive::psInit} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
81namespace QP {
82
83//${QF::QActive::psInit} .....................................................
85 QSubscrList * const subscrSto,
86 enum_t const maxSignal) noexcept
87{
88 subscrList_ = subscrSto;
89 maxPubSignal_ = maxSignal;
90
91 // initialize the subscriber list
92 for (enum_t sig = 0; sig < maxSignal; ++sig) {
93 subscrSto[sig].m_set.setEmpty();
94 #ifndef Q_UNSAFE
95 subscrSto[sig].m_set.update_(&subscrSto[sig].m_set_dis);
96 #endif
97 }
98}
99
100} // namespace QP
101//$enddef${QF::QActive::psInit} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
102
103//$define${QF::QActive::publish_} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
104namespace QP {
105
106//${QF::QActive::publish_} ...................................................
108 QEvt const * const e,
109 void const * const sender,
110 std::uint_fast8_t const qsId) noexcept
111{
112 #ifndef Q_SPY
113 Q_UNUSED_PAR(sender);
114 Q_UNUSED_PAR(qsId);
115 #endif
116
117 QSignal const sig = e->sig;
118
121 QF_MEM_SYS();
122
123 Q_REQUIRE_INCRIT(200, sig < static_cast<QSignal>(maxPubSignal_));
125 subscrList_[sig].m_set.verify_(&subscrList_[sig].m_set_dis));
126
127 QS_BEGIN_PRE_(QS_QF_PUBLISH, qsId)
128 QS_TIME_PRE_(); // the timestamp
129 QS_OBJ_PRE_(sender); // the sender object
130 QS_SIG_PRE_(e->sig); // the signal of the event
131 QS_2U8_PRE_(e->getPoolNum_(), e->refCtr_); // poolNum & refCtr
132 QS_END_PRE_()
133
134 // is it a mutable event?
135 if (e->getPoolNum_() != 0U) {
136 // NOTE: The reference counter of a mutable event is incremented to
137 // prevent premature recycling of the event while the multicasting
138 // is still in progress. At the end of the function, the garbage
139 // collector step (QF::gc()) decrements the reference counter and
140 // recycles the event if the counter drops to zero. This covers the
141 // case when the event was published without any subscribers.
143 }
144
145 // make a local, modifiable copy of the subscriber set
146 QPSet subscrSet = subscrList_[sig].m_set;
147
148 QF_MEM_APP();
149 QF_CRIT_EXIT();
150
151 if (subscrSet.notEmpty()) { // any subscribers?
152 // highest-prio subscriber
153 std::uint_fast8_t p = subscrSet.findMax();
154
156 QF_MEM_SYS();
157
158 QActive *a = registry_[p];
159 // the AO must be registered with the framework
160 Q_ASSERT_INCRIT(210, a != nullptr);
161
162 QF_MEM_APP();
163 QF_CRIT_EXIT();
164
166 QF_SCHED_LOCK_(p); // lock the scheduler up to AO's prio
167 std::uint_fast8_t limit = QF_MAX_ACTIVE + 1U;
168 do { // loop over all subscribers
169 --limit;
170
171 // POST() asserts internally if the queue overflows
172 a->POST(e, sender);
173
174 subscrSet.remove(p); // remove the handled subscriber
175 if (subscrSet.notEmpty()) { // still more subscribers?
176 p = subscrSet.findMax(); // highest-prio subscriber
177
179 QF_MEM_SYS();
180
181 a = registry_[p];
182 // the AO must be registered with the framework
183 Q_ASSERT_INCRIT(220, a != nullptr);
184
185 QF_MEM_APP();
186 QF_CRIT_EXIT();
187 }
188 else {
189 p = 0U; // no more subscribers
190 }
191 } while ((p != 0U) && (limit > 0U));
192
194 Q_ENSURE_INCRIT(290, p == 0U);
195 QF_CRIT_EXIT();
196
197 QF_SCHED_UNLOCK_(); // unlock the scheduler
198 }
199
200 // The following garbage collection step decrements the reference counter
201 // and recycles the event if the counter drops to zero. This covers both
202 // cases when the event was published with or without any subscribers.
203 #if (QF_MAX_EPOOL > 0U)
204 QF::gc(e);
205 #endif
206}
207
208} // namespace QP
209//$enddef${QF::QActive::publish_} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
210
211//$define${QF::QActive::subscribe} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
212namespace QP {
213
214//${QF::QActive::subscribe} ..................................................
215void QActive::subscribe(enum_t const sig) const noexcept {
216 std::uint_fast8_t const p = static_cast<std::uint_fast8_t>(m_prio);
217
220 QF_MEM_SYS();
221
222 Q_REQUIRE_INCRIT(300, (Q_USER_SIG <= sig)
223 && (sig < maxPubSignal_)
224 && (0U < p) && (p <= QF_MAX_ACTIVE)
225 && (registry_[p] == this));
227 subscrList_[sig].m_set.verify_(&subscrList_[sig].m_set_dis));
228
229 QS_BEGIN_PRE_(QS_QF_ACTIVE_SUBSCRIBE, m_prio)
230 QS_TIME_PRE_(); // timestamp
231 QS_SIG_PRE_(sig); // the signal of this event
232 QS_OBJ_PRE_(this); // this active object
233 QS_END_PRE_()
234
235 // insert the prio. into the subscriber set
236 subscrList_[sig].m_set.insert(p);
237 #ifndef Q_UNSAFE
238 subscrList_[sig].m_set.update_(&subscrList_[sig].m_set_dis);
239 #endif
240
241 QF_MEM_APP();
242 QF_CRIT_EXIT();
243}
244
245} // namespace QP
246//$enddef${QF::QActive::subscribe} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
247
248//$define${QF::QActive::unsubscribe} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
249namespace QP {
250
251//${QF::QActive::unsubscribe} ................................................
252void QActive::unsubscribe(enum_t const sig) const noexcept {
253 std::uint_fast8_t const p = static_cast<std::uint_fast8_t>(m_prio);
254
257 QF_MEM_SYS();
258
259 Q_REQUIRE_INCRIT(400, (Q_USER_SIG <= sig)
260 && (sig < maxPubSignal_)
261 && (0U < p) && (p <= QF_MAX_ACTIVE)
262 && (registry_[p] == this));
264 subscrList_[sig].m_set.verify_(&subscrList_[sig].m_set_dis));
265
266 QS_BEGIN_PRE_(QS_QF_ACTIVE_UNSUBSCRIBE, m_prio)
267 QS_TIME_PRE_(); // timestamp
268 QS_SIG_PRE_(sig); // the signal of this event
269 QS_OBJ_PRE_(this); // this active object
270 QS_END_PRE_()
271
272 // remove the prio. from the subscriber set
273 subscrList_[sig].m_set.remove(p);
274 #ifndef Q_UNSAFE
275 subscrList_[sig].m_set.update_(&subscrList_[sig].m_set_dis);
276 #endif
277
278 QF_MEM_APP();
279 QF_CRIT_EXIT();
280}
281
282} // namespace QP
283//$enddef${QF::QActive::unsubscribe} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
284
285//$define${QF::QActive::unsubscribeAll} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
286namespace QP {
287
288//${QF::QActive::unsubscribeAll} .............................................
289void QActive::unsubscribeAll() const noexcept {
292 QF_MEM_SYS();
293
294 std::uint_fast8_t const p = static_cast<std::uint_fast8_t>(m_prio);
295
296 Q_REQUIRE_INCRIT(500, (0U < p) && (p <= QF_MAX_ACTIVE)
297 && (registry_[p] == this));
298 enum_t const maxPubSig = maxPubSignal_;
299
300 QF_MEM_APP();
301 QF_CRIT_EXIT();
302
303 for (enum_t sig = Q_USER_SIG; sig < maxPubSig; ++sig) {
305 QF_MEM_SYS();
306
307 if (subscrList_[sig].m_set.hasElement(p)) {
308 subscrList_[sig].m_set.remove(p);
309 #ifndef Q_UNSAFE
310 subscrList_[sig].m_set.update_(&subscrList_[sig].m_set_dis);
311 #endif
312 QS_BEGIN_PRE_(QS_QF_ACTIVE_UNSUBSCRIBE, m_prio)
313 QS_TIME_PRE_(); // timestamp
314 QS_SIG_PRE_(sig); // the signal of this event
315 QS_OBJ_PRE_(this); // this active object
316 QS_END_PRE_()
317 }
318 QF_MEM_APP();
319 QF_CRIT_EXIT();
320
321 QF_CRIT_EXIT_NOP(); // prevent merging critical sections
322 }
323}
324
325} // namespace QP
326//$enddef${QF::QActive::unsubscribeAll} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Active object class (based on the QHsm implementation strategy)
Definition qp.hpp:724
void unsubscribeAll() const noexcept
Definition qf_ps.cpp:289
static QSubscrList * subscrList_
Definition qp.hpp:751
static enum_t maxPubSignal_
Definition qp.hpp:752
void subscribe(enum_t const sig) const noexcept
Definition qf_ps.cpp:215
static void publish_(QEvt const *const e, void const *const sender, std::uint_fast8_t const qsId) noexcept
Definition qf_ps.cpp:107
void unsubscribe(enum_t const sig) const noexcept
Definition qf_ps.cpp:252
static QActive * registry_[QF_MAX_ACTIVE+1U]
Definition qp.hpp:750
static void psInit(QSubscrList *const subscrSto, enum_t const maxSignal) noexcept
Definition qf_ps.cpp:84
std::uint8_t m_prio
Definition qp.hpp:726
Event class.
Definition qp.hpp:139
Set of Active Objects of up to QF_MAX_ACTIVE elements.
Definition qp.hpp:612
void update_(QPSet *const dis) const noexcept
Definition qp.hpp:681
void remove(std::uint_fast8_t const n) noexcept
Definition qp.hpp:658
std::uint_fast8_t findMax() const noexcept
Definition qp.hpp:670
bool notEmpty() const noexcept
Definition qp.hpp:630
Subscriber List (for publish-subscribe)
Definition qp.hpp:702
QPSet m_set
Definition qp.hpp:704
void gc(QEvt const *const e) noexcept
Definition qf_dyn.cpp:236
QP/C++ framework.
Definition qequeue.hpp:50
constexpr enum_t Q_USER_SIG
Definition qp.hpp:217
std::uint16_t QSignal
Definition qp.hpp:130
void QEvt_refCtr_inc_(QEvt const *const e) noexcept
Definition qp_pkg.hpp:92
@ QS_QF_ACTIVE_UNSUBSCRIBE
an AO unsubscribed to an event
Definition qs.hpp:88
@ QS_QF_ACTIVE_SUBSCRIBE
an AO subscribed to an event
Definition qs.hpp:87
@ QS_QF_PUBLISH
an event was published to active objects
Definition qs.hpp:109
#define QF_SCHED_LOCK_(ceil_)
Definition qk.hpp:127
#define QF_SCHED_UNLOCK_()
Definition qk.hpp:136
#define QF_SCHED_STAT_
Definition qk.hpp:124
int enum_t
Definition qp.hpp:108
#define QF_MEM_APP()
Definition qp.hpp:1276
#define Q_UNUSED_PAR(par_)
Definition qp.hpp:541
#define QF_MEM_SYS()
Definition qp.hpp:1271
#define QF_CRIT_EXIT_NOP()
Definition qp.hpp:1266
#define QF_MAX_ACTIVE
Internal (package scope) QP/C++ interface.
Sample QP/C++ port.
#define QS_TIME_PRE_()
Definition qs.hpp:473
QS/C++ package-scope interface.
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_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