Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Self-loops

A direct self-loop transitions from a state back to itself, such as running → running. A state can also be part of an indirect cycle, such as running → paused → running. Both forms allow states on the cycle to be entered repeatedly, so their generated events have multi cardinality.

YAML model

quent: alpha
model: fsm_self_loop

fsms:
  Task:
    states:
      running:
        initial: true
        attributes:
          items_processed: u64
        to: [running, paused, completed]
      paused:
        to: [running]
      completed: {}

Instrumentation API

The task first repeats running through its direct self-loop. It then follows the indirect cycle through paused and back to running before entering completed once.

use instrumentation::{Context, FsmSelfLoop, Noop, Task};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let context = Context::<FsmSelfLoop>::try_new(Noop)?;
    let task = context.observer::<Task>().handle().running(0);

    // Direct self-loop: running -> running.
    let task = task.running(64);
    // Indirect cycle: running -> paused -> running.
    let task = task.paused().running(128);
    let _task = task.completed();

    Ok(())
}
#include "quent-tutorial-fsm-self-loop-cpp-bridge/gen/quent.hpp"

int main() {
  auto context = quent::Context::none();
  auto task = context.task_observer()->handle().running(
      quent::task::Running{.items_processed = 0});
  task = std::move(task).running(
      quent::task::Running{.items_processed = 64});
  auto paused = std::move(task).paused();
  task = std::move(paused).running(
      quent::task::Running{.items_processed = 128});
  auto completed = std::move(task).completed();
  return 0;
}
import quent_tutorial_fsm_self_loop as quent


def main() -> None:
    with quent.Context() as context:
        task = context.task_observer().handle()
        running = task.running(items_processed=0)
        running = running.running(items_processed=64)
        paused = running.paused()
        running = paused.running(items_processed=128)
        completed = running.completed()


if __name__ == "__main__":
    main()
Key point

Every state on a direct or indirect cycle has a repeatable state-entry event.

Check yourself

Which transition is a direct self-loop?

Why does paused have multi cardinality?

Full code