QP/C++  5.9.8
qf_dyn.cpp
Go to the documentation of this file.
1 
38 #define QP_IMPL // this is QP implementation
39 #include "qf_port.h" // QF port
40 #include "qf_pkg.h" // 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.h" // include QS port
44 #else
45  #include "qs_dummy.h" // disable the QS software tracing
46 #endif // Q_SPY
47 
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 uint_fast8_t QF_maxPool_; // number of initialized event pools
56 
57 //****************************************************************************
90 void QF::poolInit(void * const poolSto,
91  uint_fast32_t const poolSize, uint_fast16_t const evtSize)
92 {
94  Q_REQUIRE_ID(200, QF_maxPool_
95  < static_cast<uint_fast8_t>(Q_DIM(QF_pool_)));
97  Q_REQUIRE_ID(201, (QF_maxPool_ == static_cast<uint_fast8_t>(0))
99  QF_pool_[QF_maxPool_ - static_cast<uint_fast8_t>(1)])
100  < evtSize));
101 
102  QF_EPOOL_INIT_(QF_pool_[QF_maxPool_], poolSto, poolSize, evtSize);
103  ++QF_maxPool_; // one more pool
104 }
105 
106 //****************************************************************************
129 QEvt *QF::newX_(uint_fast16_t const evtSize,
130  uint_fast16_t const margin, enum_t const sig)
131 {
132  uint_fast8_t idx;
133 
134  // find the pool id that fits the requested event size ...
135  for (idx = static_cast<uint_fast8_t>(0); idx < QF_maxPool_; ++idx) {
136  if (evtSize <= QF_EPOOL_EVENT_SIZE_(QF_pool_[idx])) {
137  break;
138  }
139  }
140  // cannot run out of registered pools
141  Q_ASSERT_ID(310, idx < QF_maxPool_);
142 
144  QS_BEGIN_(QS_QF_NEW, static_cast<void *>(0), static_cast<void *>(0))
145  QS_TIME_(); // timestamp
146  QS_EVS_(static_cast<QEvtSize>(evtSize)); // the size of the event
147  QS_SIG_(static_cast<QSignal>(sig)); // the signal of the event
148  QS_END_()
149 
150  // get e -- platform-dependent
151  QEvt *e;
152  QF_EPOOL_GET_(QF_pool_[idx], e,
153  ((margin != QF_NO_MARGIN)
154  ? margin
155  : static_cast<uint_fast16_t>(0)));
156 
157  // was e allocated correctly?
158  if (e != static_cast<QEvt const *>(0)) {
159  e->sig = static_cast<QSignal>(sig); // set the signal
160  // store pool ID
161  e->poolId_ = static_cast<uint8_t>(
162  idx + static_cast<uint_fast8_t>(1));
163  // initialize the reference counter to 0
164  e->refCtr_ = static_cast<uint8_t>(0);
165  }
166  else {
167  // event was not allocated, assert that the caller provided non-zero
168  // margin, which means that they can tollerate bad allocation
169  Q_ASSERT_ID(320, margin != static_cast<uint_fast16_t>(0));
170  }
171  return e;
172 }
173 
174 //****************************************************************************
197 void QF::gc(QEvt const * const e) {
198  // is it a dynamic event?
199  if (e->poolId_ != static_cast<uint8_t>(0)) {
201  QF_CRIT_ENTRY_();
202 
203  // isn't this the last reference?
204  if (e->refCtr_ > static_cast<uint8_t>(1)) {
205  QF_EVT_REF_CTR_DEC_(e); // decrement the ref counter
206 
208  static_cast<void *>(0), static_cast<void *>(0))
209  QS_TIME_(); // timestamp
210  QS_SIG_(e->sig); // the signal of the event
211  QS_2U8_(e->poolId_, e->refCtr_);// pool Id & refCtr of the evt
213 
214  QF_CRIT_EXIT_();
215  }
216  // this is the last reference to this event, recycle it
217  else {
218  uint_fast8_t idx = static_cast<uint_fast8_t>(e->poolId_)
219  - static_cast<uint_fast8_t>(1);
220 
222  static_cast<void *>(0), static_cast<void *>(0))
223  QS_TIME_(); // timestamp
224  QS_SIG_(e->sig); // the signal of the event
225  QS_2U8_(e->poolId_, e->refCtr_);// pool Id & refCtr of the evt
227 
228  QF_CRIT_EXIT_();
229 
230  // pool ID must be in range
231  Q_ASSERT_ID(410, idx < QF_maxPool_);
232 
233 #ifdef Q_EVT_VIRTUAL
234  // explicitly exectute the destructor'
235  // NOTE: casting 'const' away is legitimate,
236  // because it's a pool event
237  QF_EVT_CONST_CAST_(e)->~QEvt(); // xtor,
238 #endif
239  // cast 'const' away, which is OK, because it's a pool event
241  }
242  }
243 }
244 
245 //****************************************************************************
257 QEvt const *QF::newRef_(QEvt const * const e, QEvt const * const evtRef) {
260  Q_REQUIRE_ID(500,
261  (e->poolId_ != static_cast<uint8_t>(0))
262  && (evtRef == static_cast<QEvt const *>(0)));
263 
265  QF_CRIT_ENTRY_();
266  QF_EVT_REF_CTR_INC_(e); // increments the ref counter
267  QF_CRIT_EXIT_();
268 
269  return e;
270 }
271 
272 //****************************************************************************
277  return QF_EPOOL_EVENT_SIZE_(
278  QF_pool_[QF_maxPool_ - static_cast<uint_fast8_t>(1)]);
279 }
280 
281 } // namespace QP
#define QS_2U8_(data1_, data2_)
Internal QS macro to output 2 unformatted uint8_t data elements.
Definition: qs.h:806
static uint_fast16_t poolGetMaxBlockSize(void)
Obtain the block size of any registered event pools.
Definition: qf_dyn.cpp:276
#define QF_EVT_CONST_CAST_(e_)
helper macro to cast const away from an event pointer e_
Definition: qf_pkg.h:43
#define QF_CRIT_ENTRY_()
This is an internal macro for entering a critical section.
Definition: qf_pkg.h:66
void QF_EVT_REF_CTR_INC_(QEvt const *const e)
increment the refCtr_ of an event e
Definition: qf_pkg.h:105
uint8_t poolId_
pool ID (0 for static event)
Definition: qep.h:214
#define QF_EPOOL_TYPE_
This macro defines the type of the event pool used in this QF port.
Definition: macros.h:94
garbage collection
Definition: qs.h:110
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.h:594
QS/C++ port to a 32-bit CPU, generic compiler.
#define QF_EPOOL_GET_(p_, e_, m_)
Platform-dependent macro defining how QF should obtain an event e_ from the event pool p_...
Definition: macros.h:118
#define QF_CRIT_STAT_
This is an internal macro for defining the critical section status type.
Definition: qf_pkg.h:56
#define QS_BEGIN_NOCRIT_(rec_, objFilter_, obj_)
Internal QS macro to begin a QS record without entering critical section.
Definition: qs.h:776
garbage collection attempt
Definition: qs.h:109
QEvt base class.
Definition: qep.h:212
#define Q_DEFINE_THIS_MODULE(name_)
Define the user-specified module name for assertions in this file.
Definition: qassert.h:101
unsigned char uint8_t
exact-width 8-bit unsigned int
Definition: stdint.h:29
QF services.
Definition: qf.h:490
#define QF_EPOOL_PUT_(p_, e_)
Platform-dependent macro defining how QF should return an event e_ to the event pool p_...
Definition: macros.h:127
#define QS_END_()
Internal QS macro to end a QS record with exiting critical section.
Definition: qs.h:767
QSignal sig
signal of the event instance
Definition: qep.h:213
static QEvt const * newRef_(QEvt const *const e, QEvt const *const evtRef)
Internal QF implementation of the event reference creator.
Definition: qf_dyn.cpp:257
unsigned int uint_fast8_t
fast at-least 8-bit unsigned int
Definition: stdint.h:36
Internal (package scope) QF/C++ interface.
#define QF_EPOOL_EVENT_SIZE_(p_)
Platform-dependent macro defining how QF should obtain the event pool block-size. ...
Definition: macros.h:110
int enum_t
typedef for enumerations used for event signals
Definition: qep.h:85
unsigned long uint_fast32_t
fast at-least 32-bit unsigned int
Definition: stdint.h:40
void QF_EVT_REF_CTR_DEC_(QEvt const *const e)
decrement the refCtr_ of an event e
Definition: qf_pkg.h:110
#define Q_ASSERT_ID(id_, test_)
General purpose assertion with user-specified assertion-id.
Definition: qassert.h:136
uint8_t volatile refCtr_
reference counter
Definition: qep.h:215
unsigned int uint_fast16_t
fast at-least 16-bit unsigned int
Definition: stdint.h:38
namespace associated with the QP/C++ framework
Definition: api.dox:1
uint16_t QSignal
QSignal represents the signal of an event.
Definition: qep.h:151
new event creation
Definition: qs.h:108
Customizable and memory-efficient assertions for embedded systems.
uint_fast8_t QF_maxPool_
of initialized event pools
Definition: qf_dyn.cpp:55
#define QS_BEGIN_(rec_, objFilter_, obj_)
Internal QS macro to begin a QS record with entering critical section.
Definition: qs.h:755
#define Q_REQUIRE_ID(id_, test_)
Assertion for checking preconditions with user-specified assertion-id.
Definition: qassert.h:254
#define QF_EPOOL_INIT_(p_, poolSto_, poolSize_, evtSize_)
Platform-dependent macro defining the event pool initialization.
Definition: macros.h:101
#define QF_MAX_EPOOL
Default value of the macro configurable value in qf_port.h.
Definition: qf.h:61
static void gc(QEvt const *e)
Recycle a dynamic event.
Definition: qf_dyn.cpp:197
#define QS_TIME_()
Internal macro to output time stamp to a QS record.
Definition: qs.h:205
#define QS_END_NOCRIT_()
Internal QS macro to end a QS record without exiting critical section.
Definition: qs.h:787
static QEvt * newX_(uint_fast16_t const evtSize, uint_fast16_t const margin, enum_t const sig)
Internal QP implementation of the dynamic event allocator.
Definition: qf_dyn.cpp:129
#define QS_CRIT_STAT_
This is an internal macro for defining the critical section status type.
Definition: qs.h:691
QF_EPOOL_TYPE_ QF_pool_[QF_MAX_EPOOL]
allocate event pools
Definition: qf_dyn.cpp:54
#define Q_DIM(array_)
helper macro to calculate static dimension of a 1-dim array array_
Definition: qep.h:69
#define QF_CRIT_EXIT_()
This is an internal macro for exiting a critical section.
Definition: qf_pkg.h:77