QP/C++ 6.9.3
qf_dyn.cpp
Go to the documentation of this file.
1 
38 #define QP_IMPL // this is QP implementation
39 #include "qf_port.hpp" // QF port
40 #include "qf_pkg.hpp" // QF package-scope interface
41 #include "qassert.h" // QP embedded systems-friendly assertions
42 #ifdef Q_SPY // QS software tracing enabled?
43  #include "qs_port.hpp" // QS port
44  #include "qs_pkg.hpp" // QS facilities for pre-defined trace records
45 #else
46  #include "qs_dummy.hpp" // disable the QS software tracing
47 #endif // Q_SPY
48 
49 namespace QP {
50 
51 Q_DEFINE_THIS_MODULE("qf_dyn")
52 
53 // Package-scope objects *****************************************************
54 QF_EPOOL_TYPE_ QF_pool_[QF_MAX_EPOOL]; // allocate the event pools
55 std::uint_fast8_t QF_maxPool_; // number of initialized event pools
56 
57 //****************************************************************************
84 void QF::poolInit(void * const poolSto,
85  std::uint_fast32_t const poolSize,
86  std::uint_fast16_t const evtSize) noexcept
87 {
90  < static_cast<std::uint_fast8_t>(Q_DIM(QF_pool_)));
91 
92  // last initialized event size
93  std::uint_fast16_t const lastEvtSize = ((QF_maxPool_ ==0U)
94  ? 0U
96 
98  Q_REQUIRE_ID(201, (QF_maxPool_ == 0U)
99  || (lastEvtSize < evtSize));
100 
101  QF_EPOOL_INIT_(QF_pool_[QF_maxPool_], poolSto, poolSize, evtSize);
102  ++QF_maxPool_; // one more pool
103 
104 #ifdef Q_SPY
105  // generate the object-dictionary entry for the initialized pool
106  char_t obj_name[9] = "EvtPool?";
107  obj_name[7] = static_cast<char_t>(
108  static_cast<std::int8_t>('0')
109  + static_cast<std::int8_t>(QF_maxPool_));
110  QS::obj_dict_pre_(&QF_pool_[QF_maxPool_ - 1U], &obj_name[0]);
111 #endif // Q_SPY
112 }
113 
114 //****************************************************************************
141  std::uint_fast16_t const margin, enum_t const sig) noexcept
142 {
143  std::uint_fast8_t idx;
144 
145  // find the pool id that fits the requested event size ...
146  for (idx = 0U; idx < QF_maxPool_; ++idx) {
147  if (evtSize <= QF_EPOOL_EVENT_SIZE_(QF_pool_[idx])) {
148  break;
149  }
150  }
151  // cannot run out of registered pools
152  Q_ASSERT_ID(310, idx < QF_maxPool_);
153 
155  // get e -- platform-dependent
156  QEvt *e;
157 
158 #ifdef Q_SPY
159  QF_EPOOL_GET_(QF_pool_[idx], e, ((margin != QF_NO_MARGIN) ? margin : 0U),
160  static_cast<std::uint_fast8_t>(QS_EP_ID) + idx + 1U);
161 #else
162  QF_EPOOL_GET_(QF_pool_[idx], e, ((margin != QF_NO_MARGIN) ? margin : 0U),
163  0U);
164 #endif
165 
166  // was e allocated correctly?
167  if (e != nullptr) {
168  e->sig = static_cast<QSignal>(sig); // set the signal
169  e->poolId_ = static_cast<std::uint8_t>(idx + 1U); // store pool ID
170  e->refCtr_ = 0U; // initialize the reference counter to 0
171 
173  static_cast<std::uint_fast8_t>(QS_EP_ID)
174  + static_cast<std::uint_fast8_t>(e->poolId_))
175  QS_TIME_PRE_(); // timestamp
176  QS_EVS_PRE_(evtSize); // the size of the evt
177  QS_SIG_PRE_(sig); // the signal of the evt
178  QS_END_PRE_()
179  }
180  else {
181  // This assertion means that the event allocation failed,
182  // and this failure cannot be tolerated. The most frequent
183  // reason is an event leak in the application.
184  Q_ASSERT_ID(320, margin != QF_NO_MARGIN);
185 
187  static_cast<std::uint_fast8_t>(QS_EP_ID) + idx + 1U)
188  QS_TIME_PRE_(); // timestamp
189  QS_EVS_PRE_(evtSize); // the size of the evt
190  QS_SIG_PRE_(sig); // the signal of the evt
191  QS_END_PRE_()
192  }
193  return e; // can't be NULL if we can't tolerate bad allocation
194 }
195 
196 //****************************************************************************
219 void QF::gc(QEvt const * const e) noexcept {
220  // is it a dynamic event?
221  if (e->poolId_ != 0U) {
223  QF_CRIT_E_();
224 
225  // isn't this the last reference?
226  if (e->refCtr_ > 1U) {
227 
229  static_cast<std::uint_fast8_t>(QS_EP_ID)
230  + static_cast<std::uint_fast8_t>(e->poolId_))
231  QS_TIME_PRE_(); // timestamp
232  QS_SIG_PRE_(e->sig); // the signal of the event
233  QS_2U8_PRE_(e->poolId_, e->refCtr_); // pool Id & refCtr
235 
236  QF_EVT_REF_CTR_DEC_(e); // decrement the ref counter
237 
238  QF_CRIT_X_();
239  }
240  // this is the last reference to this event, recycle it
241  else {
242  std::uint_fast8_t const idx =
243  static_cast<std::uint_fast8_t>(e->poolId_) - 1U;
244 
246  static_cast<std::uint_fast8_t>(QS_EP_ID)
247  + static_cast<std::uint_fast8_t>(e->poolId_))
248  QS_TIME_PRE_(); // timestamp
249  QS_SIG_PRE_(e->sig); // the signal of the event
250  QS_2U8_PRE_(e->poolId_, e->refCtr_);
252 
253  QF_CRIT_X_();
254 
255  // pool ID must be in range
256  Q_ASSERT_ID(410, idx < QF_maxPool_);
257 
258 #ifdef Q_EVT_VIRTUAL
259  // explicitly exectute the destructor'
260  // NOTE: casting 'const' away is legitimate,
261  // because it's a pool event
262  QF_EVT_CONST_CAST_(e)->~QEvt(); // xtor,
263 #endif
264 
265 #ifdef Q_SPY
266  // cast 'const' away, which is OK, because it's a pool event
268  static_cast<std::uint_fast8_t>(QS_EP_ID)
269  + static_cast<std::uint_fast8_t>(e->poolId_));
270 #else
272 #endif
273  }
274  }
275 }
276 
277 //****************************************************************************
291 QEvt const *QF::newRef_(QEvt const * const e,
292  QEvt const * const evtRef) noexcept
293 {
296  Q_REQUIRE_ID(500, (e->poolId_ != 0U)
297  && (evtRef == nullptr));
298 
300  QF_CRIT_E_();
301 
302  QF_EVT_REF_CTR_INC_(e); // increments the ref counter
303 
305  static_cast<std::uint_fast8_t>(QS_EP_ID)
306  + static_cast<std::uint_fast8_t>(e->poolId_))
307  QS_TIME_PRE_(); // timestamp
308  QS_SIG_PRE_(e->sig); // the signal of the event
309  QS_2U8_PRE_(e->poolId_, e->refCtr_); // pool Id & ref Count
311 
312  QF_CRIT_X_();
313 
314  return e;
315 }
316 
317 //****************************************************************************
327 void QF::deleteRef_(QEvt const * const evtRef) noexcept {
329 
331  static_cast<std::uint_fast8_t>(QS_EP_ID)
332  + static_cast<std::uint_fast8_t>(evtRef->poolId_))
333  QS_TIME_PRE_(); // timestamp
334  QS_SIG_PRE_(evtRef->sig); // the signal of the event
335  QS_2U8_PRE_(evtRef->poolId_, evtRef->refCtr_); // pool Id & ref Count
336  QS_END_PRE_()
337 
338  gc(evtRef); // recycle the referenced event
339 }
340 
341 //****************************************************************************
347 }
348 
349 } // namespace QP
350 
unsigned int uint_fast16_t
fast at-least 16-bit unsigned int
Definition: 16bit/stdint.h:38
unsigned char uint8_t
exact-width 8-bit unsigned int
Definition: 16bit/stdint.h:29
unsigned int uint_fast8_t
fast at-least 8-bit unsigned int
Definition: 16bit/stdint.h:36
unsigned long uint_fast32_t
fast at-least 32-bit unsigned int
Definition: 16bit/stdint.h:40
signed char int8_t
exact-width 8-bit signed int
Definition: 16bit/stdint.h:24
QF services.
Definition: qf.hpp:496
static void gc(QEvt const *const e) noexcept
Recycle a dynamic event.
Definition: qf_dyn.cpp:219
static void deleteRef_(QEvt const *const evtRef) noexcept
Internal QF implementation of deleting event reference.
Definition: qf_dyn.cpp:327
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 event.
Definition: qf_dyn.cpp:140
static std::uint_fast16_t poolGetMaxBlockSize(void) noexcept
Obtain the block size of any registered event pools.
Definition: qf_dyn.cpp:345
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:291
static void obj_dict_pre_(void const *const obj, char_t const *name) noexcept
Output object dictionary record.
Definition: qs.cpp:954
#define QF_EPOOL_PUT_(p_, e_, qs_id_)
Platform-dependent macro defining how QF should return an event e_ to the event pool p_.
Definition: macros.hpp:143
#define QF_EPOOL_GET_(p_, e_, m_, qs_id_)
Platform-dependent macro defining how QF should obtain an event e_ from the event pool p_.
Definition: macros.hpp:134
#define QF_EPOOL_EVENT_SIZE_(p_)
Platform-dependent macro defining how QF should obtain the event pool block-size.
Definition: macros.hpp:126
#define QF_EPOOL_TYPE_
This macro defines the type of the event pool used in this QF port.
Definition: macros.hpp:102
#define QF_EPOOL_INIT_(p_, poolSto_, poolSize_, evtSize_)
Platform-dependent macro defining the event pool initialization.
Definition: macros.hpp:117
namespace associated with the QP/C++ framework
Definition: struct.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:627
@ QS_EP_ID
offset for event-pool IDs
Definition: qs.hpp:229
@ QS_QF_DELETE_REF
an event reference is about to be deleted
Definition: qs.hpp:118
@ QS_QF_GC_ATTEMPT
garbage collection attempt
Definition: qs.hpp:105
@ QS_QF_GC
garbage collection
Definition: qs.hpp:106
@ QS_QF_NEW_ATTEMPT
an attempt to allocate an event failed
Definition: qs.hpp:95
@ QS_QF_NEW_REF
new event reference was created
Definition: qs.hpp:103
@ QS_QF_NEW
new event was created
Definition: qs.hpp:104
void QF_EVT_REF_CTR_INC_(QEvt const *const e) noexcept
increment the refCtr_ of an event e
Definition: qf_pkg.hpp:150
std::uint_fast8_t QF_maxPool_
Definition: qf_dyn.cpp:55
QF_EPOOL_TYPE_ QF_pool_[QF_MAX_EPOOL]
allocate event pools
Definition: qf_dyn.cpp:54
std::uint16_t QSignal
QSignal represents the signal of an event.
Definition: qep.hpp:146
void QF_EVT_REF_CTR_DEC_(QEvt const *const e) noexcept
decrement the refCtr_ of an event e
Definition: qf_pkg.hpp:155
Customizable and memory-efficient assertions for embedded systems.
#define Q_DEFINE_THIS_MODULE(name_)
Define the user-specified module name for assertions in this file.
Definition: qassert.h:120
char char_t
typedef for character strings.
Definition: qassert.h:77
#define Q_ASSERT_ID(id_, test_)
General purpose assertion with user-specified assertion-id.
Definition: qassert.h:155
#define Q_REQUIRE_ID(id_, test_)
Assertion for checking preconditions with user-specified assertion-id.
Definition: qassert.h:279
#define Q_DIM(array_)
Helper macro to calculate static dimension of a 1-dim array_.
Definition: qassert.h:337
int enum_t
alias for enumerations used for event signals
Definition: qep.hpp:82
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:56
#define QF_EVT_CONST_CAST_(e_)
helper macro to cast const away from an event pointer e_
Definition: qf_pkg.hpp:43
#define QF_CRIT_X_()
This is an internal macro for exiting a critical section.
Definition: qf_pkg.hpp:77
#define QF_CRIT_E_()
This is an internal macro for entering a critical section.
Definition: qf_pkg.hpp:66
#define QS_CRIT_STAT_
This is an internal macro for defining the critical section status type.
Definition: qs.hpp:783
#define QS_TIME_PRE_()
Definition: qs.hpp:266
Dummy definitions of the QS macros that avoid code generation from the QS instrumentation.
#define QS_BEGIN_PRE_(rec_, qs_id_)
Definition: qs_dummy.hpp:96
#define QS_BEGIN_NOCRIT_PRE_(rec_, qs_id_)
Definition: qs_dummy.hpp:98
#define QS_END_NOCRIT_PRE_()
Definition: qs_dummy.hpp:99
#define QS_2U8_PRE_(data1_, data2_)
Definition: qs_dummy.hpp:101
#define QS_EVS_PRE_(size_)
Definition: qs_dummy.hpp:106
#define QS_SIG_PRE_(sig_)
Definition: qs_dummy.hpp:105
#define QS_END_PRE_()
Definition: qs_dummy.hpp:97
Internal (package scope) QS/C++ interface.
QS/C++ port to a 32-bit CPU, generic compiler.
#define QF_MAX_EPOOL
The maximum number of event pools in the application.
Definition: qxk/qf_port.hpp:74
QEvt base class.
Definition: qep.hpp:209