QP/C++  6.9.3
Real-Time Embedded Framework
qf_ps.cpp
Go to the documentation of this file.
1 
40 #define QP_IMPL // this is QP implementation
41 #include "qf_port.hpp" // QF port
42 #include "qf_pkg.hpp" // QF package-scope interface
43 #include "qassert.h" // QP embedded systems-friendly assertions
44 #ifdef Q_SPY // QS software tracing enabled?
45  #include "qs_port.hpp" // QS port
46  #include "qs_pkg.hpp" // QS facilities for pre-defined trace records
47 #else
48  #include "qs_dummy.hpp" // disable the QS software tracing
49 #endif // Q_SPY
50 
51 
52 namespace QP {
53 
54 Q_DEFINE_THIS_MODULE("qf_ps")
55 
56 // Package-scope objects *****************************************************
59 
60 //****************************************************************************
89 void QF::psInit(QSubscrList * const subscrSto,
90  enum_t const maxSignal) noexcept
91 {
92  QF_subscrList_ = subscrSto;
93  QF_maxPubSignal_ = maxSignal;
94 
95  // zero the subscriber list, so that the framework can start correctly
96  // even if the startup code fails to clear the uninitialized data
97  // (as is required by the C++ Standard)
98  bzero(subscrSto, static_cast<unsigned>(maxSignal) * sizeof(QSubscrList));
99 }
100 
101 //****************************************************************************
118 #ifndef Q_SPY
119 void QF::publish_(QEvt const * const e) noexcept {
120 #else
121 void QF::publish_(QEvt const * const e,
122  void const * const sender,
123  std::uint_fast8_t const qs_id) noexcept
124 {
125 #endif
127  Q_REQUIRE_ID(100, static_cast<enum_t>(e->sig) < QF_maxPubSignal_);
128 
130  QF_CRIT_E_();
131 
133  QS_TIME_PRE_(); // the timestamp
134  QS_OBJ_PRE_(sender); // the sender object
135  QS_SIG_PRE_(e->sig); // the signal of the event
136  QS_2U8_PRE_(e->poolId_, e->refCtr_); // pool Id & refCtr of the evt
138 
139  // is it a dynamic event?
140  if (e->poolId_ != 0U) {
141  // NOTE: The reference counter of a dynamic event is incremented to
142  // prevent premature recycling of the event while the multicasting
143  // is still in progress. At the end of the function, the garbage
144  // collector step (QF::gc()) decrements the reference counter and
145  // recycles the event if the counter drops to zero. This covers the
146  // case when the event was published without any subscribers.
147  //
149  }
150 
151  // make a local, modifiable copy of the subscriber list
152  QPSet subscrList = QF_PTR_AT_(QF_subscrList_, e->sig);
153  QF_CRIT_X_();
154 
155  if (subscrList.notEmpty()) { // any subscribers?
156  // the highest-prio subscriber
157  std::uint_fast8_t p = subscrList.findMax();
159 
160  QF_SCHED_LOCK_(p); // lock the scheduler up to prio 'p'
161  do { // loop over all subscribers */
162  // the prio of the AO must be registered with the framework
163  Q_ASSERT_ID(210, active_[p] != nullptr);
164 
165  // POST() asserts internally if the queue overflows
166  static_cast<void>(active_[p]->POST(e, sender));
167 
168  subscrList.rmove(p); // remove the handled subscriber
169  if (subscrList.notEmpty()) { // still more subscribers?
170  p = subscrList.findMax(); // the highest-prio subscriber
171  }
172  else {
173  p = 0U; // no more subscribers
174  }
175  } while (p != 0U);
176  QF_SCHED_UNLOCK_(); // unlock the scheduler
177  }
178 
179  // The following garbage collection step decrements the reference counter
180  // and recycles the event if the counter drops to zero. This covers both
181  // cases when the event was published with or without any subscribers.
182  //
183  gc(e);
184 }
185 
186 
187 //****************************************************************************
204 void QActive::subscribe(enum_t const sig) const noexcept {
205  std::uint_fast8_t const p = static_cast<std::uint_fast8_t>(m_prio);
206  Q_REQUIRE_ID(300, (Q_USER_SIG <= sig)
207  && (sig < QF_maxPubSignal_)
208  && (0U < p) && (p <= QF_MAX_ACTIVE)
209  && (QF::active_[p] == this));
210 
212  QF_CRIT_E_();
213 
215  QS_TIME_PRE_(); // timestamp
216  QS_SIG_PRE_(sig); // the signal of this event
217  QS_OBJ_PRE_(this); // this active object
219 
220  QF_PTR_AT_(QF_subscrList_, sig).insert(p); // insert into subscriber-list
221  QF_CRIT_X_();
222 }
223 
224 //****************************************************************************
248 void QActive::unsubscribe(enum_t const sig) const noexcept {
249  std::uint_fast8_t const p = static_cast<std::uint_fast8_t>(m_prio);
250 
252  // be registered with the framework
253  Q_REQUIRE_ID(400, (Q_USER_SIG <= sig)
254  && (sig < QF_maxPubSignal_)
255  && (0U < p) && (p <= QF_MAX_ACTIVE)
256  && (QF::active_[p] == this));
257 
259  QF_CRIT_E_();
260 
262  QS_TIME_PRE_(); // timestamp
263  QS_SIG_PRE_(sig); // the signal of this event
264  QS_OBJ_PRE_(this); // this active object
266 
267  QF_PTR_AT_(QF_subscrList_,sig).rmove(p); // remove from subscriber-list
268 
269  QF_CRIT_X_();
270 }
271 
272 //****************************************************************************
293 void QActive::unsubscribeAll(void) const noexcept {
294  std::uint_fast8_t const p = static_cast<std::uint_fast8_t>(m_prio);
295 
296  Q_REQUIRE_ID(500, (0U < p) && (p <= QF_MAX_ACTIVE)
297  && (QF::active_[p] == this));
298 
299  for (enum_t sig = Q_USER_SIG; sig < QF_maxPubSignal_; ++sig) {
301  QF_CRIT_E_();
302  if (QF_PTR_AT_(QF_subscrList_, sig).hasElement(p)) {
303  QF_PTR_AT_(QF_subscrList_, sig).rmove(p);
304 
306  QS_TIME_PRE_(); // timestamp
307  QS_SIG_PRE_(sig); // the signal of this event
308  QS_OBJ_PRE_(this); // this active object
310 
311  }
312  QF_CRIT_X_();
313 
314  // prevent merging critical sections
316  }
317 }
318 
319 } // namespace QP
320 
unsigned int uint_fast8_t
Definition: 16bit/stdint.h:36
void unsubscribeAll(void) const noexcept
Un-subscribes from the delivery of all signals to the active object.
Definition: qf_ps.cpp:293
void subscribe(enum_t const sig) const noexcept
Subscribes for delivery of signal sig to the active object.
Definition: qf_ps.cpp:204
void unsubscribe(enum_t const sig) const noexcept
Un-subscribes from the delivery of signal sig to the active object.
Definition: qf_ps.cpp:248
Definition: qf.hpp:496
static QActive * active_[QF_MAX_ACTIVE+1U]
array of registered active objects
Definition: qf.hpp:580
static void publish_(QEvt const *const e, void const *const sender, std::uint_fast8_t const qs_id) noexcept
Publish event to the framework.
Definition: qf_ps.cpp:121
Definition: struct.dox:1
@ QS_QF_PUBLISH
an event was published
Definition: qs.hpp:102
@ QS_QF_ACTIVE_UNSUBSCRIBE
an AO unsubscribed to an event
Definition: qs.hpp:81
@ QS_QF_ACTIVE_SUBSCRIBE
an AO subscribed to an event
Definition: qs.hpp:80
void QF_EVT_REF_CTR_INC_(QEvt const *const e) noexcept
increment the refCtr_ of an event e
Definition: qf_pkg.hpp:150
enum_t QF_maxPubSignal_
the maximum published signal
Definition: qf_ps.cpp:58
constexpr enum_t Q_USER_SIG
Offset or the user signals.
Definition: qep.hpp:610
QSubscrList * QF_subscrList_
the subscriber list array
Definition: qf_ps.cpp:57
Customizable and memory-efficient assertions for embedded systems.
#define Q_DEFINE_THIS_MODULE(name_)
Definition: qassert.h:120
#define Q_ASSERT_ID(id_, test_)
Definition: qassert.h:155
#define Q_REQUIRE_ID(id_, test_)
Definition: qassert.h:279
int enum_t
alias for enumerations used for event signals
Definition: qep.hpp:82
#define QF_CRIT_EXIT_NOP()
Definition: qf.hpp:674
Internal (package scope) QF/C++ interface.
#define QF_CRIT_STAT_
Definition: qf_pkg.hpp:56
#define QF_PTR_AT_(base_, i_)
access element at index i_ from the base pointer base_
Definition: qf_pkg.hpp:171
#define QF_CRIT_X_()
Definition: qf_pkg.hpp:77
#define QF_CRIT_E_()
Definition: qf_pkg.hpp:66
#define QF_SCHED_LOCK_(prio_)
Internal macro for selective scheduler locking.
Definition: qk.hpp:183
#define QF_SCHED_UNLOCK_()
Internal macro for selective scheduler unlocking.
Definition: qk.hpp:192
#define QF_SCHED_STAT_
Internal macro to represent the scheduler lock status.
Definition: qk.hpp:180
#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_NOCRIT_PRE_(rec_, qs_id_)
Definition: qs_dummy.hpp:98
#define QS_OBJ_PRE_(obj_)
Definition: qs_dummy.hpp:107
#define QS_END_NOCRIT_PRE_()
Definition: qs_dummy.hpp:99
#define QS_2U8_PRE_(data1_, data2_)
Definition: qs_dummy.hpp:101
#define QS_SIG_PRE_(sig_)
Definition: qs_dummy.hpp:105
Internal (package scope) QS/C++ interface.
QS/C++ port to a 32-bit CPU, generic compiler.
#define QF_MAX_ACTIVE
Definition: qxk/qf_port.hpp:57
void rmove(std::uint_fast8_t const n) noexcept
Definition: qpset.hpp:109
bool notEmpty(void) const noexcept
Evaluates to true if the priority set is not empty.
Definition: qpset.hpp:91
std::uint_fast8_t findMax(void) const noexcept
Definition: qpset.hpp:114