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