QP/C++  8.0.0
Real-Time Embedded Framework
Loading...
Searching...
No Matches
qf_dyn.cpp
Go to the documentation of this file.
1//$file${src::qf::qf_dyn.cpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
2//
3// Model: qpcpp.qm
4// File: ${src::qf::qf_dyn.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_dyn.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#if (QF_MAX_EPOOL > 0U) // mutable events configured?
47
48// unnamed namespace for local definitions with internal linkage
49namespace {
50Q_DEFINE_THIS_MODULE("qf_dyn")
51} // unnamed namespace
52
53//$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
54// Check for the minimum required QP version
55#if (QP_VERSION < 730U) || (QP_VERSION != ((QP_RELEASE^4294967295U)%0x2710U))
56#error qpcpp version 7.3.0 or higher required
57#endif
58//$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
59//$define${QF::QF-dyn} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
60namespace QP {
61namespace QF {
62
63//${QF::QF-dyn::poolInit} ....................................................
65 void * const poolSto,
66 std::uint_fast32_t const poolSize,
67 std::uint_fast16_t const evtSize) noexcept
68{
69 std::uint_fast8_t const poolNum = priv_.maxPool_;
70
71 // see precondition{qf_dyn,200} and precondition{qf_dyn,201}
74 QF_MEM_SYS();
75
76 Q_REQUIRE_INCRIT(200, poolNum < QF_MAX_EPOOL);
77 if (poolNum > 0U) {
79 QF_EPOOL_EVENT_SIZE_(priv_.ePool_[poolNum - 1U]) < evtSize);
80 }
81 priv_.maxPool_ = poolNum + 1U; // one more pool
82
83 QF_MEM_APP();
85
86 // perform the port-dependent initialization of the event-pool
87 QF_EPOOL_INIT_(priv_.ePool_[poolNum], poolSto, poolSize, evtSize);
88
89 #ifdef Q_SPY
90 // generate the object-dictionary entry for the initialized pool
91 {
92 std::uint8_t obj_name[9] = "EvtPool?";
93 obj_name[7] = static_cast<std::uint8_t>(
94 static_cast<std::uint8_t>('0')
95 + static_cast<std::uint8_t>(poolNum + 1U));
96 QS::obj_dict_pre_(&priv_.ePool_[poolNum],
97 reinterpret_cast<char *>(&obj_name[0]));
98 }
99 #endif // Q_SPY
100}
101
102//${QF::QF-dyn::poolGetMaxBlockSize} .........................................
103std::uint_fast16_t poolGetMaxBlockSize() noexcept {
106 QF_MEM_SYS();
107 std::uint_fast16_t const max_size =
109 QF_MEM_APP();
110 QF_CRIT_EXIT();
111
112 return max_size;
113}
114
115//${QF::QF-dyn::getPoolMin} ..................................................
116std::uint_fast16_t getPoolMin(std::uint_fast8_t const poolNum) noexcept {
119 QF_MEM_SYS();
120
121 Q_REQUIRE_INCRIT(400, (poolNum <= QF_MAX_EPOOL)
122 && (0U < poolNum) && (poolNum <= priv_.maxPool_));
123
124 std::uint_fast16_t const min = static_cast<std::uint_fast16_t>(
125 priv_.ePool_[poolNum - 1U].getNMin());
126
127 QF_MEM_APP();
128 QF_CRIT_EXIT();
129
130 return min;
131}
132
133//${QF::QF-dyn::newX_} .......................................................
135 std::uint_fast16_t const evtSize,
136 std::uint_fast16_t const margin,
137 enum_t const sig) noexcept
138{
141 QF_MEM_SYS();
142
143 // find the pool id that fits the requested event size...
144 std::uint_fast8_t poolNum = 0U; // zero-based poolNum initially
145 for (; poolNum < priv_.maxPool_; ++poolNum) {
146 if (evtSize <= QF_EPOOL_EVENT_SIZE_(priv_.ePool_[poolNum])) {
147 break;
148 }
149 }
150
151 // precondition:
152 // - cannot run out of registered pools
153 Q_REQUIRE_INCRIT(300, poolNum < priv_.maxPool_);
154
155 ++poolNum; // convert to 1-based poolNum
156
157 QF_MEM_APP();
158 QF_CRIT_EXIT();
159
160 // get event e (port-dependent)...
161 QEvt *e;
162 #ifdef Q_SPY
163 QF_EPOOL_GET_(priv_.ePool_[poolNum - 1U], e,
164 ((margin != NO_MARGIN) ? margin : 0U),
165 static_cast<std::uint_fast8_t>(QS_EP_ID) + poolNum);
166 #else
167 QF_EPOOL_GET_(priv_.ePool_[poolNum - 1U], e,
168 ((margin != NO_MARGIN) ? margin : 0U), 0U);
169 #endif
170
171 if (e != nullptr) { // was e allocated correctly?
172 e->sig = static_cast<QSignal>(sig); // set the signal
173 e->evtTag_ = static_cast<std::uint8_t>((poolNum << 4U) | 0x0FU);
174 e->refCtr_ = 0U; // initialize the reference counter to 0
175
177 QS_MEM_SYS();
178 QS_BEGIN_PRE(QS_QF_NEW,
179 static_cast<std::uint_fast8_t>(QS_EP_ID) + poolNum)
180 QS_TIME_PRE(); // timestamp
181 QS_EVS_PRE(evtSize); // the size of the event
182 QS_SIG_PRE(sig); // the signal of the event
183 QS_END_PRE()
184 QS_MEM_APP();
185 QS_CRIT_EXIT();
186 }
187 else { // event was not allocated
188
190 // This assertion means that the event allocation failed,
191 // and this failure cannot be tolerated. The most frequent
192 // reason is an event leak in the application.
193 Q_ASSERT_INCRIT(320, margin != NO_MARGIN);
194
195 QS_MEM_SYS();
196 QS_BEGIN_PRE(QS_QF_NEW_ATTEMPT,
197 static_cast<std::uint_fast8_t>(QS_EP_ID) + poolNum)
198 QS_TIME_PRE(); // timestamp
199 QS_EVS_PRE(evtSize); // the size of the event
200 QS_SIG_PRE(sig); // the signal of the event
201 QS_END_PRE()
202 QS_MEM_APP();
203
204 QF_CRIT_EXIT();
205 }
206
207 // the returned event e is guaranteed to be valid (not NULL)
208 // if we can't tolerate failed allocation
209 return e;
210}
211
212//${QF::QF-dyn::gc} ..........................................................
213void gc(QEvt const * const e) noexcept {
216 Q_REQUIRE_INCRIT(400, e != nullptr);
217 Q_INVARIANT_INCRIT(401, e->verify_());
218
219 std::uint_fast8_t const poolNum = e->getPoolNum_();
220
221 if (poolNum != 0U) { // is it a pool event (mutable)?
222 QF_MEM_SYS();
223
224 if (e->refCtr_ > 1U) { // isn't this the last reference?
225
226 QS_BEGIN_PRE(QS_QF_GC_ATTEMPT,
227 static_cast<std::uint_fast8_t>(QS_EP_ID) + poolNum)
228 QS_TIME_PRE(); // timestamp
229 QS_SIG_PRE(e->sig); // the signal of the event
230 QS_2U8_PRE(poolNum, e->refCtr_);
231 QS_END_PRE()
232
233 QEvt_refCtr_dec_(e); // decrement the ref counter
234
235 QF_MEM_APP();
236 QF_CRIT_EXIT();
237 }
238 else { // this is the last reference to this event, recycle it
239
240 QS_BEGIN_PRE(QS_QF_GC,
241 static_cast<std::uint_fast8_t>(QS_EP_ID) + poolNum)
242 QS_TIME_PRE(); // timestamp
243 QS_SIG_PRE(e->sig); // the signal of the event
244 QS_2U8_PRE(poolNum, e->refCtr_);
245 QS_END_PRE()
246
247 // pool number must be in range
248 Q_ASSERT_INCRIT(410, (poolNum <= priv_.maxPool_)
249 && (poolNum <= QF_MAX_EPOOL));
250 QF_MEM_APP();
251 QF_CRIT_EXIT();
252
253 // NOTE: casting 'const' away is legit because it's a pool event
254 #ifdef Q_SPY
255 QF_EPOOL_PUT_(priv_.ePool_[poolNum - 1U],
256 QF_CONST_CAST_(QEvt*, e),
257 static_cast<std::uint_fast8_t>(QS_EP_ID) + poolNum);
258 #else
259 QF_EPOOL_PUT_(priv_.ePool_[poolNum - 1U],
260 QF_CONST_CAST_(QEvt*, e), 0U);
261 #endif
262 }
263 }
264 else {
265 QF_CRIT_EXIT();
266 }
267}
268
269//${QF::QF-dyn::newRef_} .....................................................
270QEvt const * newRef_(
271 QEvt const * const e,
272 QEvt const * const evtRef) noexcept
273{
274 #ifdef Q_UNSAFE
275 Q_UNUSED_PAR(evtRef);
276 #endif
277
280
281 Q_REQUIRE_INCRIT(500, e != nullptr);
282 Q_INVARIANT_INCRIT(501, e->verify_());
283
284 std::uint_fast8_t const poolNum = e->getPoolNum_();
285 Q_UNUSED_PAR(poolNum); // might be unused
286
287 Q_REQUIRE_INCRIT(501, (poolNum != 0U)
288 && (evtRef == nullptr));
289
290 QEvt_refCtr_inc_(e); // increments the ref counter
291
292 QS_MEM_SYS();
293 QS_BEGIN_PRE(QS_QF_NEW_REF,
294 static_cast<std::uint_fast8_t>(QS_EP_ID) + poolNum)
295 QS_TIME_PRE(); // timestamp
296 QS_SIG_PRE(e->sig); // the signal of the event
297 QS_2U8_PRE(poolNum, e->refCtr_);
298 QS_END_PRE()
299 QS_MEM_APP();
300
301 QF_CRIT_EXIT();
302
303 return e;
304}
305
306//${QF::QF-dyn::deleteRef_} ..................................................
307void deleteRef_(QEvt const * const evtRef) noexcept {
310
311 QEvt const * const e = evtRef;
312 Q_REQUIRE_INCRIT(600, e != nullptr);
313 Q_INVARIANT_INCRIT(601, e->verify_());
314
315 #ifdef Q_SPY
316 std::uint_fast8_t const poolNum = e->getPoolNum_();
317 #endif
318
319 QS_MEM_SYS();
320 QS_BEGIN_PRE(QS_QF_DELETE_REF,
321 static_cast<std::uint_fast8_t>(QS_EP_ID) + poolNum)
322 QS_TIME_PRE(); // timestamp
323 QS_SIG_PRE(e->sig); // the signal of the event
324 QS_2U8_PRE(poolNum, e->refCtr_);
325 QS_END_PRE()
326 QS_MEM_APP();
327
328 QF_CRIT_EXIT();
329
330 #if (QF_MAX_EPOOL > 0U)
331 gc(e); // recycle the referenced event
332 #endif
333}
334
335} // namespace QF
336} // namespace QP
337//$enddef${QF::QF-dyn} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
338
339#endif // (QF_MAX_EPOOL > 0U) mutable events configured
Event class.
Definition qp.hpp:131
QSignal sig
Signal of the event (see Event Signal)
Definition qp.hpp:133
std::uint8_t volatile refCtr_
Event reference counter.)
Definition qp.hpp:135
bool verify_() const noexcept
Internal function to verify the internal integrity of the event instance (QP FuSa Subsystem)
Definition qp.hpp:154
std::uint8_t evtTag_
Event "tag" contains pool-ID plus the Duplicate Inverted Storage of the QEvt::refCtr_.
Definition qp.hpp:134
std::uint_fast8_t getPoolNum_() const noexcept
Internal function to get the event pool-number of the given event.
Definition qp.hpp:159
QF_EPOOL_TYPE_ ePool_[QF_MAX_EPOOL]
Array of event pools sized for the maximum allowed number of pools.
Definition qp_pkg.hpp:47
std::uint_fast8_t maxPool_
Number of event pools managed by the QF Framework.
Definition qp_pkg.hpp:51
QF Active Object Framework namespace.
void deleteRef_(QEvt const *const evtRef) noexcept
Definition qf_dyn.cpp:307
QEvt const * newRef_(QEvt const *const e, QEvt const *const evtRef) noexcept
Definition qf_dyn.cpp:270
void gc(QEvt const *const e) noexcept
Recycle a mutable (mutable) event.
Definition qf_dyn.cpp:213
std::uint_fast16_t getPoolMin(std::uint_fast8_t const poolNum) noexcept
Definition qf_dyn.cpp:116
std::uint_fast16_t poolGetMaxBlockSize() noexcept
Definition qf_dyn.cpp:103
QF::Attr priv_
Definition qf_act.cpp:69
void poolInit(void *const poolSto, std::uint_fast32_t const poolSize, std::uint_fast16_t const evtSize) noexcept
Definition qf_dyn.cpp:64
constexpr std::uint_fast16_t NO_MARGIN
Definition qp.hpp:1086
QEvt * newX_(std::uint_fast16_t const evtSize, std::uint_fast16_t const margin, enum_t const sig) noexcept
Definition qf_dyn.cpp:134
QP/C++ framework.
Definition qequeue.hpp:42
void QEvt_refCtr_inc_(QEvt const *const e) noexcept
Definition qp_pkg.hpp:81
void QEvt_refCtr_dec_(QEvt const *const e) noexcept
Decrement the refCtr of a const event (requires casting const away)
Definition qp_pkg.hpp:89
std::uint16_t QSignal
The signal of event QP::QEvt.
Definition qp.hpp:122
#define QF_EPOOL_EVENT_SIZE_(p_)
Definition qk.hpp:175
#define QF_EPOOL_PUT_(p_, e_, qsId_)
Definition qk.hpp:182
#define QF_EPOOL_INIT_(p_, poolSto_, poolSize_, evtSize_)
Definition qk.hpp:171
#define QF_EPOOL_GET_(p_, e_, m_, qsId_)
Definition qk.hpp:178
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_MAX_EPOOL
Maximum # event pools in the system (0..15)
Internal (package scope) QP/C++ interface.
#define QF_CONST_CAST_(type_, ptr_)
Definition qp_pkg.hpp:71
Sample QP/C++ port.
#define QS_SIG_PRE(sig_)
Definition qs_dummy.hpp:156
#define QS_TIME_PRE()
Definition qs_dummy.hpp:155
#define QS_MEM_APP()
Definition qs_dummy.hpp:170
#define QS_2U8_PRE(data1_, data2_)
Definition qs_dummy.hpp:152
#define QS_EVS_PRE(size_)
Definition qs_dummy.hpp:157
#define QS_CRIT_EXIT()
Definition qs_dummy.hpp:167
#define QS_MEM_SYS()
Definition qs_dummy.hpp:169
#define QS_END_PRE()
Definition qs_dummy.hpp:150
#define QS_CRIT_ENTRY()
Definition qs_dummy.hpp:166
#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 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