Skip to content

jfayot/dynamic-state-machine

Repository files navigation

Dynamic StateMachine

A Dynamic StateMachine where states and transitions are created runtime.

GitHub version Project Status: Active – The project has reached a stable, usable state and is being actively developed. License: MIT

Windows Build Status Linux Build Status MacOS Build Status

Tests Status codecov CodeQL Coverity scan Codacy Badge Language grade: C/C++ Total alerts

Features

  • Flat-style and enclosed-style setup
  • Unlimited number of states and transitions
  • Hierarchical states
  • Entry and exit actions
  • Internal and external transitions
  • Transition actions
  • Transition guard conditions
  • State history (deep and shallow)
  • Event processing
  • Event deferring
  • Event posting
  • Orthogonal regions
  • Optional shared storage
  • Visitable
  • Observable (check current active states)
  • Exception handling
  • Platform independent, C++17
  • Header only
  • No external dependencies except STL
  • Moderate use of templates

Minimal examples

Considering the following minimal state machine, it can be coded as follows: minimal

Flat-style StateMachine setup

#include "dsm/dsm.hpp"
#include <cassert>

using namespace dsm;

struct e1 : Event<e1> {};

struct minimal : StateMachine<minimal> {};
struct s0 : State<s0, minimal> {};
struct s1 : State<s1, minimal> {};

int main()
{
    minimal sm;

    sm.addState<s0, Entry>();
    sm.addState<s1>();
    sm.addTransition<s0, e1, s1>();

    sm.start();
    assert(sm.checkStates<s0>());
    std::cout << sm << std::endl;
    sm.processEvent(e1{});
    assert(sm.checkStates<s1>());
    std::cout << sm << std::endl;
}

Enclosed-style StateMachine setup

#include "dsm/dsm.hpp"
#include <cassert>

using namespace dsm;

struct minimal;
struct e1 : Event<e1> {};
struct s1 : State<s1, minimal> {};
struct s0 : State<s0, minimal> {
    TTransitions getTransitions() override {
        return { createTransition<e1, s1>() };
    }
};
struct minimal : StateMachine<minimal> {
    TStates getStates() override {
        return { createState<s0, Entry>(), createState<s1>() };
    }
};

int main()
{
    minimal sm;

    sm.setup();

    sm.start();
    assert(sm.checkStates<s0>());
    std::cout << sm << std::endl;
    sm.processEvent(e1{});
    assert(sm.checkStates<s1>());
    std::cout << sm << std::endl;
}