fsm 0.4.1
Header-only C++20 hierarchical table-driven FSM
Loading...
Searching...
No Matches
fsm Namespace Reference

Classes

struct  any_t
 Tag type for fsm::any. More...
 
struct  event_tag
 Tag carrying an event as a compile-time value. More...
 
struct  from_spec
 Row source: a concrete state or the fsm::any wildcard. More...
 
struct  initial_spec
 Initial-child declaration for composite states. More...
 
struct  internal_t
 Tag type for fsm::internal. More...
 
class  machine
 The state machine engine interpreting a Traits' constexpr tables. More...
 
struct  no_timeout_t
 Tag type for fsm::no_timeout. More...
 
struct  observer
 Runtime-attachable debug observer: plain nullable function pointers. More...
 
struct  on_spec
 Row trigger event, with poison default for omitted .on. More...
 
struct  parent_spec
 Parent link — a mandatory column: fsm::root or fsm::child_of(P). More...
 
struct  result
 Dispatch verdict: what happened, where, and why. More...
 
struct  root_t
 Tag type for fsm::root. More...
 
struct  row
 One transition-table row: {from, on, when, then, to}. More...
 
struct  state_id
 State identifier for a state_spec, with poison default. More...
 
struct  state_spec
 One state's specification: hierarchy links, actions, deadline. More...
 
struct  target
 Row target: external transition, internal handling, or refusal. More...
 
struct  timeout_spec
 Per-state deadline declaration — a mandatory column. More...
 

Enumerations

enum class  status : uint8_t {
  transitioned , handled_internally , refused_by_row , refused_guard ,
  unhandled , refused_reentrant , not_started
}
 Verdict category returned by machine::dispatch(). More...
 
enum class  from_kind : uint8_t { unspecified , any , state }
 Kinds for row::from. unspecified is the poison default. More...
 
enum class  on_kind : uint8_t { unspecified , event }
 Kinds for row::on. unspecified is the poison default. More...
 
enum class  target_kind : uint8_t { unspecified , to , internal_ , refuse_ }
 Kinds for row::to. unspecified is the poison default. More...
 
enum class  id_kind : uint8_t { unspecified , state }
 Kinds for state_spec::state. unspecified is the poison default. More...
 
enum class  parent_kind : uint8_t { unspecified , root , child }
 Kinds for state_spec::parent. unspecified is the poison default. More...
 
enum class  initial_kind : uint8_t { leaf , start_at }
 Kinds for state_spec::initial. Default is leaf (no children). More...
 
enum class  timeout_kind : uint8_t { unspecified , none , after_ , after_dyn_ }
 Kinds for state_spec::deadline. unspecified is the poison default. More...
 

Functions

template<class Traits , class W >
void write_dot (W &&write)
 Emit a Graphviz digraph of Traits' machine through write.
 
template<class State , class Event , class Reason >
constexpr bool accepted (const result< State, Event, Reason > &r)
 True when the event was acted on (transitioned or handled internally).
 
template<class State >
constexpr detail::to_t< State > to (State s)
 Make an external-transition target.
 
template<class Reason >
constexpr detail::refuse_t< Reason > refuse (Reason r)
 Make a declarative refusal target carrying a reason.
 
template<class State >
constexpr parent_spec< State > child_of (State s)
 Declare a state's parent in the hierarchy.
 
template<class State >
constexpr initial_spec< State > start_at (State s)
 Declare the child entered when a composite state is targeted.
 
template<class Event >
constexpr timeout_spec< Event > after (uint32_t ms, Event e)
 Declare "dispatch @p e after @p ms milliseconds in this state".
 
template<class Event >
constexpr timeout_spec< Event > after_dyn (Event e)
 Declare a dynamic deadline: duration read from the context at entry time instead of the table.
 

Variables

constexpr uint16_t no_row = 0xFFFF
 Sentinel row index meaning "no table row was involved".
 
constexpr any_t any {}
 Wildcard row source: matches any state, after all ancestor levels.
 
constexpr internal_t internal {}
 Row target: handle the event (run the action) without exit/entry.
 
constexpr no_timeout_t no_timeout {}
 State deadline declaration: this state has no timeout (explicitly).
 
constexpr root_t root {}
 Parent declaration: this state is a hierarchy root (no parent).
 

Enumeration Type Documentation

◆ from_kind

enum class fsm::from_kind : uint8_t
strong

Kinds for row::from. unspecified is the poison default.

Enumerator
unspecified 
any 
state 

◆ id_kind

enum class fsm::id_kind : uint8_t
strong

Kinds for state_spec::state. unspecified is the poison default.

Enumerator
unspecified 
state 

◆ initial_kind

enum class fsm::initial_kind : uint8_t
strong

Kinds for state_spec::initial. Default is leaf (no children).

Enumerator
leaf 
start_at 

◆ on_kind

enum class fsm::on_kind : uint8_t
strong

Kinds for row::on. unspecified is the poison default.

Enumerator
unspecified 
event 

◆ parent_kind

enum class fsm::parent_kind : uint8_t
strong

Kinds for state_spec::parent. unspecified is the poison default.

Enumerator
unspecified 
root 
child 

◆ status

enum class fsm::status : uint8_t
strong

Verdict category returned by machine::dispatch().

Refusal is the default: an event no table row matches yields status::unhandled rather than being silently dropped or deferred.

