QP/C++  7.3.3
Real-Time Embedded Framework
Loading...
Searching...
No Matches
qf_qeq.cpp
Go to the documentation of this file.
1//$file${src::qf::qf_qeq.cpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
2//
3// Model: qpcpp.qm
4// File: ${src::qf::qf_qeq.cpp}
5//
6// This code has been generated by QM 6.1.1 <www.state-machine.com/qm>.
7// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost.
8//
9// This code is covered by the following QP license:
10// License # : LicenseRef-QL-dual
11// Issued to : Any user of the QP/C++ real-time embedded framework
12// Framework(s) : qpcpp
13// Support ends : 2024-12-31
14// License scope:
15//
16// Copyright (C) 2005 Quantum Leaps, LLC <state-machine.com>.
17//
18// Q u a n t u m L e a P s
19// ------------------------
20// Modern Embedded Software
21//
22// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
23//
24// This software is dual-licensed under the terms of the open source GNU
25// General Public License version 3 (or any later version), or alternatively,
26// under the terms of one of the closed source Quantum Leaps commercial
27// licenses.
28//
29// The terms of the open source GNU General Public License version 3
30// can be found at: <www.gnu.org/licenses/gpl-3.0>
31//
32// The terms of the closed source Quantum Leaps commercial licenses
33// can be found at: <www.state-machine.com/licensing>
34//
35// Redistributions in source code must retain this top-level comment block.
36// Plagiarizing this software to sidestep the license obligations is illegal.
37//
38// Contact information:
39// <www.state-machine.com/licensing>
40// <info@state-machine.com>
41//
42//$endhead${src::qf::qf_qeq.cpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
43#define QP_IMPL // this is QP implementation
44#include "qp_port.hpp" // QP port
45#include "qp_pkg.hpp" // QP package-scope interface
46#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem
47#ifdef Q_SPY // QS software tracing enabled?
48 #include "qs_port.hpp" // QS port
49 #include "qs_pkg.hpp" // QS facilities for pre-defined trace records
50#else
51 #include "qs_dummy.hpp" // disable the QS software tracing
52#endif // Q_SPY
53
54// unnamed namespace for local definitions with internal linkage
55namespace {
56Q_DEFINE_THIS_MODULE("qf_qeq")
57} // unnamed namespace
58
59//$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
60// Check for the minimum required QP version
61#if (QP_VERSION < 730U) || (QP_VERSION != ((QP_RELEASE^4294967295U) % 0x3E8U))
62#error qpcpp version 7.3.0 or higher required
63#endif
64//$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
65
66//$define${QF::QEQueue} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
67namespace QP {
68
69//${QF::QEQueue} .............................................................
70
71//${QF::QEQueue::init} .......................................................
73 QEvt const * qSto[],
74 std::uint_fast16_t const qLen) noexcept
75{
76 m_frontEvt = nullptr; // no events in the queue
77 m_ring = &qSto[0];
78 m_end = static_cast<QEQueueCtr>(qLen);
79 if (qLen > 0U) {
80 m_head = 0U;
81 m_tail = 0U;
82 }
83 m_nFree = static_cast<QEQueueCtr>(qLen + 1U); //+1 for frontEvt
84 m_nMin = m_nFree;
85}
86
87//${QF::QEQueue::post} .......................................................
89 QEvt const * const e,
90 std::uint_fast16_t const margin,
91 std::uint_fast8_t const qsId) noexcept
92{
93 #ifndef Q_SPY
94 Q_UNUSED_PAR(qsId);
95 #endif
96
99 QF_MEM_SYS();
100
101 Q_REQUIRE_INCRIT(200, e != nullptr);
102
103 QEQueueCtr nFree = m_nFree; // get volatile into temporary
104
105 // required margin available?
106 bool status;
107 if (((margin == QF::NO_MARGIN) && (nFree > 0U))
108 || (nFree > static_cast<QEQueueCtr>(margin)))
109 {
110 // is it a mutable event?
111 if (e->getPoolNum_() != 0U) {
112 QEvt_refCtr_inc_(e); // increment the reference counter
113 }
114
115 --nFree; // one free entry just used up
116 m_nFree = nFree; // update the original
117 if (m_nMin > nFree) {
118 m_nMin = nFree; // update minimum so far
119 }
120
121 QS_BEGIN_PRE_(QS_QF_EQUEUE_POST, qsId)
122 QS_TIME_PRE_(); // timestamp
123 QS_SIG_PRE_(e->sig); // the signal of this event
124 QS_OBJ_PRE_(this); // this queue object
125 QS_2U8_PRE_(e->getPoolNum_(), e->refCtr_); // poolNum & refCtr
126 QS_EQC_PRE_(nFree); // # free entries
127 QS_EQC_PRE_(m_nMin); // min # free entries
128 QS_END_PRE_()
129
130 if (m_frontEvt == nullptr) { // was the queue empty?
131 m_frontEvt = e; // deliver event directly
132 }
133 else { // queue was not empty, insert event into the ring-buffer
134 // insert event into the ring buffer (FIFO)
135 m_ring[m_head] = e; // insert e into buffer
136
137 // need to wrap?
138 if (m_head == 0U) {
139 m_head = m_end; // wrap around
140 }
141 m_head = (m_head - 1U);
142 }
143 status = true; // event posted successfully
144 }
145 else { // event cannot be posted
146 // dropping events must be acceptable
147 Q_ASSERT_INCRIT(210, margin != QF::NO_MARGIN);
148
149 QS_BEGIN_PRE_(QS_QF_EQUEUE_POST_ATTEMPT, qsId)
150 QS_TIME_PRE_(); // timestamp
151 QS_SIG_PRE_(e->sig); // the signal of this event
152 QS_OBJ_PRE_(this); // this queue object
153 QS_2U8_PRE_(e->getPoolNum_(), e->refCtr_); // poolNum & refCtr
154 QS_EQC_PRE_(nFree); // # free entries
155 QS_EQC_PRE_(margin); // margin requested
156 QS_END_PRE_()
157
158 status = false; // event not posted
159 }
160
161 QF_MEM_APP();
162 QF_CRIT_EXIT();
163
164 return status;
165}
166
167//${QF::QEQueue::postLIFO} ...................................................
169 QEvt const * const e,
170 std::uint_fast8_t const qsId) noexcept
171{
172 #ifndef Q_SPY
173 Q_UNUSED_PAR(qsId);
174 #endif
175
178 QF_MEM_SYS();
179
180 QEQueueCtr nFree = m_nFree; // get volatile into temporary
181
182 Q_REQUIRE_INCRIT(300, nFree != 0U);
183
184 if (e->getPoolNum_() != 0U) { // is it a mutable event?
185 QEvt_refCtr_inc_(e); // increment the reference counter
186 }
187
188 --nFree; // one free entry just used up
189 m_nFree = nFree; // update the original
190 if (m_nMin > nFree) {
191 m_nMin = nFree; // update minimum so far
192 }
193
194 QS_BEGIN_PRE_(QS_QF_EQUEUE_POST_LIFO, qsId)
195 QS_TIME_PRE_(); // timestamp
196 QS_SIG_PRE_(e->sig); // the signal of this event
197 QS_OBJ_PRE_(this); // this queue object
198 QS_2U8_PRE_(e->getPoolNum_(), e->refCtr_); // poolNum & refCtr
199 QS_EQC_PRE_(nFree); // # free entries
200 QS_EQC_PRE_(m_nMin); // min # free entries
201 QS_END_PRE_()
202
203 QEvt const * const frontEvt = m_frontEvt; // read into temporary
204 m_frontEvt = e; // deliver event directly to the front of the queue
205
206 if (frontEvt != nullptr) { // was the queue not empty?
207 m_tail = (m_tail + 1U);
208 if (m_tail == m_end) { // need to wrap the tail?
209 m_tail = 0U; // wrap around
210 }
211 m_ring[m_tail] = frontEvt; // buffer the old front evt
212 }
213
214 QF_MEM_APP();
215 QF_CRIT_EXIT();
216}
217
218//${QF::QEQueue::get} ........................................................
219QEvt const * QEQueue::get(std::uint_fast8_t const qsId) noexcept {
220 #ifndef Q_SPY
221 Q_UNUSED_PAR(qsId);
222 #endif
223
226 QF_MEM_SYS();
227
228 QEvt const * const e = m_frontEvt; // always remove evt from the front
229
230 if (e != nullptr) { // was the queue not empty?
231 QEQueueCtr const nFree = m_nFree + 1U;
232 m_nFree = nFree; // update the # free
233
234 // any events in the the ring buffer?
235 if (nFree <= m_end) {
236 m_frontEvt = m_ring[m_tail]; // remove from the tail
237 if (m_tail == 0U) { // need to wrap?
238 m_tail = m_end; // wrap around
239 }
240 m_tail = (m_tail - 1U);
241
242 QS_BEGIN_PRE_(QS_QF_EQUEUE_GET, qsId)
243 QS_TIME_PRE_(); // timestamp
244 QS_SIG_PRE_(e->sig); // the signal of this event
245 QS_OBJ_PRE_(this); // this queue object
246 QS_2U8_PRE_(e->getPoolNum_(), e->refCtr_); // poolNum & refCtr
247 QS_EQC_PRE_(nFree); // # free entries
248 QS_END_PRE_()
249 }
250 else {
251 m_frontEvt = nullptr; // queue becomes empty
252
253 // all entries in the queue must be free (+1 for fronEvt)
254 Q_ASSERT_INCRIT(410, nFree == (m_end + 1U));
255
256 QS_BEGIN_PRE_(QS_QF_EQUEUE_GET_LAST, qsId)
257 QS_TIME_PRE_(); // timestamp
258 QS_SIG_PRE_(e->sig); // the signal of this event
259 QS_OBJ_PRE_(this); // this queue object
260 QS_2U8_PRE_(e->getPoolNum_(), e->refCtr_); // poolNum & refCtr
261 QS_END_PRE_()
262 }
263 }
264
265 QF_MEM_APP();
266 QF_CRIT_EXIT();
267
268 return e;
269}
270
271} // namespace QP
272//$enddef${QF::QEQueue} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
bool post(QEvt const *const e, std::uint_fast16_t const margin, std::uint_fast8_t const qsId) noexcept
Definition qf_qeq.cpp:88
QEvt const * get(std::uint_fast8_t const qsId) noexcept
Definition qf_qeq.cpp:219
void postLIFO(QEvt const *const e, std::uint_fast8_t const qsId) noexcept
Definition qf_qeq.cpp:168
void init(QEvt const *qSto[], std::uint_fast16_t const qLen) noexcept
Definition qf_qeq.cpp:72
Event class.
Definition qp.hpp:139
std::uint_fast8_t getPoolNum_() const noexcept
Definition qp.hpp:167
std::uint8_t volatile refCtr_
Definition qp.hpp:142
QSignal sig
Definition qp.hpp:141
constexpr std::uint_fast16_t NO_MARGIN
Definition qp.hpp:1101
QP/C++ framework.
Definition qequeue.hpp:50
std::uint16_t QEQueueCtr
Definition qequeue.hpp:55
void QEvt_refCtr_inc_(QEvt const *const e) noexcept
Definition qp_pkg.hpp:92
@ QS_QF_EQUEUE_POST_ATTEMPT
attempt to post evt to QEQueue failed
Definition qs.hpp:137
@ QS_QF_EQUEUE_GET_LAST
get the last event from the queue
Definition qs.hpp:99
@ QS_QF_EQUEUE_GET
get an event and queue still not empty
Definition qs.hpp:98
@ QS_QF_EQUEUE_POST_LIFO
an event was posted (LIFO) to a raw queue
Definition qs.hpp:97
@ QS_QF_EQUEUE_POST
an event was posted (FIFO) to a raw queue
Definition qs.hpp:96
#define QF_MEM_APP()
Definition qp.hpp:1276
#define Q_UNUSED_PAR(par_)
Definition qp.hpp:541
#define QF_MEM_SYS()
Definition qp.hpp:1271
Internal (package scope) QP/C++ interface.
Sample QP/C++ port.
#define QS_TIME_PRE_()
Definition qs.hpp:473
QS/C++ package-scope interface.
QS/C++ port to a 32-bit CPU, generic C++ compiler.
QP Functional Safety (FuSa) Subsystem.
#define QF_CRIT_ENTRY()
Definition qsafe.h:58
#define Q_ASSERT_INCRIT(id_, expr_)
Definition qsafe.h:72
#define QF_CRIT_EXIT()
Definition qsafe.h:62
#define Q_REQUIRE_INCRIT(id_, expr_)
Definition qsafe.h:136
#define QF_CRIT_STAT
Definition qsafe.h:54