Zth (libzth)
Loading...
Searching...
No Matches
fsm.h
Go to the documentation of this file.
1#ifndef ZTH_FSM_H
2#define ZTH_FSM_H
3/*
4 * SPDX-FileCopyrightText: 2019-2026 Jochem Rutgers
5 *
6 * SPDX-License-Identifier: MPL-2.0
7 */
8
18#include <libzth/macros.h>
19
20#ifdef __cplusplus
21# include <libzth/allocator.h>
22# include <libzth/time.h>
23# include <libzth/util.h>
24# include <libzth/waiter.h>
25
26// Suppress missing braces, as this is what you do when you specify the FSM.
27# pragma GCC diagnostic ignored "-Wmissing-braces"
28
29# if __cplusplus >= 201402L
30# define deprecated14(msg) [[deprecated(msg)]]
31# else
32# define deprecated14(msg)
33# endif
34
35namespace zth {
36
37namespace guards {
38
39enum End {
44 end = 0
45};
46
51template <typename Fsm>
52ZTH_EXPORT TimeInterval always(Fsm& fsm)
53{
54 zth_dbg(fsm, "[%s] Guard always", fsm.id_str());
55 return TimeInterval();
56}
57
64template <typename FsmInput, typename FsmInput::Input i, typename Fsm>
65ZTH_EXPORT TimeInterval input(Fsm& fsm)
66{
67 if(fsm.clearInput(i)) {
68 zth_dbg(fsm, "[%s] Guard input %s", fsm.id_str(), str(i).c_str());
69 return TimeInterval();
70 } else
72}
73
80template <typename FsmInput, typename FsmInput::Input i, typename Fsm>
81ZTH_EXPORT TimeInterval peek(Fsm& fsm)
82{
83 if(fsm.hasInput(i)) {
84 zth_dbg(fsm, "[%s] Guard peek input %s", fsm.id_str(), str(i).c_str());
85 return TimeInterval();
86 } else
88}
89
90template <typename Fsm>
92{
93 TimeInterval ti = timeout - fsm.dt();
94 if(ti.hasPassed())
95 zth_dbg(fsm, "[%s] Guard timeout %s", fsm.id_str(), timeout.str().c_str());
96 return ti;
97}
98
103template <time_t s, typename Fsm>
104ZTH_EXPORT TimeInterval timeout_s(Fsm& fsm)
105{
106 static constexpr TimeInterval const timeout(s);
107 return timeout_<Fsm>(fsm, timeout);
108}
109
114template <unsigned int ms, typename Fsm>
116{
117 static TimeInterval const timeout((double)ms * 1e-3);
118 return timeout_<Fsm>(fsm, timeout);
119}
120
125template <uint64_t us, typename Fsm>
127{
128 static TimeInterval const timeout((double)us * 1e-6);
129 return timeout_<Fsm>(fsm, timeout);
130}
131
136template <typename Fsm>
137ZTH_EXPORT TimeInterval lock(Fsm& fsm)
138{
139 if(fsm.guardLock()) {
140 zth_dbg(fsm, "[%s] Guard lock", fsm.id_str());
141 return TimeInterval();
142 } else
143 return TimeInterval::infinity();
144}
145
150template <typename Fsm>
151ZTH_EXPORT TimeInterval step(Fsm& fsm)
152{
153 if(fsm.guardStep()) {
154 zth_dbg(fsm, "[%s] Guard step", fsm.id_str());
155 return TimeInterval();
156 } else
157 return TimeInterval::infinity();
158}
159} // namespace guards
160
173template <typename Fsm>
174class FsmGuard {
175public:
176 typedef TimeInterval (*Function)(Fsm& fsm);
177
178 // cppcheck-suppress noExplicitConstructor
179 constexpr FsmGuard(Function function)
180 : m_function(function)
181 {}
182
183 // cppcheck-suppress noExplicitConstructor
185 : m_function()
186 {}
187
189 {
190 zth_assert(valid());
191 return m_function(fsm);
192 }
193 constexpr bool valid() const
194 {
195 return m_function;
196 }
197
198private:
199 Function m_function;
200};
201
208template <typename Fsm>
210 union {
213 };
215};
216
222template <typename Fsm>
224public:
226 : m_description(description)
227 , m_compiled()
228 {}
229
230# if GCC_VERSION >= 49000L
231 __attribute__((returns_nonnull))
232# endif
233 __attribute__((warn_unused_result)) Fsm*
234 create() const
235 {
236 return new Fsm(*this);
237 }
238
240 {
241 compile();
242 return m_description;
243 }
244
245protected:
246 void compile() const
247 {
248 if(likely(m_compiled))
249 return;
250
251 typename map_type<typename Fsm::State, FsmDescription<Fsm> const*>::type stateAddr;
252 FsmDescription<Fsm>* p = m_description;
253 while(true) {
254 // Register this state
255 zth_assert(stateAddr.count(p->state) == 0);
256 stateAddr[p->state] = const_cast<FsmDescription<Fsm> const*>(p);
257
258 if(!p->guard.valid())
259 // End of description
260 break;
261
262 // Go to end of guard list
263 while((p++)->guard.valid())
264 ;
265 }
266
267 // Patch State references
268 p = m_description;
269 while(true) {
270 if(!p->guard.valid())
271 // End of description
272 break;
273
274 // Patch this state's guard list
275 while((p++)->guard.valid()) {
276 zth_assert(stateAddr.count(p->state) == 1);
277 p->stateAddr = stateAddr[p->state];
278 }
279 }
280
281 m_compiled = true;
282 }
283
284private:
285 FsmDescription<Fsm>* const m_description;
286 mutable bool m_compiled;
287};
288
302template <typename State_, typename Input_ = int, typename FsmImpl_ = void>
303class Fsm : public UniqueID<Fsm<void, void, void> > {
305public:
307 typedef State_ State;
308 typedef Input_ Input;
311
312protected:
315
323
324public:
325 explicit Fsm(Compiler const& compiler, char const* name = "FSM")
326 : UniqueID(name)
327 , m_compiler(&compiler)
328 , m_evalState(evalInit)
329 , m_lockstep(lockstepNormal)
330 {
331# if __cplusplus >= 201103L && !defined(DOXYGEN)
332 static_assert(std::is_base_of<Fsm, FsmImpl>::value, "");
333# endif
334 }
335
336 explicit Fsm(Description description, char const* name = "FSM")
337 : UniqueID(name)
338 , m_description(description)
339 , m_evalState(evalCompile)
340 , m_lockstep(lockstepNormal)
341 {}
342
343 virtual ~Fsm() {}
344
345 State const& state() const
346 {
347 switch(m_evalState) {
348 default:
349 return m_state->state;
350 case evalCompile:
351 return m_description->state;
352 case evalInit:
353 return m_compiler->description()->state;
354 case evalReset:
356 }
357 }
358
359 Timestamp const& t() const
360 {
361 return m_t;
362 }
363
365 {
366 return Timestamp::now() - t();
367 }
368
369 State const& next() const
370 {
371 switch(m_evalState) {
372 default:
373 zth_assert(exit() || m_stateNext == m_state);
374 return m_stateNext->state;
375 case evalCompile:
376 return m_description->state;
377 case evalInit:
378 return m_compiler->description()->state;
379 case evalReset:
381 }
382 }
383
384 void reset()
385 {
386 zth_dbg(fsm, "[%s] Reset", id_str());
387 switch(m_evalState) {
388 default:
389 // If you get here, you probably called reset from within the callback
390 // function, which you shouldn't do.
391 zth_assert(false);
393 case evalIdle:
394 m_evalState = evalReset;
395 break;
396 case evalCompile:
397 case evalInit:
398 case evalReset:
399 break;
400 }
401 clearInputs();
402 }
403
404 bool entry() const
405 {
406 return m_entry;
407 }
408
409 bool exit() const
410 {
411 return m_exit;
412 }
413
417 bool lockstep() const
418 {
419 return m_lockstep != lockstepNormal;
420 }
421
455 void setLockstep(bool enable)
456 {
457 if(lockstep() == enable)
458 return;
459
460 switch(m_lockstep) {
461 case lockstepNormal:
462 m_lockstep = lockstepLock;
463 break;
464 default:
465 m_lockstep = lockstepNormal;
466 break;
467 }
468 trigger();
469 }
470
477 {
478 switch(m_lockstep) {
479 case lockstepLock:
480 case lockstepStep:
481 return true;
482 default:
483 return false;
484 }
485 }
486
493 {
494 switch(m_lockstep) {
495 case lockstepLock:
496 return false;
497 case lockstepStep:
498 m_lockstep = lockstepSteppingNext;
499 return true;
500 default:
501 return true;
502 }
503 }
504
509 void step()
510 {
511 switch(m_lockstep) {
512 case lockstepLock:
513 m_lockstep = lockstepStep;
514 trigger();
515 break;
516 default:;
517 }
518 }
519
520 void input(Input i)
521 {
522 m_inputs.push_back(i);
523 trigger();
524 }
525
527 {
528 for(size_t j = 0; j < m_inputs.size(); j++)
529 if(m_inputs[j] == i) {
530 m_inputs[j] = m_inputs.back();
531 m_inputs.pop_back();
532 return true;
533 }
534 return false;
535 }
536
538 {
539 m_inputs.clear();
540 }
541
542 void setInputsCapacity(size_t capacity)
543 {
544# if __cplusplus >= 201103L
545 if(m_inputs.capacity() > capacity * 2U) {
546 // Shrink when the current capacity is significantly more.
547 m_inputs.shrink_to_fit();
548 }
549# endif
550
551 m_inputs.reserve(capacity);
552 }
553
554 bool hasInput(Input i) const
555 {
556 for(size_t j = 0; j < m_inputs.size(); j++)
557 if(m_inputs[j] == i)
558 return true;
559 return false;
560 }
561
562 TimeInterval eval(bool alwaysDoCallback = false)
563 {
564 bool didCallback = false;
566
567 switch(m_evalState) {
568 case evalCompile:
570 if(false) {
572 case evalInit:
574 }
576 case evalReset:
577 m_stateNext = m_state = m_compiledDescription;
578 m_evalState = evalState;
579 zth_dbg(fsm, "[%s] Initial state %s", id_str(), str(state()).c_str());
580 m_t = Timestamp::now();
581 m_exit = false;
582 m_entry = true;
583 callback();
584 m_entry = false;
585 didCallback = true;
587 case evalIdle: {
588 do {
589 m_evalState = evalState;
590 while((wait = evalOnce()).hasPassed())
591 didCallback = true;
592 if(alwaysDoCallback && !didCallback)
593 callback();
594 } while(m_evalState == evalRecurse);
595 m_evalState = evalIdle;
596 break;
597 }
598 case evalState:
599 m_evalState = evalRecurse;
601 case evalRecurse:
602 break;
603 }
604 return wait;
605 }
606
607 deprecated14("Use zth::fsm::compile() instead") void run()
608 {
609 TimeInterval wait = eval();
610 if(!m_state->guard.valid()) {
611done:
612 zth_dbg(fsm, "[%s] Final state %s", id_str(), str(state()).c_str());
613 return;
614 }
615
616 PolledMemberWaiting<Fsm> wake_up(*this, &Fsm::trigger_, wait);
617 do {
618 if(wake_up.interval().isInfinite()) {
619 m_trigger.wait();
620 } else {
621 scheduleTask(wake_up);
622 m_trigger.wait();
623 unscheduleTask(wake_up);
624 }
625 wait = eval();
626 wake_up.setInterval(wait, currentFiber().runningSince());
627 } while(m_state->guard.valid());
628 goto done;
629 }
630
631 void trigger()
632 {
633 m_trigger.signal(false);
634 }
635
636private:
637 bool trigger_()
638 {
639 m_trigger.signal(false);
640 return true;
641 }
642
643 TimeInterval evalOnce()
644 {
645 TimeInterval wait = TimeInterval::infinity();
646 StateAddr p = m_state;
647 while(p->guard.valid()) {
648 TimeInterval ti((p++)->guard(static_cast<FsmImpl&>(*this)));
649 if(ti.hasPassed()) {
650 setState(p->stateAddr);
651 wait = ti; // NVRO
652 return wait; // Return any passed TimeInterval, which indicates that
653 // a transition was taken.
654 } else if(ti < wait) {
655 // Save shortest wait interval.
656 wait = ti;
657 }
658 }
659 zth_dbg(fsm, "[%s] State %s blocked for %s", id_str(), str(state()).c_str(),
660 wait.str().c_str());
661 return wait;
662 }
663
664 void setState(StateAddr nextState)
665 {
666 if(nextState == m_state)
667 zth_dbg(fsm, "[%s] Selfloop of state %s", id_str(), str(state()).c_str());
668 else
669 zth_dbg(fsm, "[%s] Transition %s -> %s", id_str(), str(state()).c_str(),
670 str(nextState->state).c_str());
671
672 m_stateNext = nextState;
673
674 m_exit = true;
675 callback();
676 m_exit = false;
677
678 m_state = nextState;
679 m_t = Timestamp::now();
680
681 switch(m_lockstep) {
683 m_lockstep = lockstepStepping;
684 break;
685 case lockstepStepping:
686 m_lockstep = lockstepLock;
687 break;
688 default:;
689 }
690
691 m_entry = true;
692 callback();
693 m_entry = false;
694 }
695
696protected:
704 virtual void callback() = 0;
705
706private:
707 union {
708 FsmDescription<FsmImpl>* m_description; // only valid during stateCompile
709 Compiler const* m_compiler; // only valid during stateInit
711 };
712 StateAddr m_state;
713 StateAddr m_stateNext;
714 EvalState m_evalState;
715 Timestamp m_t;
716 bool m_entry;
717 bool m_exit;
718 Lockstep m_lockstep;
719 Signal m_trigger;
720 typename vector_type<Input>::type m_inputs;
721};
722
723template <
724 typename State_, typename CallbackArg_ = void, typename Input_ = int,
725 typename FsmImpl_ = void>
727 : public Fsm<
728 State_, Input_,
729 typename choose_type<
730 FsmImpl_, FsmCallback<State_, CallbackArg_, Input_, void> >::type> {
732public:
733 typedef typename choose_type<
736 typedef CallbackArg_ CallbackArg;
737 typedef void (*Callback)(FsmCallback&, CallbackArg);
738
739 // cppcheck-suppress noExplicitConstructor
741 // cppcheck-suppress constParameter
742 typename base::Compiler const& compiler, Callback const& cb,
743 CallbackArg const& cbArg, char const* name = "FSM")
744 : base(compiler, name)
745 , m_callback(cb)
746 , m_callbackArg(cbArg)
747 {}
748
749 // cppcheck-suppress noExplicitConstructor
751 // cppcheck-suppress passedByValue
752 // cppcheck-suppress constParameter
753 typename base::Description description, Callback const& cb,
754 CallbackArg const& cbArg, char const* name = "FSM")
755 : base(description, name)
756 , m_callback(cb)
757 , m_callbackArg(cbArg)
758 {}
759
760 virtual ~FsmCallback() override {}
761
763 {
764 return m_callbackArg;
765 }
766
767protected:
768 virtual void callback() override
769 {
770 if(m_callback) {
771 zth_dbg(fsm, "[%s] Callback for %s%s", this->id_str(),
772 str(this->state()).c_str(),
773 this->entry() ? " (entry)"
774 : this->exit() ? " (exit)"
775 : "");
776 m_callback(*this, m_callbackArg);
777 }
778 }
779
780private:
781 Callback const m_callback;
782 CallbackArg const m_callbackArg;
783};
784
785template <typename State_, typename Input_, typename FsmImpl_>
786class FsmCallback<State_, void, Input_, FsmImpl_>
787 : public Fsm<
788 State_, Input_,
789 typename choose_type<
790 FsmImpl_, FsmCallback<State_, void, Input_, void> >::type> {
792public:
796 typedef void (*Callback)(FsmCallback&);
797
798 explicit FsmCallback(
799 typename base::Compiler const& compiler, Callback cb = nullptr,
800 char const* name = "FSM")
801 : base(compiler, name)
802 , m_callback(cb)
803 {}
804
805 explicit FsmCallback(
806 // cppcheck-suppress passedByValue
807 typename base::Description description, Callback cb = nullptr,
808 char const* name = "FSM")
809 : base(description, name)
810 , m_callback(cb)
811 {}
812
813 virtual ~FsmCallback() override {}
814
815protected:
816 virtual void callback() override
817 {
818 if(m_callback) {
819 zth_dbg(fsm, "[%s] Callback for %s%s", this->id_str(),
820 str(this->state()).c_str(),
821 this->entry() ? " (entry)"
822 : this->exit() ? " (exit)"
823 : "");
824 m_callback(*this);
825 }
826 }
827
828private:
829 Callback const m_callback;
830};
831
832} // namespace zth
833#endif // __cplusplus
834#endif // ZTH_FSM_H
FsmCallback(typename base::Compiler const &compiler, Callback cb=nullptr, char const *name="FSM")
Definition fsm.h:798
choose_type< FsmImpl_, FsmCallback< State_, void, Input_, void > >::type FsmImpl
Definition fsm.h:794
virtual void callback() override
This function is called when the FSM has to execute the code belonging by the current state.
Definition fsm.h:816
Fsm< State_, Input_, FsmImpl > base
Definition fsm.h:795
FsmCallback(typename base::Description description, Callback cb=nullptr, char const *name="FSM")
Definition fsm.h:805
CallbackArg callbackArg() const
Definition fsm.h:762
void(* Callback)(FsmCallback &, CallbackArg)
Definition fsm.h:737
CallbackArg_ CallbackArg
Definition fsm.h:736
FsmCallback(typename base::Compiler const &compiler, Callback const &cb, CallbackArg const &cbArg, char const *name="FSM")
Definition fsm.h:740
FsmCallback(typename base::Description description, Callback const &cb, CallbackArg const &cbArg, char const *name="FSM")
Definition fsm.h:750
choose_type< FsmImpl_, FsmCallback< State_, CallbackArg_, Input_, void > >::type FsmImpl
Definition fsm.h:734
Fsm< State_, Input_, FsmImpl > base
Definition fsm.h:735
virtual void callback() override
This function is called when the FSM has to execute the code belonging by the current state.
Definition fsm.h:768
virtual ~FsmCallback() override
Definition fsm.h:760
A compiler to turn an zth::FsmDescription into something that can be used by zth::Fsm.
Definition fsm.h:223
FsmDescription< Fsm > const * description() const
Definition fsm.h:239
void compile() const
Definition fsm.h:246
constexpr FsmCompiler(FsmDescription< Fsm > *description)
Definition fsm.h:225
Fsm * create() const
Definition fsm.h:234
A guard is evaluated, and when true, the corresponding transition is taken.
Definition fsm.h:174
constexpr bool valid() const
Definition fsm.h:193
TimeInterval(* Function)(Fsm &fsm)
Definition fsm.h:176
TimeInterval operator()(Fsm &fsm) const
Definition fsm.h:188
constexpr FsmGuard(Function function)
Definition fsm.h:179
FsmGuard(guards::End)
Definition fsm.h:184
A Finite-state machine.
Definition fsm.h:303
bool lockstep() const
Check if lockstep mode is enabled.
Definition fsm.h:417
Lockstep
Definition fsm.h:316
@ lockstepLock
Definition fsm.h:318
@ lockstepNormal
Definition fsm.h:317
@ lockstepStep
Definition fsm.h:319
@ lockstepStepping
Definition fsm.h:321
@ lockstepSteppingNext
Definition fsm.h:320
bool guardStep()
Check if a step was requested while paused in lockstep mode.
Definition fsm.h:492
bool exit() const
Definition fsm.h:409
bool clearInput(Input i)
Definition fsm.h:526
void step()
Allow the Fsm to proceed one step, if in lockstep mode.
Definition fsm.h:509
void run()
Definition fsm.h:607
void input(Input i)
Definition fsm.h:520
virtual void callback()=0
This function is called when the FSM has to execute the code belonging by the current state.
State const & state() const
Definition fsm.h:345
Fsm(Compiler const &compiler, char const *name="FSM")
Definition fsm.h:325
FsmDescription< FsmImpl > * m_description
Definition fsm.h:708
Timestamp const & t() const
Definition fsm.h:359
void clearInputs()
Definition fsm.h:537
FsmDescription< FsmImpl > const * m_compiledDescription
Definition fsm.h:710
FsmDescription< FsmImpl > const * StateAddr
Definition fsm.h:314
void trigger()
Definition fsm.h:631
void setInputsCapacity(size_t capacity)
Definition fsm.h:542
FsmDescription< FsmImpl > Description[]
Definition fsm.h:310
State_ State
Definition fsm.h:307
bool entry() const
Definition fsm.h:404
virtual ~Fsm()
Definition fsm.h:343
TimeInterval dt() const
Definition fsm.h:364
choose_type< FsmImpl_, Fsm >::type FsmImpl
Definition fsm.h:306
Compiler const * m_compiler
Definition fsm.h:709
Fsm(Description description, char const *name="FSM")
Definition fsm.h:336
State const & next() const
Definition fsm.h:369
EvalState
Definition fsm.h:313
@ evalReset
Definition fsm.h:313
@ evalCompile
Definition fsm.h:313
@ evalInit
Definition fsm.h:313
@ evalState
Definition fsm.h:313
@ evalIdle
Definition fsm.h:313
@ evalRecurse
Definition fsm.h:313
bool hasInput(Input i) const
Definition fsm.h:554
bool guardLock()
Check if a lock was requested while running in lockstep mode.
Definition fsm.h:476
Input_ Input
Definition fsm.h:308
void setLockstep(bool enable)
Enable/disable lockstep mode.
Definition fsm.h:455
FsmCompiler< FsmImpl > Compiler
Definition fsm.h:309
TimeInterval eval(bool alwaysDoCallback=false)
Definition fsm.h:562
void reset()
Definition fsm.h:384
void setInterval(TimeInterval const &interval, Timestamp const &now=Timestamp::now()) noexcept
Definition waiter.h:146
TimeInterval const & interval() const noexcept
Definition waiter.h:140
Fiber-aware signal.
Definition sync.h:512
void signal(bool queue=true, bool queueEveryTime=false) noexcept
Definition sync.h:565
void wait()
Definition sync.h:529
Convenient wrapper around struct timespec that contains a time interval.
Definition time.h:55
static constexpr TimeInterval null() noexcept
Definition time.h:69
constexpr bool isInfinite() const noexcept
Definition time.h:256
static constexpr TimeInterval infinity() noexcept
Definition time.h:64
constexpr bool hasPassed() const noexcept
Definition time.h:261
string str() const
Definition time.h:426
Convenient wrapper around struct timespec that contains an absolute timestamp.
Definition time.h:568
static Timestamp now()
Definition time.h:595
friend cow_string str(UniqueIDBase const &)
Keeps track of a process-wide unique ID within the type T.
Definition util.h:715
virtual char const * id_str() const override
Definition util.h:809
string const & name() const noexcept
Definition util.h:783
string str() &&
Definition util.h:379
char const * c_str() const
Definition util.h:391
#define deprecated14(msg)
Definition fsm.h:30
Fiber & currentFiber() noexcept
Return the currently executing fiber.
Definition worker.h:399
TimeInterval timeout_s(Fsm &fsm)
A guard that is true when the Fsm stayed for the given time in this state.
Definition fsm.h:104
TimeInterval lock(Fsm &fsm)
A wrapper for zth::Fsm::guardLock().
Definition fsm.h:137
TimeInterval always(Fsm &fsm)
A guard that is always true.
Definition fsm.h:52
TimeInterval step(Fsm &fsm)
A wrapper for zth::Fsm::guardStep().
Definition fsm.h:151
TimeInterval peek(Fsm &fsm)
A guard that is true when the given input has been set.
Definition fsm.h:81
TimeInterval timeout_us(Fsm &fsm)
A guard that is true when the Fsm stayed for the given time in this state.
Definition fsm.h:126
@ end
End-of-guard-list marker.
Definition fsm.h:44
TimeInterval input(Fsm &fsm)
A guard that is true when the given input has been set.
Definition fsm.h:65
TimeInterval timeout_ms(Fsm &fsm)
A guard that is true when the Fsm stayed for the given time in this state.
Definition fsm.h:115
#define zth_dbg(group, fmt, a...)
Debug printf()-like function.
Definition util.h:189
#define ZTH_CLASS_NEW_DELETE(T)
Define new/delete operators for a class, which are allocator-aware.
Definition allocator.h:143
#define ZTH_FALLTHROUGH
Definition macros.h:89
TimeInterval timeout_(Fsm &fsm, TimeInterval const &timeout)
Definition fsm.h:91
cow_string str(T value)
Returns an zth::string representation of the given value.
Definition util.h:492
void unscheduleTask(TimedWaitable &w)
Definition waiter.cpp:66
void scheduleTask(TimedWaitable &w)
Definition waiter.cpp:54
The description of a Fsm.
Definition fsm.h:209
FsmDescription const * stateAddr
Definition fsm.h:212
FsmGuard< Fsm > guard
Definition fsm.h:214
Fsm::State state
Definition fsm.h:211
std::map type using Config::Allocator::type.
Definition allocator.h:182
std::vector< T, typename Config::Allocator< T >::type > type
Definition allocator.h:174
#define zth_assert(expr)
assert(), but better integrated in Zth.
Definition util.h:212
#define likely(expr)
Marks the given expression to likely be evaluated to true.
Definition util.h:40