QP/C++ 8.1.2
Real-Time Event Framework
Loading...
Searching...
No Matches
qep_hsm.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 {
42
43Q_DEFINE_THIS_MODULE("qep_hsm")
44
45//! @cond INTERNAL
46
47// array of immutable events corresponding to the reserved signals
48static constexpr std::array<QP::QEvt, 4> l_resEvt_ {
53};
54
55//! @endcond
56
57} // unnamed namespace
58
59//============================================================================
60//! @cond INTERNAL
61
62// internal helper macro to pass a reserved event into the state handler
63
64#ifdef Q_SPY
65// helper macro to trace state action (entry/exit)
66#define QS_STATE_ACT_(rec_, state_) \
67 QS_CRIT_ENTRY(); \
68 QS_BEGIN_PRE((rec_), qsId) \
69 QS_OBJ_PRE(this); \
70 QS_FUN_PRE(state_); \
71 QS_END_PRE() \
72 QS_CRIT_EXIT()
73
74// internal helper macro to top-most init
75#define QS_TOP_INIT_(rec_, trg_) \
76 QS_CRIT_ENTRY(); \
77 QS_BEGIN_PRE((rec_), qsId) \
78 QS_TIME_PRE(); \
79 QS_OBJ_PRE(this); \
80 QS_FUN_PRE(trg_); \
81 QS_END_PRE() \
82 QS_CRIT_EXIT()
83
84// internal helper macro to trace transition segment
85#define QS_TRAN_SEG_(rec_, src_, trg_) \
86 QS_CRIT_ENTRY(); \
87 QS_BEGIN_PRE((rec_), qsId) \
88 QS_OBJ_PRE(this); \
89 QS_FUN_PRE(src_); \
90 QS_FUN_PRE(trg_); \
91 QS_END_PRE() \
92 QS_CRIT_EXIT()
93
94// internal helper macro to trace transition action
95#define QS_TRAN_ACT_(rec_, state_) \
96 QS_CRIT_ENTRY(); \
97 QS_BEGIN_PRE((rec_), qsId) \
98 QS_SIG_PRE(e->sig); \
99 QS_OBJ_PRE(this); \
100 QS_FUN_PRE(state_); \
101 QS_END_PRE() \
102 QS_CRIT_EXIT()
103
104// internal helper macro to trace transition begin/end
105#define QS_TRAN0_(rec_, trg_) \
106 QS_CRIT_ENTRY(); \
107 QS_BEGIN_PRE((rec_), qsId) \
108 QS_TIME_PRE(); \
109 QS_SIG_PRE(e->sig); \
110 QS_OBJ_PRE(this); \
111 QS_FUN_PRE(trg_); \
112 QS_END_PRE() \
113 QS_CRIT_EXIT()
114
115// internal helper macro to trace regular transition
116#define QS_TRAN_END_(rec_, src_, trg_) \
117 QS_CRIT_ENTRY(); \
118 QS_BEGIN_PRE((rec_), qsId) \
119 QS_TIME_PRE(); \
120 QS_SIG_PRE(e->sig); \
121 QS_OBJ_PRE(this); \
122 QS_FUN_PRE(src_); \
123 QS_FUN_PRE(trg_); \
124 QS_END_PRE() \
125 QS_CRIT_EXIT()
126
127#else
128#define QS_STATE_ACT_(rec_, state_) (static_cast<void>(0))
129#define QS_TOP_INIT_(rec_, trg_) (static_cast<void>(0))
130#define QS_TRAN_SEG_(rec_, src_, trg_) (static_cast<void>(0))
131#define QS_TRAN_ACT_(rec_, state_) (static_cast<void>(0))
132#define QS_TRAN0_(rec_, trg_) (static_cast<void>(0))
133#define QS_TRAN_END_(rec_, src_, trg_) (static_cast<void>(0))
134#endif
135
136//! @endcond
137
138//============================================================================
139namespace QP {
140
141//............................................................................
142QHsm::QHsm(QStateHandler const initial) noexcept
143 : QAsm()
144{
145 m_state.fun = &top; // the current state (top)
146 m_temp.fun = initial; // the initial tran. handler
147}
148
149//............................................................................
151 void const * const e,
152 std::uint_fast8_t const qsId)
153{
154#ifdef Q_SPY
155 // produce QS dictionary for QHsm_top handler...
156 // NOTE: the QHsm_top dictionary needs to be produced only once
157 // and not every time QHsm_init_() is called.
160 bool toDo = false; // assume that dictionary not produced
161 if ((QS::priv_.flags & 0x01U) == 0U) { // dictionary not produced yet?
162 QS::priv_.flags |= 0x01U; // mark the QHsm::top dictionary as produced
163 toDo = true;
164 }
165 QS_CRIT_EXIT();
166 if (toDo) { // need to produce the dictionary?
168 }
169#else
170 Q_UNUSED_PAR(qsId);
171#endif // Q_SPY
172
173 QStateHandler const s = m_state.fun; // current state
174
175 // current state must be initialized to QHsm_top in QHsm_ctor()
176 Q_REQUIRE_LOCAL(200, s == Q_STATE_CAST(&top));
177
178 // temp contains the top-most initial tran. handler, which must be valid
179 Q_REQUIRE_LOCAL(210, m_temp.fun != nullptr);
180
181 // execute the top-most initial tran.
182 QState const r = (*m_temp.fun)(this, Q_EVT_CAST(QEvt));
183
184 // the top-most initial tran. must be taken
185 Q_ASSERT_LOCAL(240, r == Q_RET_TRAN);
186
187 // the top-most initial tran. must set the target in temp
188 Q_ASSERT_LOCAL(250, m_temp.fun != nullptr);
189
190 QS_TRAN_SEG_(QS_QEP_STATE_INIT, s, m_temp.fun); // output QS record
191
192 // drill down into the state hierarchy with initial transitions...
193 std::array <QStateHandler, MAX_NEST_DEPTH_> path; // entry path array
194
195 std::size_t ip = 0U; // path index & fixed loop bound
196 do {
197 // the entry path index must not overflow the allocated array
199
200 // the initial tran. must set target in temp
201 Q_ASSERT_LOCAL(270, m_temp.fun != nullptr);
202
203 path[ip] = m_temp.fun; // store the entry path
204 ++ip;
205
206 // find the superstate of 'm_temp.fun', ignore result
207 static_cast<void>((*m_temp.fun)(this, &l_resEvt_[Q_EMPTY_SIG]));
208 } while (m_temp.fun != s);
209
210 // enter the target (possibly recursively) by initial trans.
211 enter_target_(path, ip, qsId);
212
213 QS_TOP_INIT_(QS_QEP_INIT_TRAN, path[0U]); // output QS record
214
215 m_state.fun = path[0U]; // change the current active state
216#ifndef Q_UNSAFE
217 // establish stable state configuration
219#else
220 Q_UNUSED_PAR(r);
221#endif
222}
223
224//............................................................................
226 QEvt const * const e,
227 std::uint_fast8_t const qsId)
228{
229#ifndef Q_SPY
230 Q_UNUSED_PAR(qsId);
231#endif
232
233 // this state machine must be in a "stable state configuration"
234 // NOTE: stable state configuration is established after every RTC step.
237
238 // the event to be dispatched must be valid
239 Q_REQUIRE_LOCAL(310, e != nullptr);
240
241 QStateHandler s = m_state.fun; // current state
242#ifndef Q_UNSAFE
243 std::uintptr_t const state_dis = m_temp.uint; // from invariant-300
244#endif
245 m_temp.fun = nullptr; // invalidate "stable state configuration"
246
248 QS_TRAN0_(QS_QEP_DISPATCH, s); // output QS record
249
250 // process the event hierarchically...
251 std::array <QStateHandler, MAX_NEST_DEPTH_> path; // entry path array
252 m_temp.fun = s;
253 QState r; // state handler return value
254 std::size_t ip = MAX_NEST_DEPTH_; // path index & fixed loop bound
255 do {
256 // the entry path index must stay in range of the path[] array
257 Q_INVARIANT_LOCAL(340, ip != 0U);
258
259 s = m_temp.fun; // set s to the superstate set previously
260 --ip; // build the entry path[] from the end
261 path[ip] = s; // store the path to potential tran. source
262
263 r = (*s)(this, e); // try to handle event e in state s
264
265 if (r == Q_RET_UNHANDLED) { // unhandled due to a guard?
266 QS_TRAN_ACT_(QS_QEP_UNHANDLED, s); // output QS record
267
268 // find the superstate of 's'
269 r = (*s)(this, &l_resEvt_[Q_EMPTY_SIG]);
270 }
271 } while (r == Q_RET_SUPER); // loop as long as superstate returned
272
273 // me->state should not change, so it must match the saved DIS
275 dis_verify<std::uintptr_t>(m_state.uint, state_dis));
276
277 if (r == Q_RET_IGNORED) { // was event ignored?
278 QS_TRAN0_(QS_QEP_IGNORED, m_state.fun); // output QS record
279 }
280 else if (r == Q_RET_HANDLED) { // did the last handler handle the event?
281 QS_TRAN0_(QS_QEP_INTERN_TRAN, s); // output QS record
282 }
283 else if ((r == Q_RET_TRAN) || (r == Q_RET_TRAN_HIST)) { // tran. taken?
284 // tran. must have set m_temp to the target state
285 Q_ASSERT_LOCAL(360, m_temp.fun != nullptr);
286
287#ifdef Q_SPY
288 if (r == Q_RET_TRAN_HIST) { // tran. to history?
289 QS_TRAN_SEG_(QS_QEP_TRAN_HIST, s, m_temp.fun); // output QS record
290 }
291#endif
292
293 path[0U] = m_temp.fun; // save tran. target in path[0]
294
295 // exit current state to tran. source (path[0] not used)...
296 for (std::size_t iq = MAX_NEST_DEPTH_ - 1U; iq > ip; --iq) {
297 // exit from 'path[iq]'
298 if ((*path[iq])(this, &l_resEvt_[Q_EXIT_SIG]) == Q_RET_HANDLED) {
299 QS_STATE_ACT_(QS_QEP_STATE_EXIT, path[iq]); //output QS record
300 }
301 }
302 path[2U] = s; // save tran. source in path[2]
303
304 // take the tran...
305 ip = tran_simple_(path, qsId); // try simple tran. first
306 if (ip > 1U) { // not a simple tran.?
307 ip = tran_complex_(path, qsId);
308 }
309
310 // enter the target (possibly recursively) by initial trans.
311 enter_target_(path, ip, qsId);
312 QS_TRAN_END_(QS_QEP_TRAN, s, path[0U]); // output QS record
313
314 m_state.fun = path[0U]; // change the current active state
315 }
316 else {
317 Q_ERROR_LOCAL(370); // last state handler returned impossible value
318 }
319
320#ifndef Q_UNSAFE
321 // establish "stable state configuration"
323#endif
324}
325
326//............................................................................
327//! @private @memberof QHsm
329 std::array<QStateHandler, MAX_NEST_DEPTH_> &path,
330 std::uint_fast8_t const qsId)
331{
332#ifndef Q_SPY
333 Q_UNUSED_PAR(qsId);
334#endif
335
336 QStateHandler t = path[0U]; // target
337 QStateHandler const s = path[2U]; // source
338 std::size_t ip = 1U; // assume to enter the target
340
341 // (a) check source==target (tran. to self)...
342 if (s == t) {
343 // exit source 's' (external tran. semantics)
344 if ((*s)(this, &l_resEvt_[Q_EXIT_SIG]) == Q_RET_HANDLED) {
345 QS_STATE_ACT_(QS_QEP_STATE_EXIT, s); // output QS record
346 }
347 }
348 else { // not a tran. to self
349 // find superstate of target in 't'
350 QState const r = (*t)(this, &l_resEvt_[Q_EMPTY_SIG]);
351
352 // state handler t must return the superstate for Q_EMPTY_SIG
353 Q_ASSERT_LOCAL(440, r == Q_RET_SUPER);
354
355 // state handler t must set temp to the superstate
356 Q_ASSERT_LOCAL(450, m_temp.fun != nullptr);
357#ifdef Q_UNSAFE
358 Q_UNUSED_PAR(r);
359#endif
360
361 // (b) check source==target->super...
362 t = m_temp.fun;
363 if (s != t) {
364 // find superstate of source 's', ignore the result
365 static_cast<void>((*s)(this, &l_resEvt_[Q_EMPTY_SIG]));
366
367 // (c) check source->super==target->super...
368 if (m_temp.fun == t) {
369 // exit source 's'
370 if ((*s)(this, &l_resEvt_[Q_EXIT_SIG]) == Q_RET_HANDLED) {
371 QS_STATE_ACT_(QS_QEP_STATE_EXIT, s); // output QS record
372 }
373 }
374 // (d) check source->super==target...
375 else if (m_temp.fun == path[0U]) {
376 // exit source 's'
377 if ((*s)(this, &l_resEvt_[Q_EXIT_SIG]) == Q_RET_HANDLED) {
378 QS_STATE_ACT_(QS_QEP_STATE_EXIT, s); // output QS record
379 }
380 ip = 0U; // set entry path index NOT to enter the target
381 }
382 else { // tran. more complex
383 path[1U] = t; // save the superstate of target
384 ip = 2U; // need QHsm::tran_complex_()
385 }
386 }
387 }
388 // return: # levels in path[] for QHsm_enter_target_()
389 // or indication to call QHsm_tran_complex_()
390 return ip;
391}
392
393//............................................................................
394//! @private @memberof QHsm
396 std::array<QStateHandler, MAX_NEST_DEPTH_> &path,
397 std::uint_fast8_t const qsId)
398{
399#ifndef Q_SPY
400 Q_UNUSED_PAR(qsId);
401#endif
402
403 QStateHandler s = path[2U]; // tran. source
404 QStateHandler const ss = m_temp.fun; // source->super
405 m_temp.fun = path[1U]; // target->super
406 QState r;
407
408 // (e) check rest of source == target->super->super...
409 // and store the target entry path along the way
410 std::size_t ip = 1U; // path index & fixed loop bound
411 std::size_t iq = 0U; // assume that LCA is NOT found
412 do {
413 // the entry path index must stay in range of the path[] array
415
416 path[ip] = m_temp.fun; // store temp in the entry path array
417 ++ip;
418
419 // find superstate of 'm_temp.fun'
420 r = (*m_temp.fun)(this, &l_resEvt_[Q_EMPTY_SIG]);
421 if (m_temp.fun == s) { // is temp the LCA?
422 iq = 1U; // indicate that LCA is found
423 break;
424 }
425 } while (r == Q_RET_SUPER); // loop as long as superstate reached
426
427 if (iq == 0U) { // the LCA not found yet?
429
430#ifndef Q_SPY
431 // exit the source 's', ignore the result
432 static_cast<void>((*s)(this, &l_resEvt_[Q_EXIT_SIG]));
433#else
434 // exit the source 's'
435 if ((*s)(this, &l_resEvt_[Q_EXIT_SIG]) == Q_RET_HANDLED) {
436 QS_STATE_ACT_(QS_QEP_STATE_EXIT, s); // output QS record
437 }
438#endif // def Q_SPY
439
440 // (f) check the rest of
441 // source->super... == target->super->super...
442 s = ss; // source->super
443 r = Q_RET_IGNORED; // assume that the LCA NOT found
444 iq = ip;
445 while (iq > 0U) {
446 --iq;
447 if (s == path[iq]) { // is this the LCA?
448 r = Q_RET_HANDLED; // indicate the LCA found
449 ip = iq; // do NOT enter the LCA
450 break;
451 }
452 }
453
454 if (r != Q_RET_HANDLED) { // the LCA still not found?
455 // (g) check each source->super->...
456 // for each target->super...
457 do {
458 // exit from 's'
459 if ((*s)(this, &l_resEvt_[Q_EXIT_SIG]) == Q_RET_HANDLED) {
460 QS_STATE_ACT_(QS_QEP_STATE_EXIT, s);
461 // find superstate of 's', ignore the result
462 static_cast<void>((*s)(this, &l_resEvt_[Q_EMPTY_SIG]));
463 }
464 s = m_temp.fun; // set to super of s
465 // NOTE: loop bounded per invariant:540
466 iq = ip;
467 while (iq > 0U) {
468 --iq;
469 if (s == path[iq]) { // is this the LCA?
470 ip = iq; // do NOT to enter the LCA
471 r = Q_RET_HANDLED; // cause break from outer loop
472 break;
473 }
474 }
475 } while (r != Q_RET_HANDLED);
476 }
477 }
478 // # levels in path[] for QHsm_enter_target_()
479 return ip;
480}
481
482//............................................................................
483//! @private @memberof QHsm
485 std::array<QStateHandler, MAX_NEST_DEPTH_> &path,
486 std::size_t const depth,
487 std::uint_fast8_t const qsId)
488{
489#ifndef Q_SPY
490 Q_UNUSED_PAR(qsId);
491#endif
492
494 std::size_t ip = depth;
495
497
498 // execute entry actions from LCA to tran target...
499 while (ip > 0U) {
500 --ip;
501 // enter 'path[ip]'
502 if ((*path[ip])(this, &l_resEvt_[Q_ENTRY_SIG]) == Q_RET_HANDLED) {
503 QS_STATE_ACT_(QS_QEP_STATE_ENTRY, path[ip]); // output QS record
504 }
505 }
506 QStateHandler t = path[0U]; // tran. target
507
508 // drill into the target hierarchy with nested initial trans...
509
510 // take initial tran in 't'
511 while ((*t)(this, &l_resEvt_[Q_INIT_SIG]) == Q_RET_TRAN) { // tran. taken?
512 // temp holds the target of initial tran. and must be valid
513 Q_ASSERT_LOCAL(650, m_temp.fun != nullptr);
514
515 QS_TRAN_SEG_(QS_QEP_STATE_INIT, t, m_temp.fun); // output QS record
516
517 // find superstate of initial tran. target...
518 ip = 0U; // entry path index and fixed loop bound
519 do {
520 // the entry path index must stay in range of the path[] array
522
523 path[ip] = m_temp.fun; // store the entry path
524 ++ip;
525
526 // find superstate of 'm_temp.fun'
527 QState const r = (*m_temp.fun)(this, &l_resEvt_[Q_EMPTY_SIG]);
528
529 // the temp superstate handler must return superstate
530 Q_ASSERT_LOCAL(680, r == Q_RET_SUPER);
531#ifdef Q_UNSAFE
532 Q_UNUSED_PAR(r);
533#endif
534 } while (m_temp.fun != t); // loop as long as tran.target not reached
535
536 // retrace the entry path in reverse (correct) order...
537 while (ip > 0U) {
538 --ip;
539 // enter 'path[ip]'
540 if ((*path[ip])(this, &l_resEvt_[Q_ENTRY_SIG]) == Q_RET_HANDLED) {
541 QS_STATE_ACT_(QS_QEP_STATE_ENTRY, path[ip]);//output QS record
542 }
543 }
544 t = path[0U]; // tran. target becomes the new source
545 }
546}
547
548//............................................................................
549bool QHsm::isIn(QStateHandler const stateHndl) noexcept {
550 // this state machine must be in a stable state configuration
551 // NOTE: stable state configuration is established after every RTC step.
554
555 bool inState = false; // assume that this HSM is NOT in 'stateHndl'
556
557 // scan the state hierarchy bottom-up
558 QStateHandler s = m_state.fun;
559 QState r;
560 do {
561 if (s == stateHndl) { // do the states match?
562 inState = true; // 'true' means that match found
563 break; // break out of the do-loop
564 }
565
566 // find superstate of 's'
567 r = (*s)(this, &l_resEvt_[Q_EMPTY_SIG]);
568 s = m_temp.fun;
569 } while (r == Q_RET_SUPER);
570
571#ifndef Q_UNSAFE
572 // restore the invariant (stable state configuration)
574#endif
575 return inState; // return the status
576}
577
578//............................................................................
579QStateHandler QHsm::childState(QStateHandler const parentHndl) noexcept {
580 // NOTE: this function is designed to be called during an RTC step,
581 // so it does NOT assume to be called in a stable state configuration
582 // and also does NOT establish stable state configuration upon exit.
583
584#ifndef Q_UNSAFE
585 bool isFound = false; // assume the child state NOT found
586#endif
587
588 QStateHandler child = m_state.fun; // child state to find
589 m_temp.fun = child; // start from the current state
591 do {
592 // have the parent of the current child?
593 if (m_temp.fun == parentHndl) {
594#ifndef Q_UNSAFE
595 isFound = true; // indicate that child state was found
596#endif
597 break;
598 }
599 child = m_temp.fun;
600
601 // find superstate of 'child' (placed in m_temp)
602 r = (*child)(this, &l_resEvt_[Q_EMPTY_SIG]);
603 } while (r == Q_RET_SUPER);
604 Q_ENSURE_LOCAL(890, isFound);
605
606 return child;
607}
608
609//............................................................................
611 // NOTE: this function does NOT apply critical section, so it can
612 // be safely called from an already established critical section.
613 return m_state.fun; // public "getter" to the state handler (function)
614}
615
616} // namespace QP
QAsm() noexcept
Constructor of the QP::QAsm base class.
Definition qf_act.cpp:75
static constexpr QState Q_RET_UNHANDLED
Definition qp.hpp:175
static constexpr QState Q_RET_TRAN
Definition qp.hpp:177
QAsmAttr m_temp
Temporary storage for target/act-table etc.
Definition qp.hpp:170
static constexpr QState Q_RET_IGNORED
Definition qp.hpp:181
static constexpr QState Q_RET_SUPER
Definition qp.hpp:174
static constexpr QState Q_RET_TRAN_HIST
Definition qp.hpp:178
static constexpr QSignal Q_INIT_SIG
Definition qp.hpp:193
QAsmAttr m_state
Current state (pointer to the current state-handler function).
Definition qp.hpp:169
static constexpr QSignal Q_ENTRY_SIG
Definition qp.hpp:191
static constexpr QSignal Q_EXIT_SIG
Definition qp.hpp:192
static constexpr QSignal Q_EMPTY_SIG
Definition qp.hpp:190
static constexpr QState Q_RET_HANDLED
Definition qp.hpp:176
static QState top(void *const me, QEvt const *const e) noexcept
Top state handler that ignores all events.
Definition qf_act.cpp:80
Event class.
Definition qp.hpp:101
void dispatch(QEvt const *const e, std::uint_fast8_t const qsId) override
Virtual function to dispatch an event to the state machine.
Definition qep_hsm.cpp:225
static constexpr std::size_t MAX_NEST_DEPTH_
Definition qp.hpp:319
void enter_target_(std::array< QStateHandler, MAX_NEST_DEPTH_ > &path, std::size_t const depth, std::uint_fast8_t const qsId)
QStateHandler childState(QStateHandler const parentHndl) noexcept
Obtain the current active child state of a given parent in QP::QMsm.
Definition qep_hsm.cpp:579
void init(void const *const e, std::uint_fast8_t const qsId) override
Virtual function to take the top-most initial transition in the state machine.
Definition qep_hsm.cpp:150
std::size_t tran_simple_(std::array< QStateHandler, MAX_NEST_DEPTH_ > &path, std::uint_fast8_t const qsId)
QHsm(QStateHandler const initial) noexcept
Definition qep_hsm.cpp:142
bool isIn(QStateHandler const stateHndl) noexcept override
Check whether the HSM is in a given state.
Definition qep_hsm.cpp:549
std::size_t tran_complex_(std::array< QStateHandler, MAX_NEST_DEPTH_ > &path, std::uint_fast8_t const qsId)
QStateHandler getStateHandler() const noexcept override
Virtual method for getting the current state handler.
Definition qep_hsm.cpp:610
static Attr priv_
Definition qs.hpp:473
QP/C++ Framework namespace.
Definition qequeue.hpp:36
@ QS_QEP_DISPATCH
an event was dispatched (begin of RTC step)
Definition qs.hpp:64
@ QS_QEP_STATE_ENTRY
a state was entered
Definition qs.hpp:57
@ QS_QEP_STATE_EXIT
a state was exited
Definition qs.hpp:58
@ QS_QEP_TRAN_HIST
a tran. to history was taken
Definition qs.hpp:137
@ QS_QEP_IGNORED
an event was ignored (silently discarded)
Definition qs.hpp:63
@ QS_QEP_UNHANDLED
an event was un-handled due to a guard
Definition qs.hpp:65
@ QS_QEP_STATE_INIT
an initial transition was taken in a state
Definition qs.hpp:59
@ QS_QEP_TRAN
a regular transition was taken
Definition qs.hpp:62
@ QS_QEP_INIT_TRAN
the top-most initial transition was taken
Definition qs.hpp:60
@ QS_QEP_INTERN_TRAN
an internal transition was taken
Definition qs.hpp:61
static T_ dis_update(T_ const org)
Internal function template to calculate the Duplicate Inverse Storage (DIS).
Definition qp_pkg.hpp:59
static bool dis_verify(T_ const org, T_ const dis)
Internal function template to verify the Duplicate Inverse Storage (DIS).
Definition qp_pkg.hpp:66
std::uint_fast8_t QState
Type returned from state-handler functions.
Definition qp.hpp:134
QState(*)(void *const me, QEvt const *const e) QStateHandler
Pointer to a state-handler function.
Definition qp.hpp:138
std::uint16_t QSignal
The signal of event QP::QEvt.
Definition qp.hpp:98
#define Q_EVT_CAST(subclass_)
Perform downcast of an event onto a subclass of QP::QEvt class_.
Definition qp.hpp:388
#define Q_UNUSED_PAR(par_)
Helper macro to mark unused parameters of functions.
Definition qp.hpp:89
#define Q_STATE_CAST(handler_)
Perform cast to QP::QStateHandler.
Definition qp.hpp:389
QP/C++ Framework in C++ internal (package-scope) interface.
Sample QP/C++ port.
#define QS_CRIT_STAT
Internal QS macro for defining the critical section status.
Definition qs.hpp:430
#define QS_FUN_DICTIONARY(fun_)
Produce function dictionary (typically for state-handler functions).
Definition qs.hpp:400
#define QS_CRIT_EXIT()
Internal macro for exiting a critical section.
Definition qs.hpp:438
#define QS_CRIT_ENTRY()
Internal macro for entering a critical section.
Definition qs.hpp:434
QS (QP/Spy software tracing) internal (package-scope) interface.
Sample QS/C++ port.
QP Functional Safety (FuSa) Subsystem.
#define Q_REQUIRE_LOCAL(id_, expr_)
Assertion for checking a precondition (local critical section).
Definition qsafe.h:99
#define Q_ERROR_LOCAL(id_)
Assertion with user-specified ID for a wrong path through the code (local critical section).
Definition qsafe.h:111
#define Q_ENSURE_LOCAL(id_, expr_)
Assertion for checking a postcondition (local critical section).
Definition qsafe.h:104
#define Q_ASSERT_LOCAL(id_, expr_)
General-purpose assertion with user-specified ID number (local critical section).
Definition qsafe.h:72
#define Q_INVARIANT_LOCAL(id_, expr_)
Assertion for checking a postcondition (local critical section).
Definition qsafe.h:109