xtc_fsm(3)

---

xtc_fsm(3)

gen_statem-style finite state machine as a process

XTC_FSM(3) Library Functions Manual XTC_FSM(3)

xtc_fsm_start, xtc_fsm_stop, xtc_fsm_join, xtc_fsm_pid, xtc_fsm_send, xtc_fsm_call, xtc_fsm_replygen_statem-style finite state machine as a process

#include <xtc.h>
#include <xtc_fsm.h>

int
xtc_fsm_start(xtc_loop_t *loop, const xtc_fsm_callbacks_t *cb, void *state, int initial_state, const xtc_fsm_opts_t *opts, xtc_fsm_t **out);

int
xtc_fsm_stop(xtc_fsm_t *fsm);

int
xtc_fsm_join(xtc_fsm_t *fsm, int64_t timeout_ns);

xtc_pid_t
xtc_fsm_pid(const xtc_fsm_t *fsm);

int
xtc_fsm_send(xtc_pid_t target, const void *ev, size_t len);

int
xtc_fsm_call(xtc_pid_t target, const void *req, size_t req_size, void **out_reply, size_t *out_size, int64_t timeout_ns);

int
xtc_fsm_reply(xtc_fsm_call_t *call, const void *reply, size_t size);

The xtc_fsm family is a gen_statem(3)-style finite state machine that runs as its own xtc_proc(3): a disciplined loop over () that dispatches each event to the caller's () callback for the current state and acts on the returned xtc_fsm_result_t. It standardizes the three features hand-rolled C switch machines almost always get wrong:

  • : the enter() callback runs on every state change, so entry actions live in one place.
  • : an event returned as XTC_FSM_POSTPONE is stashed and REPLAYED, oldest first, after the next XTC_FSM_NEXT transition, ahead of fresh events.
  • : a result with state_timeout_ns > 0 arms a timeout for the resulting state; if it fires first a synthetic state-timeout event is delivered to event() with msg == NULL and len == 0 (XTC_FSM_IS_STATE_TIMEOUT). Any real event cancels a pending state timeout.

() spawns the machine on loop in initial_state (() is called for it first) and returns a handle in out. () asks the machine to stop (non-blocking; runs (), then the proc exits); () waits for exit and frees the handle. () returns the machine's pid.

() delivers an asynchronous, fire-and-forget event (arrives with call == NULL). () delivers a synchronous request and blocks until the machine replies or timeout_ns elapses; on success out_reply receives a heap buffer the caller releases with xtc_free(3). Inside event(), when call is non-NULL the callback answers it exactly once with ().

All functions returning int return XTC_OK on success or a negative XTC_E_* code; xtc_fsm_call() returns XTC_E_AGAIN on timeout and must be called from within a process. xtc_fsm_join() returns XTC_E_AGAIN on timeout, leaving the handle valid to join again. xtc_fsm_pid() returns the machine's pid, or XTC_PID_NONE for a NULL handle.

xtc_svr(3), xtc_proc(3), xtc_supervisor(3), xtc(7)

Appeared in xtc 1.10.

July 9, 2026 Debian

View the mdoc source