Skip to content

boost-ext/sml

master
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Code

Files

Permalink
Failed to load latest commit information.
Type
Name
Latest commit message
Commit time
 
 
 
 
doc
 
 
 
 
sml
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

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.