Enumerator
transitioned 

A row matched and an external transition completed.

handled_internally 

A row matched with target fsm::internal; no state change.

refused_by_row 

An explicit fsm::refuse row matched; result carries its reason.

refused_guard 

Row(s) matched (from, event) but every guard declined.

unhandled 

No row considered this (state, event) pair at all.

refused_reentrant 

dispatch() called from inside a guard/action; not allowed.

not_started 

dispatch() before machine::start().

◆ target_kind

enum class fsm::target_kind : uint8_t
strong

Kinds for row::to. unspecified is the poison default.

Enumerator
unspecified 
to 
internal_ 
refuse_ 

◆ timeout_kind

enum class fsm::timeout_kind : uint8_t
strong

Kinds for state_spec::deadline. unspecified is the poison default.

Enumerator
unspecified 
none 
after_ 
after_dyn_ 

Function Documentation

◆ accepted()

template<class State , class Event , class Reason >
constexpr bool fsm::accepted ( const result< State, Event, Reason > &  r)
constexpr

True when the event was acted on (transitioned or handled internally).

◆ after()

template<class Event >
constexpr timeout_spec< Event > fsm::after ( uint32_t  ms,
Event  e 
)
constexpr

Declare "dispatch @p e after @p ms milliseconds in this state".

The deadline is stamped on state entry, disarmed on exit, and fired by machine::service() through the normal transition table — a timeout is just an event with the plumbing supplied.

◆ after_dyn()

template<class Event >
constexpr timeout_spec< Event > fsm::after_dyn ( Event  e)
constexpr

Declare a dynamic deadline: duration read from the context at entry time instead of the table.

The traits must provide static uint32_t deadline_ms(State, const Context&) (compile error otherwise); it is consulted at every entry — including external self-transition re-entry — under the same reentrancy rules as entry hooks (pure read of the context; dispatch from it is refused). A returned 0 means "due now": the deadline arms at now and fires on the next service() call. Returns above half the Time range are clamped there (and assert in debug builds via FSM_DEADLINE_ASSERT). The fired event runs the normal table with a value-initialized Payload, exactly like fsm::after.

{.state = St::Pulsing, .parent = fsm::child_of(St::Seq),
.deadline = fsm::after_dyn(Ev::PulseDone)}, // width from the profile
// in traits:
static uint32_t deadline_ms(St s, const Ctx& c) {
return s == St::Pulsing ? c.profile.pulse_ms : 0;
}
constexpr parent_spec< State > child_of(State s)
Declare a state's parent in the hierarchy.
Definition fsm.hpp:317
constexpr timeout_spec< Event > after_dyn(Event e)
Declare a dynamic deadline: duration read from the context at entry time instead of the table.
Definition fsm.hpp:398

◆ child_of()

template<class State >
constexpr parent_spec< State > fsm::child_of ( State  s)
constexpr

Declare a state's parent in the hierarchy.

◆ refuse()

template<class Reason >
constexpr detail::refuse_t< Reason > fsm::refuse ( Reason  r)
constexpr

Make a declarative refusal target carrying a reason.

Combine with guarded rows above it for the "guard chain with reasoned fallback" pattern: the first passing row wins; the trailing refuse row turns "all guards declined" into a reasoned verdict.

◆ start_at()

template<class State >
constexpr initial_spec< State > fsm::start_at ( State  s)
constexpr

Declare the child entered when a composite state is targeted.

Required on every composite (a state that is some state's parent), forbidden on leaves — both validated at compile time.

◆ to()

template<class State >
constexpr detail::to_t< State > fsm::to ( State  s)
constexpr

Make an external-transition target.

{.from = St::Arming, .on = Ev::Confirm, .to = fsm::to(St::Live)}

◆ write_dot()

template<class Traits , class W >
void fsm::write_dot ( W &&  write)

Emit a Graphviz digraph of Traits' machine through write.

Composite states become clusters, transition rows become edges labelled event [guard] /action, per-state timeouts become dashed self-annotations (after N ms: event), refuse rows point at an octagon refused sink, and fsm::any rows originate from a point node. Edges touching a composite anchor at its initial-descent leaf and clip at the cluster border via ltail/lhead. write is called once per line with a NUL-terminated string (no trailing newline); no allocation.

State/event names are emitted verbatim as Graphviz identifiers: keep them to [A-Za-z0-9_] (the default s<N>/e<N> fallback always is), avoid the reserved node names any and refused and dot keywords (node, edge, graph), and keep them short — each output line shares one fixed 224-byte buffer, and a truncated edge line is invalid dot.

Variable Documentation

◆ any

constexpr any_t fsm::any {}
inlineconstexpr

Wildcard row source: matches any state, after all ancestor levels.

◆ internal

constexpr internal_t fsm::internal {}
inlineconstexpr

Row target: handle the event (run the action) without exit/entry.

◆ no_row

constexpr uint16_t fsm::no_row = 0xFFFF
inlineconstexpr

Sentinel row index meaning "no table row was involved".

◆ no_timeout

constexpr no_timeout_t fsm::no_timeout {}
inlineconstexpr

State deadline declaration: this state has no timeout (explicitly).

◆ root

constexpr root_t fsm::root {}
inlineconstexpr

Parent declaration: this state is a hierarchy root (no parent).