SkillAgentSearch skills...

Sml

C++14 State Machine library

Install / Use

/learn @boost-ext/Sml
About this skill

Quality Score

0/100

Category

Design

Supported Platforms

Universal

README

<a href="http://www.boost.org/LICENSE_1_0.txt" target="_blank">Boost Licence</a> <a href="https://github.com/boost-ext/sml/releases" target="_blank">Version</a> <a href="https://github.com/boost-ext/sml/actions/workflows/build_matrix.yml" target="_blank">Linux</a> <a href="https://codecov.io/gh/boost-ext/sml" target="_blank">Codecov</a> <a href="https://godbolt.org/z/y99L50">Try it online</a>


SML (State Machine Language)

Your scalable C++14 one header only State Machine Library with no dependencies

<p align="center"><a href="https://www.youtube.com/watch?v=Zb6xcd2as6o"><img src="doc/images/rise_of_the_state_machines.png" alt="Rise of the State Machines"/></a></p>

https://www.youtube.com/watch?v=Zb6xcd2as6o


<p align="center"> <br /> <b>Let's release a TCP connection!</b> <br /> </p> <p align="center"><img src="doc/images/tcp_release.png" alt="tcp release"/></p>

Quick start

Download

[Boost::ext].SML requires only one file. Get the latest header here!

Include

#include <boost/sml.hpp>
namespace sml = boost::sml;

Dependencies

struct sender {
  template<class TMsg>
  constexpr void send(const TMsg& msg) { std::printf("send: %d\n", msg.id); }
};

Events

struct ack { bool valid{}; };
struct fin { int id{}; bool valid{}; };
struct release {};
struct timeout {};

Guards

constexpr auto is_valid = [](const auto& event) { return event.valid; };

Actions

constexpr auto send_fin = [](sender& s) { s.send(fin{0}); };
constexpr auto send_ack = [](const auto& event, sender& s) { s.send(event); };

State Machine

struct tcp_release {
  auto operator()() const {
    using namespace sml;
    /**
     * Initial state: *initial_state
     * Transition DSL: src_state + event [ guard ] / action = dst_state
     */
    return make_transition_table(
      *"established"_s + event<release>          / send_fin  = "fin wait 1"_s,
       "fin wait 1"_s  + event<ack> [ is_valid ]             = "fin wait 2"_s,
       "fin wait 2"_s  + event<fin> [ is_valid ] / send_ack  = "timed wait"_s,
       "timed wait"_s  + event<timeout>                      = X
    );
  }
};

Usage

int main() {
  using namespace sml;

  sender s{};
  sm<tcp_release> sm{s}; // pass dependencies via ctor
  assert(sm.is("established"_s));

  sm.process_event(release{}); // complexity O(1)
  assert(sm.is("fin wait 1"_s));

  sm.process_event(ack{true}); // prints 'send: 0'
  assert(sm.is("fin wait 2"_s));

  sm.process_event(fin{42, true}); // prints 'send: 42'
  assert(sm.is("timed wait"_s));

  sm.process_event(timeout{});
  assert(sm.is(X));  // terminated
}

MSVC-2015 (Example)

  • use state<class state_name> instead of "state_name"_s
  • expliclty state a lambda's result type auto action = [] -> void {}

Compile

  • GCC/Clang
    $CXX -std=c++14 -O2 -fno-exceptions -Wall -Wextra -Werror -pedantic tcp_release.cpp
    
  • MSVC
    cl /std:c++14 /Ox /W3 tcp_release.cpp
    
<p align="center"> <table> <tr> <th>tcp_release.cpp</th> <th>Clang-3.8</th> <th>GCC-6.3</th> <th>MSVC-2015</th> </tr> <tr> <td>Compilation Time</td> <td>0.102s</td> <td>0.118s</td> <td>0.296s</td> </tr> <tr> <td>Binary size (stripped)</td> <td>6.2kb</td> <td>6.2kb</td> <td>105kb</td> </tr> <tr> <td>ASM x86-64 - <br/>https://godbolt.org/z/y99L50</td> <td colspan="3"> <pre><code> main: # @main pushq %rax movl $.L.str, %edi xorl %esi, %esi xorl %eax, %eax callq printf movl $.L.str, %edi movl $42, %esi xorl %eax, %eax callq printf xorl %eax, %eax popq %rcx retq .L.str: .asciz "send: %d\n" </code></pre> </td> </tr> </table> </p>

Run

Output (https://wandbox.org/permlink/WbvV9HsIyiPkCFw7)

send: 0
send: 42

Benchmark

Complex Test

| |Enum/Switch | Variant | [Boost::ext].SML - 1.1.0 | Boost-1.65.MSM-eUML | Boost-1.65.Statechart | |------------------|------------|---------|--------------|------------------|--------------------| | Compilation time | 0.132s | 15.321s | 0.582s | 1m15.935s | 5.671s | | Execution time | 679ms | 827ms | 622ms | 664ms | 2282ms | | Memory usage | 1b | 2b/8b | 1b | 120b | 224b | | Executable size | 15K | 187K | 34K | 611K | 211K |


Examples

<a name="arduino"></a>

<p align="center"><a href="http://www.plantuml.com/plantuml/uml/TP11Qy9048Nl-HNlPYnj4ZtcK4JheQtq4kX5HDRiRB9LTyFiXDH_twmM2WKl2n_xFjvZ5a4KIty-9PDaWfNlBcoRLf3MKyoBUO5tjW5lVR3gYFGOGGc-Rgozm95Ch-wB3SBsq0jfz4uJGrh2qliWgBoHGJ5XOsjoWHxnIHoiTvXbHJRAQKK4LTV-t2btiQw1iQSn_hfQVrJh_MnVPF8jy8nwd1Wdj29TcUV3C6I7s95vRl9_-JWCs3xiyFGCRqo2-5x10IMMuigoOmg1DBOtZ3yxvDYGZX0LXr__dcBCdn9h5kJqUD8V"><img src="doc/images/arduino/uml.png" alt="Arduino UML"/></a></p> <p align="center"><a href="https://godbolt.org/z/Y983h4"><img src="doc/images/arduino/code.png" alt="Arduino Code"/></a></p>

https://godbolt.org/z/Y983h4

<p align="center"><a href="https://www.tinkercad.com/things/9epUrFrzKP3"><img src="doc/images/arduino/board.png" alt="Arduino Board"/></a></p>

https://www.tinkercad.com/things/9epUrFrzKP3


<a name="avr"></a>

<p align="center"><a href="https://godbolt.org/z/qhx8Md"><img src="doc/images/avr.png" alt="AVR performance"/></a></p>

https://godbolt.org/z/qhx8Md


<a name="match3"></a>

<table> <tr> <td> <p align="center"><a href="https://www.youtube.com/watch?v=8gRHHIjx4oE"><img src="doc/images/match3.png" alt="match3"/></a></p> </td> <td> <p align="center"><a href="http://modern-cpp-examples.github.io/match3/"><img src="https://github.com/modern-cpp-examples/match3/raw/master/docs/images/match3.png" alt="match3"/></a></p> </td> </tr> </table>

https://github.com/modern-cpp-examples/match3


Documentation

View on GitHub
GitHub Stars1.3k
CategoryDesign
Updated14h ago
Forks202

Languages

C++

Security Score

100/100

Audited on Apr 2, 2026

No findings