Skip to content

boost-ext/sml

Repository files navigation

Boost Licence Version Linux Codecov Try it online


SML (State Machine Language)

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

Rise of the State Machines

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



Let's release a TCP connection!

tcp release

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

tcp_release.cpp Clang-3.8 GCC-6.3 MSVC-2015
Compilation Time 0.102s 0.118s 0.296s
Binary size (stripped) 6.2kb 6.2kb 105kb
ASM x86-64 -
https://godbolt.org/z/y99L50
 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" 

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

Arduino UML

Arduino Code

https://godbolt.org/z/Y983h4

Arduino Board

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


AVR performance

https://godbolt.org/z/qhx8Md


match3

match3

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


Documentation


Disclaimer [Boost::ext].SML is not an official Boost library.