QP/C++  7.4.0-rc.1
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 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_dyn.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#if (QF_MAX_EPOOL > 0U) // mutable events configured?
55
56// unnamed namespace for local definitions with internal linkage
57namespace {
58Q_DEFINE_THIS_MODULE("qf_dyn")
59} // unnamed namespace
60
61//$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
62// Check for the minimum required QP version
63#if (QP_VERSION < 730U) || (QP_VERSION != ((QP_RELEASE^4294967295U) % 0x3E8U))
64#error qpcpp version 7.3.0 or higher required
65#endif
66//$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
67
68//$define${QF::QF-dyn} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
69namespace QP {
70namespace QF {
71
72//${QF::QF-dyn::poolInit} ....................................................
74 void * const poolSto,
75 std::uint_fast32_t const poolSize,
76 std::uint_fast16_t const evtSize) noexcept
77{
78 std::uint_fast8_t const poolNum = priv_.maxPool_;
79
80 // see precondition{qf_dyn,200} and precondition{qf_dyn,201}
83 QF_MEM_SYS();
84
85 Q_REQUIRE_INCRIT(200, poolNum < QF_MAX_EPOOL);
86 if (poolNum > 0U) {
88 QF_EPOOL_EVENT_SIZE_(priv_.ePool_[poolNum - 1U]) < evtSize);
89 }
90 priv_.maxPool_ = poolNum + 1U; // one more pool
91
92 QF_MEM_APP();
94
95 // perform the port-dependent initialization of the event-pool
96 QF_EPOOL_INIT_(priv_.ePool_[poolNum], poolSto, poolSize, evtSize);
97
98 #ifdef Q_SPY
99 // generate the object-dictionary entry for the initialized pool
100 {
101 std::uint8_t obj_name[9] = "EvtPool?";
102 obj_name[7] = static_cast<std::uint8_t>(
103 static_cast<std::uint8_t>('0')
104 + static_cast<std::uint8_t>(poolNum + 1U));
105 QS::obj_dict_pre_(&priv_.ePool_[poolNum],
106 reinterpret_cast<char *>(&obj_name[0]));
107 }
108 #endif // Q_SPY
109}
110
111//${QF::QF-dyn::poolGetMaxBlockSize} .........................................
112std::uint_fast16_t poolGetMaxBlockSize() noexcept {
115 QF_MEM_SYS();
116 std::uint_fast16_t const max_size =
118 QF_MEM_APP();
119 QF_CRIT_EXIT();
120
121 return max_size;
122}
123
124//${QF::QF-dyn::getPoolMin} ..................................................
125std::uint_fast16_t getPoolMin(std::uint_fast8_t const poolNum) noexcept {
128 QF_MEM_SYS();
129
130 Q_REQUIRE_INCRIT(400, (poolNum <= QF_MAX_EPOOL)
131 && (0U < poolNum) && (poolNum <= priv_.maxPool_));
132
133 std::uint_fast16_t const min = static_cast<std::uint_fast16_t>(
134 priv_.ePool_[poolNum - 1U].getNMin());
135
136 QF_MEM_APP();
137 QF_CRIT_EXIT();
138
139 return min;
140}
141
142//${QF::QF-dyn::newX_} .......................................................
144 std::uint_fast16_t const evtSize,
145 std::uint_fast16_t const margin,
146 enum_t const sig) noexcept
147{
150 QF_MEM_SYS();
151
152 // find the pool id that fits the requested event size...
153 std::uint_fast8_t poolNum = 0U; // zero-based poolNum initially
154 for (; poolNum < priv_.maxPool_; ++poolNum) {
155 if (evtSize <= QF_EPOOL_EVENT_SIZE_(priv_.ePool_[poolNum])) {
156 break;
157 }
158 }
159
160 // precondition:
161 // - cannot run out of registered pools
162 Q_REQUIRE_INCRIT(300, poolNum < priv_.maxPool_);
163
164 ++poolNum; // convert to 1-based poolNum
165
166 QF_MEM_APP();
167 QF_CRIT_EXIT();
168
169 // get event e (port-dependent)...
170 QEvt *e;
171 #ifdef Q_SPY
172 QF_EPOOL_GET_(priv_.ePool_[poolNum - 1U], e,
173 ((margin != NO_MARGIN) ? margin : 0U),
174 static_cast<std::uint_fast8_t>(QS_EP_ID) + poolNum);
175 #else
176 QF_EPOOL_GET_(priv_.ePool_[poolNum - 1U], e,
177 ((margin != NO_MARGIN) ? margin : 0U), 0U);
178 #endif
179
180 if (e != nullptr) { // was e allocated correctly?
181 e->sig = static_cast<QSignal>(sig); // set the signal
182 e->refCtr_ = 0U; // initialize the reference counter to 0
183 e->evtTag_ = static_cast<std::uint8_t>(QEvt::MARKER | poolNum);
184
186 QS_MEM_SYS();
187 QS_BEGIN_PRE_(QS_QF_NEW,
188 static_cast<std::uint_fast8_t>(QS_EP_ID) + poolNum)
189 QS_TIME_PRE_(); // timestamp
190 QS_EVS_PRE_(evtSize); // the size of the event
191 QS_SIG_PRE_(sig); // the signal of the event
192 QS_END_PRE_()
193 QS_MEM_APP();
194 QS_CRIT_EXIT();
195 }
196 else { // event was not allocated
197
199 // This assertion means that the event allocation failed,
200 // and this failure cannot be tolerated. The most frequent
201 // reason is an event leak in the application.
202 Q_ASSERT_INCRIT(320, margin != NO_MARGIN);
203
204 QS_MEM_SYS();
205 QS_BEGIN_PRE_(QS_QF_NEW_ATTEMPT,
206 static_cast<std::uint_fast8_t>(QS_EP_ID) + poolNum)
207 QS_TIME_PRE_(); // timestamp
208 QS_EVS_PRE_(evtSize); // the size of the event
209 QS_SIG_PRE_(sig); // the signal of the event
210 QS_END_PRE_()
211 QS_MEM_APP();
212
213 QF_CRIT_EXIT();
214 }
215
216 // the returned event e is guaranteed to be valid (not NULL)
217 // if we can't tolerate failed allocation
218 return e;
219}
220
221//${QF::QF-dyn::gc} ..........................................................
222void gc(QEvt const * const e) noexcept {
226
227 std::uint_fast8_t const poolNum = e->getPoolNum_();
228
229 if (poolNum != 0U) { // is it a pool event (mutable)?
230 QF_MEM_SYS();
231
232 if (e->refCtr_ > 1U) { // isn't this the last reference?
233
234 QS_BEGIN_PRE_(QS_QF_GC_ATTEMPT,
235 static_cast<std::uint_fast8_t>(QS_EP_ID) + poolNum)
236 QS_TIME_PRE_(); // timestamp
237 QS_SIG_PRE_(e->sig); // the signal of the event
238 QS_2U8_PRE_(poolNum, e->refCtr_); // poolNum & refCtr
239 QS_END_PRE_()
240
241 QEvt_refCtr_dec_(e); // decrement the ref counter
242
243 QF_MEM_APP();
244 QF_CRIT_EXIT();
245 }
246 else { // this is the last reference to this event, recycle it
247
248 QS_BEGIN_PRE_(QS_QF_GC,
249 static_cast<std::uint_fast8_t>(QS_EP_ID) + poolNum)
250 QS_TIME_PRE_(); // timestamp
251 QS_SIG_PRE_(e->sig); // the signal of the event
252 QS_2U8_PRE_(poolNum, e->refCtr_); // poolNum & refCtr
253 QS_END_PRE_()
254
255 // pool number must be in range
256 Q_ASSERT_INCRIT(410, (poolNum <= priv_.maxPool_)
257 && (poolNum <= QF_MAX_EPOOL));
258 QF_MEM_APP();
259 QF_CRIT_EXIT();
260
261 // NOTE: casting 'const' away is legit because it's a pool event
262 #ifdef Q_SPY
263 QF_EPOOL_PUT_(priv_.ePool_[poolNum - 1U],
264 QF_CONST_CAST_(QEvt*, e),
265 static_cast<std::uint_fast8_t>(QS_EP_ID) + poolNum);
266 #else
267 QF_EPOOL_PUT_(priv_.ePool_[poolNum - 1U],
268 QF_CONST_CAST_(QEvt*, e), 0U);
269 #endif
270 }
271 }
272 else {
273 QF_CRIT_EXIT();
274 }
275}
276
277//${QF::QF-dyn::newRef_} .....................................................
278QEvt const * newRef_(
279 QEvt const * const e,
280 QEvt const * const evtRef) noexcept
281{
282 #ifdef Q_UNSAFE
283 Q_UNUSED_PAR(evtRef);
284 #endif
285
288
290
291 std::uint_fast8_t const poolNum = e->getPoolNum_();
292
293 Q_REQUIRE_INCRIT(501, (poolNum != 0U)
294 && (evtRef == nullptr));
295
296 QEvt_refCtr_inc_(e); // increments the ref counter
297
298 QS_MEM_SYS();
299 QS_BEGIN_PRE_(QS_QF_NEW_REF,
300 static_cast<std::uint_fast8_t>(QS_EP_ID) + poolNum)
301 QS_TIME_PRE_(); // timestamp
302 QS_SIG_PRE_(e->sig); // the signal of the event
303 QS_2U8_PRE_(poolNum, e->refCtr_); // poolNum & refCtr
304 QS_END_PRE_()
305 QS_MEM_APP();
306
307 QF_CRIT_EXIT();
308
309 return e;
310}
311
312//${QF::QF-dyn::deleteRef_} ..................................................
313void deleteRef_(QEvt const * const evtRef) noexcept {
316
317 QEvt const * const e = evtRef;
319
320 #ifdef Q_SPY
321 std::uint_fast8_t const poolNum = e->getPoolNum_();
322 #endif
323
324 QS_MEM_SYS();
325 QS_BEGIN_PRE_(QS_QF_DELETE_REF,
326 static_cast<std::uint_fast8_t>(QS_EP_ID) + poolNum)
327 QS_TIME_PRE_(); // timestamp
328 QS_SIG_PRE_(e->sig); // the signal of the event
329 QS_2U8_PRE_(poolNum, e->refCtr_); // poolNum & refCtr
330 QS_END_PRE_()
331 QS_MEM_APP();
332
333 QF_CRIT_EXIT();
334
335 #if (QF_MAX_EPOOL > 0U)
336 gc(evtRef); // recycle the referenced event
337 #endif
338}
339
340} // namespace QF
341} // namespace QP
342//$enddef${QF::QF-dyn} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
343
344#endif // (QF_MAX_EPOOL > 0U) mutable events configured
Event class.
Definition qp.hpp:137
static constexpr std::uint8_t MARKER
Definition qp.hpp:144
QSignal sig
Definition qp.hpp:139
std::uint8_t volatile refCtr_
Definition qp.hpp:140
std::uint8_t evtTag_
Definition qp.hpp:141
std::uint_fast8_t getPoolNum_() const noexcept
Definition qp.hpp:165
static bool verify_(QEvt const *const e) noexcept
Definition qp.hpp:161
QF_EPOOL_TYPE_ ePool_[QF_MAX_EPOOL]
Array of event pools sized for the maximum allowed number of pools.
Definition qp_pkg.hpp:55
std::uint_fast8_t maxPool_
Number of event pools managed by the QF Framework.
Definition qp_pkg.hpp:59
void deleteRef_(QEvt const *const evtRef) noexcept
Definition qf_dyn.cpp:313
QEvt const * newRef_(QEvt const *const e, QEvt const *const evtRef) noexcept
Definition qf_dyn.cpp:278
void gc(QEvt const *const e) noexcept
Definition qf_dyn.cpp:222
std::uint_fast16_t getPoolMin(std::uint_fast8_t const poolNum) noexcept
Definition qf_dyn.cpp:125
std::uint_fast16_t poolGetMaxBlockSize() noexcept
Definition qf_dyn.cpp:112
QF::Attr priv_
Definition qf_act.cpp:78
void poolInit(void *const poolSto, std::uint_fast32_t const poolSize, std::uint_fast16_t const evtSize) noexcept
Definition qf_dyn.cpp:73
constexpr std::uint_fast16_t NO_MARGIN
Definition qp.hpp:1095
QEvt * newX_(std::uint_fast16_t const evtSize, std::uint_fast16_t const margin, enum_t const sig) noexcept
Definition qf_dyn.cpp:143
QP/C++ framework.
Definition qequeue.hpp:50
void QEvt_refCtr_inc_(QEvt const *const e) noexcept
Definition qp_pkg.hpp:92
@ QS_EP_ID
offset for event-pool IDs
Definition qs.hpp:227
void QEvt_refCtr_dec_(QEvt const *const e) noexcept
Decrement the refCtr of a const event (requires casting const away)
Definition qp_pkg.hpp:96
std::uint16_t QSignal
Definition qp.hpp:128
@ QS_QF_NEW
new event was created
Definition qs.hpp:111
@ QS_QF_GC
garbage collection
Definition qs.hpp:113
@ QS_QF_DELETE_REF
an event reference is about to be deleted
Definition qs.hpp:125
@ QS_QF_NEW_ATTEMPT
an attempt to allocate an event failed
Definition qs.hpp:102
@ QS_QF_GC_ATTEMPT
garbage collection attempt
Definition qs.hpp:112
@ QS_QF_NEW_REF
new event reference was created
Definition qs.hpp:110
#define QF_EPOOL_EVENT_SIZE_(p_)
Definition qk.hpp:184
#define QF_EPOOL_PUT_(p_, e_, qsId_)
Definition qk.hpp:191
#define QF_EPOOL_INIT_(p_, poolSto_, poolSize_, evtSize_)
Definition qk.hpp:180
#define QF_EPOOL_GET_(p_, e_, m_, qsId_)
Definition qk.hpp:187
int enum_t
Definition qp.hpp:106
#define QF_MEM_APP()
Definition qp.hpp:1331
#define Q_UNUSED_PAR(par_)
Definition qp.hpp:539
#define QF_MEM_SYS()
Definition qp.hpp:1326
#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:79
Sample QP/C++ port.
#define QS_TIME_PRE_()
Definition qs.hpp:473
#define QS_MEM_APP()
Definition qs.hpp:610
#define QS_CRIT_EXIT()
Definition qs.hpp:600
#define QS_MEM_SYS()
Definition qs.hpp:605
#define QS_CRIT_ENTRY()
Definition qs.hpp:595
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 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