A real GenStateMachine implementing a Petri-net-style token game for a
POWL process model.
The machine's state is a marking: a map of place -> non_neg_integer
token counts. The single state-machine state is :marking (this executor
is deliberately single-mode — the "state" that matters is the data, not the
state-function name), and the machine data carries both the current marking
and the transition graph it was started with.
A transition is identified by any term (usually an atom or string) and is
described by its input places (consumed on fire) and output places
(produced on fire). Firing a transition whose input places do not all hold
at least one token is refused: the marking is left unchanged and the caller
receives {:error, :insufficient_tokens}.
This module is intentionally self-contained: it has no dependency on BRCE
or receipts. Wiring a receipted :fire call is a later capability's job.
Summary
Functions
Returns a specification to start this module under a supervisor.
Attempt to fire transition_id. Returns {:ok, marking} with the new
marking on success, or {:error, :insufficient_tokens} /
{:error, :unknown_transition} on refusal, in which case the marking is
left unchanged.
Return the current marking.
Start the executor.
Types
@type marking() :: %{optional(place()) => non_neg_integer()}
@type place() :: term()
@type transition_id() :: term()
@type transitions() :: %{optional(transition_id()) => transition()}
Functions
Returns a specification to start this module under a supervisor.
See Supervisor.
@spec fire(GenServer.server(), transition_id()) :: {:ok, marking()} | {:error, :insufficient_tokens | :unknown_transition}
Attempt to fire transition_id. Returns {:ok, marking} with the new
marking on success, or {:error, :insufficient_tokens} /
{:error, :unknown_transition} on refusal, in which case the marking is
left unchanged.
@spec marking(GenServer.server()) :: marking()
Return the current marking.
@spec start_link(marking(), transitions(), GenServer.options()) :: GenServer.on_start()
Start the executor.
initial_marking is a map of place => token count. transitions is a map
of transition_id => %{inputs: [place], outputs: [place]}.