QP/C++  8.0.3
Real-Time Event Framework
Loading...
Searching...
No Matches
qf_qeq.cpp
Go to the documentation of this file.
1//============================================================================
2// QP/C++ Real-Time Event Framework (RTEF)
3//
4// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
5//
6// Q u a n t u m L e a P s
7// ------------------------
8// Modern Embedded Software
9//
10// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
11//
12// This software is dual-licensed under the terms of the open-source GNU
13// General Public License (GPL) or under the terms of one of the closed-
14// source Quantum Leaps commercial licenses.
15//
16// Redistributions in source code must retain this top-level comment block.
17// Plagiarizing this software to sidestep the license obligations is illegal.
18//
19// NOTE:
20// The GPL does NOT permit the incorporation of this code into proprietary
21// programs. Please contact Quantum Leaps for commercial licensing options,
22// which expressly supersede the GPL and are designed explicitly for
23// closed-source distribution.
24//
25// Quantum Leaps contact information:
26// <www.state-machine.com/licensing>
27// <info@state-machine.com>
28//============================================================================
29#define QP_IMPL // this is QP implementation
30#include "qp_port.hpp" // QP port
31#include "qp_pkg.hpp" // QP package-scope interface
32#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem
33#ifdef Q_SPY // QS software tracing enabled?
34 #include "qs_port.hpp" // QS port
35 #include "qs_pkg.hpp" // QS facilities for pre-defined trace records
36#else
37 #include "qs_dummy.hpp" // disable the QS software tracing
38#endif // Q_SPY
39
40// unnamed namespace for local definitions with internal linkage
41namespace {
42Q_DEFINE_THIS_MODULE("qf_qeq")
43} // unnamed namespace
44
45namespace QP {
46
47//............................................................................
49 QEvt const * * const qSto,
50 std::uint_fast16_t const qLen) noexcept
51{
54
55#if (QF_EQUEUE_CTR_SIZE == 1U)
56 Q_REQUIRE_INCRIT(100, qLen < 0xFFU);
57#endif
58
59 m_frontEvt = nullptr; // no events in the queue
60 m_ring = qSto;
61 m_end = static_cast<QEQueueCtr>(qLen);
62 if (qLen > 0U) {
63 m_head = 0U;
64 m_tail = 0U;
65 }
66 m_nFree = static_cast<QEQueueCtr>(qLen + 1U); //+1 for frontEvt
68
70}
71
72//............................................................................
74 QEvt const * const e,
75 std::uint_fast16_t const margin,
76 std::uint_fast8_t const qsId) noexcept
77{
78#ifndef Q_SPY
79 Q_UNUSED_PAR(qsId);
80#endif
81
84
85 Q_REQUIRE_INCRIT(200, e != nullptr);
86
87 QEQueueCtr tmp = m_nFree; // get volatile into temporary
88
89 // can the queue accept the event?
90 bool const status = ((margin == QF::NO_MARGIN) && (tmp > 0U))
91 || (tmp > static_cast<QEQueueCtr>(margin));
92 if (status) {
93 // is it a mutable event?
94 if (e->poolNum_ != 0U) {
95 Q_ASSERT_INCRIT(205, e->refCtr_ < (2U * QF_MAX_ACTIVE));
96 QEvt_refCtr_inc_(e); // increment the reference counter
97 }
98
99 --tmp; // one free entry just used up
100
101 m_nFree = tmp; // update the original
102 if (m_nMin > tmp) { // is this the new minimum?
103 m_nMin = tmp; // update minimum so far
104 }
105
106#ifdef Q_SPY
107 QS_BEGIN_PRE(QS_QF_EQUEUE_POST, qsId)
108 QS_TIME_PRE(); // timestamp
109 QS_SIG_PRE(e->sig); // the signal of the event
110 QS_OBJ_PRE(this); // this queue object
111 QS_2U8_PRE(e->poolNum_, e->refCtr_);
112 QS_EQC_PRE(tmp); // # free entries
113 QS_EQC_PRE(m_nMin); // min # free entries
114 QS_END_PRE()
115#endif // def Q_SPY
116
117 if (m_frontEvt == nullptr) { // is the queue empty?
118 m_frontEvt = e; // deliver event directly
119 }
120 else { // queue was not empty, insert event into the ring-buffer
121 tmp = m_head; // get volatile into temporary
122 m_ring[tmp] = e; // insert e into buffer
123
124 if (tmp == 0U) { // need to wrap the head?
125 tmp = m_end;
126 }
127 --tmp; // advance head (counter-clockwise)
128
129 m_head = tmp; // update the original
130 }
131 }
132 else { // event cannot be posted
133 // dropping events must be acceptable
134 Q_ASSERT_INCRIT(230, margin != QF::NO_MARGIN);
135
136#ifdef Q_SPY
137 QS_BEGIN_PRE(QS_QF_EQUEUE_POST_ATTEMPT, qsId)
138 QS_TIME_PRE(); // timestamp
139 QS_SIG_PRE(e->sig); // the signal of this event
140 QS_OBJ_PRE(this); // this queue object
141 QS_2U8_PRE(e->poolNum_, e->refCtr_);
142 QS_EQC_PRE(tmp); // # free entries
143 QS_EQC_PRE(margin); // margin requested
144 QS_END_PRE()
145#endif // def Q_SPY
146 }
147
148 QF_CRIT_EXIT();
149
150 return status;
151}
152
153//............................................................................
155 QEvt const * const e,
156 std::uint_fast8_t const qsId) noexcept
157{
158#ifndef Q_SPY
159 Q_UNUSED_PAR(qsId);
160#endif
161
164
165 Q_REQUIRE_INCRIT(300, e != nullptr);
166
167 QEQueueCtr tmp = m_nFree; // get volatile into temporary
168
169 // must be able to LIFO-post the event
170 Q_REQUIRE_INCRIT(310, tmp != 0U);
171
172 if (e->poolNum_ != 0U) { // is it a mutable event?
173 Q_ASSERT_INCRIT(305, e->refCtr_ < (2U * QF_MAX_ACTIVE));
174 QEvt_refCtr_inc_(e); // increment the reference counter
175 }
176
177 --tmp; // one free entry just used up
178
179 m_nFree = tmp; // update the original
180 if (m_nMin > tmp) { // is this the new minimum?
181 m_nMin = tmp; // update minimum so far
182 }
183
184 QS_BEGIN_PRE(QS_QF_EQUEUE_POST_LIFO, qsId)
185 QS_TIME_PRE(); // timestamp
186 QS_SIG_PRE(e->sig); // the signal of this event
187 QS_OBJ_PRE(this); // this queue object
188 QS_2U8_PRE(e->poolNum_, e->refCtr_);
189 QS_EQC_PRE(tmp); // # free entries
190 QS_EQC_PRE(m_nMin); // min # free entries
191 QS_END_PRE()
192
193 QEvt const * const frontEvt = m_frontEvt; // read into temporary
194 m_frontEvt = e; // deliver the event directly to the front
195
196 if (frontEvt != nullptr) { // was the queue NOT empty?
197 tmp = m_tail; // get volatile into temporary;
198 ++tmp;
199 if (tmp == m_end) { // need to wrap the tail?
200 tmp = 0U; // wrap around
201 }
202 m_tail = tmp;
203 m_ring[tmp] = frontEvt;
204 }
205
206 QF_CRIT_EXIT();
207}
208
209//............................................................................
210QEvt const * QEQueue::get(std::uint_fast8_t const qsId) noexcept {
211#ifndef Q_SPY
212 Q_UNUSED_PAR(qsId);
213#endif
214
217
218 QEvt const * const e = m_frontEvt; // always remove evt from the front
219
220 if (e != nullptr) { // was the queue not empty?
221 QEQueueCtr tmp = m_nFree; // get volatile into temporary
222
223 ++tmp; // one more free event in the queue
224
225 m_nFree = tmp; // update the # free
226
227 // any events in the ring buffer?
228 if (tmp <= m_end) {
229
230 QS_BEGIN_PRE(QS_QF_EQUEUE_GET, qsId)
231 QS_TIME_PRE(); // timestamp
232 QS_SIG_PRE(e->sig); // the signal of this event
233 QS_OBJ_PRE(this); // this queue object
235 QS_EQC_PRE(tmp); // # free entries
236 QS_END_PRE()
237
238 tmp = m_tail; // get volatile into temporary
239 QEvt const * const frontEvt = m_ring[tmp];
240
241 Q_ASSERT_INCRIT(420, frontEvt != nullptr);
242
243 m_frontEvt = frontEvt; // update the original
244
245 if (tmp == 0U) { // need to wrap the tail?
246 tmp = m_end;
247 }
248 --tmp; // advance the tail (counter-clockwise)
249 m_tail = tmp; // update the original
250 }
251 else {
252 m_frontEvt = nullptr; // queue becomes empty
253
254 // all entries in the queue must be free (+1 for frontEvt)
255 Q_INVARIANT_INCRIT(440, tmp == (m_end + 1U));
256
257 QS_BEGIN_PRE(QS_QF_EQUEUE_GET_LAST, qsId)
258 QS_TIME_PRE(); // timestamp
259 QS_SIG_PRE(e->sig); // the signal of this event
260 QS_OBJ_PRE(this); // this queue object
262 QS_END_PRE()
263 }
264 }
265
266 QF_CRIT_EXIT();
267
268 return e;
269}
270
271} // namespace QP
QEQueueCtr volatile m_nFree
Definition qequeue.hpp:60
QEvt const * get(std::uint_fast8_t const qsId) noexcept
Definition qf_qeq.cpp:210
QEQueueCtr volatile m_tail
Definition qequeue.hpp:59
QEvt const ** m_ring
Definition qequeue.hpp:56
void init(QEvt const **const qSto, std::uint_fast16_t const qLen) noexcept
Definition qf_qeq.cpp:48
QEQueueCtr m_nMin
Definition qequeue.hpp:61
bool post(QEvt const *const e, std::uint_fast16_t const margin, std::uint_fast8_t const qsId) noexcept
Definition qf_qeq.cpp:73
QEQueueCtr volatile m_head
Definition qequeue.hpp:58
QEvt const *volatile m_frontEvt
Definition qequeue.hpp:55
QEQueueCtr m_end
Definition qequeue.hpp:57
void postLIFO(QEvt const *const e, std::uint_fast8_t const qsId) noexcept
Definition qf_qeq.cpp:154
Event class.
Definition qp.hpp:115
QSignal sig
Signal of the event (see Event Signal)
Definition qp.hpp:117
std::uint8_t poolNum_
Event pool number of this event.
Definition qp.hpp:118
std::uint8_t volatile refCtr_
Event reference counter.
Definition qp.hpp:119
constexpr std::uint_fast16_t NO_MARGIN
Definition qp.hpp:901
QP/C++ framework.
Definition qequeue.hpp:36
void QEvt_refCtr_inc_(QEvt const *const e) noexcept
Definition qp_pkg.hpp:66
std::uint16_t QEQueueCtr
Definition qequeue.hpp:41
#define Q_UNUSED_PAR(par_)
Helper macro to clearly mark unused parameters of functions.
Definition qp.hpp:94
#define QF_MAX_ACTIVE
Maximum # Active Objects in the system (1..64)
Internal (package scope) QP/C++ interface.
Sample QP/C++ port.
QS/C++ dummy public interface.
#define QS_OBJ_PRE(obj_)
Definition qs_dummy.hpp:157
#define QS_EQC_PRE(ctr_)
Definition qs_dummy.hpp:159
#define QS_SIG_PRE(sig_)
Definition qs_dummy.hpp:155
#define QS_TIME_PRE()
Definition qs_dummy.hpp:154
#define QS_2U8_PRE(data1_, data2_)
Definition qs_dummy.hpp:151
#define QS_END_PRE()
Definition qs_dummy.hpp:149
#define QS_BEGIN_PRE(rec_, qsId_)
Definition qs_dummy.hpp:148
Sample QS/C++ port.
QP Functional Safety (FuSa) Subsystem.
#define QF_CRIT_ENTRY()
Definition qsafe.h:39
#define Q_ASSERT_INCRIT(id_, expr_)
General-purpose assertion with user-specified ID number (in critical section)
Definition qsafe.h:49
#define Q_INVARIANT_INCRIT(id_, expr_)
Definition qsafe.h:92
#define QF_CRIT_EXIT()
Definition qsafe.h:43
#define Q_REQUIRE_INCRIT(id_, expr_)
Assertion for checking a precondition (in critical section)
Definition qsafe.h:86
#define QF_CRIT_STAT
Definition qsafe.h:35