QP/C++  7.0.1
Real-Time Embedded Framework
qf_dyn.cpp
Go to the documentation of this file.
1//============================================================================
2// QP/C++ Real-Time Embedded Framework (RTEF)
3// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
4//
5// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
6//
7// This software is dual-licensed under the terms of the open source GNU
8// General Public License version 3 (or any later version), or alternatively,
9// under the terms of one of the closed source Quantum Leaps commercial
10// licenses.
11//
12// The terms of the open source GNU General Public License version 3
13// can be found at: <www.gnu.org/licenses/gpl-3.0>
14//
15// The terms of the closed source Quantum Leaps commercial licenses
16// can be found at: <www.state-machine.com/licensing>
17//
18// Redistributions in source code must retain this top-level comment block.
19// Plagiarizing this software to sidestep the license obligations is illegal.
20//
21// Contact information:
22// <www.state-machine.com>
23// <info@state-machine.com>
24//============================================================================
30
31#define QP_IMPL // this is QP implementation
32#include "qf_port.hpp" // QF port
33#include "qf_pkg.hpp" // QF package-scope interface
34#include "qassert.h" // QP embedded systems-friendly assertions
35#ifdef Q_SPY // QS software tracing enabled?
36 #include "qs_port.hpp" // QS port
37 #include "qs_pkg.hpp" // QS facilities for pre-defined trace records
38#else
39 #include "qs_dummy.hpp" // disable the QS software tracing
40#endif // Q_SPY
41
42// unnamed namespace for local definitions with internal linkage
43namespace {
44
46
47} // unnamed namespace
48
49//============================================================================
50namespace QP {
51
52// Package-scope objects *****************************************************
53QF_EPOOL_TYPE_ QF_pool_[QF_MAX_EPOOL]; // allocate the event pools
54std::uint_fast8_t QF_maxPool_; // number of initialized event pools
55
56//............................................................................
57void QF::poolInit(void * const poolSto,
58 std::uint_fast32_t const poolSize,
59 std::uint_fast16_t const evtSize) noexcept
60{
62 Q_REQUIRE_ID(200, QF_maxPool_ < QF_MAX_EPOOL);
63
65 Q_REQUIRE_ID(201, (QF_maxPool_ == 0U)
67 < evtSize));
68
69 QF_EPOOL_INIT_(QF_pool_[QF_maxPool_], poolSto, poolSize, evtSize);
70 ++QF_maxPool_; // one more pool
71
72#ifdef Q_SPY
73 // generate the object-dictionary entry for the initialized pool
74 char obj_name[9] = "EvtPool?";
75 obj_name[7] = static_cast<char>(
76 static_cast<std::int8_t>('0')
77 + static_cast<std::int8_t>(QF_maxPool_));
78 QS::obj_dict_pre_(&QF_pool_[QF_maxPool_ - 1U], &obj_name[0]);
79#endif // Q_SPY
80}
81
82//============================================================================
83QEvt *QF::newX_(std::uint_fast16_t const evtSize,
84 std::uint_fast16_t const margin, enum_t const sig) noexcept
85{
86 std::uint_fast8_t idx;
87
88 // find the pool id that fits the requested event size ...
89 for (idx = 0U; idx < QF_maxPool_; ++idx) {
90 if (evtSize <= QF_EPOOL_EVENT_SIZE_(QF_pool_[idx])) {
91 break;
92 }
93 }
94 // cannot run out of registered pools
95 Q_ASSERT_ID(310, idx < QF_maxPool_);
96
97 // get e -- platform-dependent
98 QEvt *e;
99
100#ifdef Q_SPY
101 QF_EPOOL_GET_(QF_pool_[idx], e, ((margin != QF_NO_MARGIN) ? margin : 0U),
102 static_cast<std::uint_fast8_t>(QS_EP_ID) + idx + 1U);
103#else
104 QF_EPOOL_GET_(QF_pool_[idx], e, ((margin != QF_NO_MARGIN) ? margin : 0U),
105 0U);
106#endif
107
108 // was e allocated correctly?
110 if (e != nullptr) {
111 e->sig = static_cast<QSignal>(sig); // set the signal
112 e->poolId_ = static_cast<std::uint8_t>(idx + 1U); // store pool ID
113 e->refCtr_ = 0U; // initialize the reference counter to 0
114
116 static_cast<std::uint_fast8_t>(QS_EP_ID)
117 + static_cast<std::uint_fast8_t>(e->poolId_))
118 QS_TIME_PRE_(); // timestamp
119 QS_EVS_PRE_(evtSize); // the size of the evt
120 QS_SIG_PRE_(sig); // the signal of the evt
122 }
123 else {
124 // This assertion means that the event allocation failed,
125 // and this failure cannot be tolerated. The most frequent
126 // reason is an event leak in the application.
127 Q_ASSERT_ID(320, margin != QF_NO_MARGIN);
128
130 static_cast<std::uint_fast8_t>(QS_EP_ID) + idx + 1U)
131 QS_TIME_PRE_(); // timestamp
132 QS_EVS_PRE_(evtSize); // the size of the evt
133 QS_SIG_PRE_(sig); // the signal of the evt
135 }
136 return e; // can't be NULL if we can't tolerate bad allocation
137}
138
139//============================================================================
140void QF::gc(QEvt const * const e) noexcept {
141 // is it a dynamic event?
142 if (e->poolId_ != 0U) {
144 QF_CRIT_E_();
145
146 // isn't this the last reference?
147 if (e->refCtr_ > 1U) {
148
150 static_cast<std::uint_fast8_t>(QS_EP_ID)
151 + static_cast<std::uint_fast8_t>(e->poolId_))
152 QS_TIME_PRE_(); // timestamp
153 QS_SIG_PRE_(e->sig); // the signal of the event
154 QS_2U8_PRE_(e->poolId_, e->refCtr_); // pool Id & refCtr
156
157 QF_EVT_REF_CTR_DEC_(e); // decrement the ref counter
158
159 QF_CRIT_X_();
160 }
161 // this is the last reference to this event, recycle it
162 else {
163 std::uint_fast8_t const idx =
164 static_cast<std::uint_fast8_t>(e->poolId_) - 1U;
165
167 static_cast<std::uint_fast8_t>(QS_EP_ID)
168 + static_cast<std::uint_fast8_t>(e->poolId_))
169 QS_TIME_PRE_(); // timestamp
170 QS_SIG_PRE_(e->sig); // the signal of the event
171 QS_2U8_PRE_(e->poolId_, e->refCtr_);
173
174 QF_CRIT_X_();
175
176 // pool ID must be in range
177 Q_ASSERT_ID(410, idx < QF_maxPool_);
178
179#ifdef Q_EVT_XTOR
180 // explicitly exectute the destructor'
181 // NOTE: casting 'const' away is legitimate,
182 // because it's a pool event
183 QF_EVT_CONST_CAST_(e)->~QEvt(); // xtor,
184#endif
185
186#ifdef Q_SPY
187 // cast 'const' away, which is OK, because it's a pool event
189 static_cast<std::uint_fast8_t>(QS_EP_ID)
190 + static_cast<std::uint_fast8_t>(e->poolId_));
191#else
193#endif
194 }
195 }
196}
197
198//============================================================================
199QEvt const *QF::newRef_(QEvt const * const e,
200 QEvt const * const evtRef) noexcept
201{
204 Q_REQUIRE_ID(500, (e->poolId_ != 0U)
205 && (evtRef == nullptr));
206
208 QF_CRIT_E_();
209
210 QF_EVT_REF_CTR_INC_(e); // increments the ref counter
211
213 static_cast<std::uint_fast8_t>(QS_EP_ID)
214 + static_cast<std::uint_fast8_t>(e->poolId_))
215 QS_TIME_PRE_(); // timestamp
216 QS_SIG_PRE_(e->sig); // the signal of the event
217 QS_2U8_PRE_(e->poolId_, e->refCtr_); // pool Id & ref Count
219
220 QF_CRIT_X_();
221
222 return e;
223}
224
225//============================================================================
226void QF::deleteRef_(QEvt const * const evtRef) noexcept {
228
230 static_cast<std::uint_fast8_t>(QS_EP_ID)
231 + static_cast<std::uint_fast8_t>(evtRef->poolId_))
232 QS_TIME_PRE_(); // timestamp
233 QS_SIG_PRE_(evtRef->sig); // the signal of the event
234 QS_2U8_PRE_(evtRef->poolId_, evtRef->refCtr_); // pool Id & ref Count
236
237 gc(evtRef); // recycle the referenced event
238}
239
240//============================================================================
244std::uint_fast16_t QF::poolGetMaxBlockSize(void) noexcept {
246}
247
248} // namespace QP
static void gc(QEvt const *const e) noexcept
Recycle a dynamic event.
Definition: qf_dyn.cpp:140
static void deleteRef_(QEvt const *const evtRef) noexcept
Internal QF implementation of deleting event reference.
Definition: qf_dyn.cpp:226
static QEvt * newX_(std::uint_fast16_t const evtSize, std::uint_fast16_t const margin, enum_t const sig) noexcept
Internal QF implementation of creating new dynamic mutable event.
Definition: qf_dyn.cpp:83
static std::uint_fast16_t poolGetMaxBlockSize(void) noexcept
Obtain the block size of any registered event pools.
Definition: qf_dyn.cpp:244
static void poolInit(void *const poolSto, std::uint_fast32_t const poolSize, std::uint_fast16_t const evtSize) noexcept
Event pool initialization for dynamic allocation of events.
Definition: qf_dyn.cpp:57
static QEvt const * newRef_(QEvt const *const e, QEvt const *const evtRef) noexcept
Internal QF implementation of creating new event reference.
Definition: qf_dyn.cpp:199
static void obj_dict_pre_(void const *const obj, char const *const name) noexcept
Output object dictionary record.
Definition: qs.cpp:817
namespace associated with the QP/C++ framework
Definition: exa_native.dox:1
std::uint_fast16_t const QF_NO_MARGIN
special value of margin that causes asserting failure in case event allocation or event posting fails
Definition: qf.hpp:1211
void QF_EVT_REF_CTR_DEC_(QEvt const *const e) noexcept
decrement the refCtr_ of an event e
Definition: qf_pkg.hpp:147
@ QS_EP_ID
offset for event-pool IDs
Definition: qs.hpp:705
@ QS_QF_DELETE_REF
an event reference is about to be deleted
Definition: qs.hpp:627
@ QS_QF_GC_ATTEMPT
garbage collection attempt
Definition: qs.hpp:614
@ QS_QF_GC
garbage collection
Definition: qs.hpp:615
@ QS_QF_NEW_ATTEMPT
an attempt to allocate an event failed
Definition: qs.hpp:604
@ QS_QF_NEW_REF
new event reference was created
Definition: qs.hpp:612
@ QS_QF_NEW
new event was created
Definition: qs.hpp:613
std::uint_fast8_t QF_maxPool_
Definition: qf_dyn.cpp:54
QF_EPOOL_TYPE_ QF_pool_[QF_MAX_EPOOL]
allocate event pools
Definition: qf_dyn.cpp:53
std::uint16_t QSignal
QSignal represents the signal of an event.
Definition: qep.hpp:136
void QF_EVT_REF_CTR_INC_(QEvt const *const e) noexcept
increment the refCtr_ of an event e
Definition: qf_pkg.hpp:142
Customizable and memory-efficient assertions for embedded systems.
#define Q_DEFINE_THIS_MODULE(name_)
Definition: qassert.h:102
#define Q_ASSERT_ID(id_, test_)
Definition: qassert.h:135
#define Q_REQUIRE_ID(id_, test_)
Definition: qassert.h:252
int enum_t
alias for enumerations used for event signals
Definition: qep.hpp:67
Internal (package scope) QF/C++ interface.
#define QF_CRIT_STAT_
This is an internal macro for defining the critical section status type.
Definition: qf_pkg.hpp:48
#define QF_EVT_CONST_CAST_(e_)
helper macro to cast const away from an event pointer e_
Definition: qf_pkg.hpp:35
#define QF_CRIT_X_()
This is an internal macro for exiting a critical section.
Definition: qf_pkg.hpp:69
#define QF_CRIT_E_()
This is an internal macro for entering a critical section.
Definition: qf_pkg.hpp:58
#define QS_CRIT_STAT_
This is an internal macro for defining the critical section status type.
Definition: qs.hpp:978
#define QS_TIME_PRE_()
Internal macro to output time stamp to a QS record.
Definition: qs.hpp:748
Internal (package scope) QS/C++ interface.
#define QS_BEGIN_PRE_(rec_, qs_id_)
Internal QS macro to begin a predefined QS record with critical section.
Definition: qs_pkg.hpp:111
#define QS_BEGIN_NOCRIT_PRE_(rec_, qs_id_)
Internal QS macro to begin a predefined QS record without critical section.
Definition: qs_pkg.hpp:133
#define QS_END_NOCRIT_PRE_()
Internal QS macro to end a predefiend QS record without critical section.
Definition: qs_pkg.hpp:142
#define QS_2U8_PRE_(data1_, data2_)
Internal QS macro to output 2 unformatted uint8_t data elements.
Definition: qs_pkg.hpp:165
#define QS_EVS_PRE_(size_)
Definition: qs_pkg.hpp:235
#define QS_END_PRE_()
Internal QS macro to end a predefined QS record with critical section.
Definition: qs_pkg.hpp:122
#define QF_EPOOL_PUT_(p_, e_, qs_id_)
Definition: qv.hpp:105
#define QF_EPOOL_GET_(p_, e_, m_, qs_id_)
Definition: qv.hpp:103
#define QF_EPOOL_EVENT_SIZE_(p_)
Definition: qv.hpp:102
#define QF_EPOOL_TYPE_
Definition: qv.hpp:99
#define QF_EPOOL_INIT_(p_, poolSto_, poolSize_, evtSize_)
Definition: qv.hpp:100
QEvt base class.
Definition: qep.hpp:155
QSignal sig
signal of the event instance
Definition: qep.hpp:156
std::uint8_t volatile refCtr_
reference counter
Definition: qep.hpp:158
std::uint8_t poolId_
pool ID (0 for static event)
Definition: qep.hpp:157