boost-ext / sml

C++14 State Machine library
https://boost-ext.github.io/sml
Boost Software License 1.0
1.16k stars 179 forks source link

Best way to implement a counter behavior in SML? #434

Open smccauliff opened 3 years ago

smccauliff commented 3 years ago

I have functionality I would like to represent with a state machine in SML.

struct MessageFlusher {
  uint32_t message_count{0};
  void addMessage() {
     message_count++;
     if (message_count == kThreshold) {
        flushMessages(message_count);
        message_count = 0;
     }
  }
}

What's the best way to represent states that take some action when a count reaches some value in SML? If this was a pure state machine then the states would be like count_0, count_1, count_2, ... but that seems wasteful for small counts and not possible for large ones.

smccauliff commented 3 years ago

Also is this the right place to ask questions?

uyha commented 3 years ago
#include <cassert>
#include <sml/sml.hpp>

struct Process {};

struct StateMachine {
  struct s1 {};
  auto operator()() const noexcept {
    using namespace boost::sml;
    auto const guard           = [](int const &message_count) { return message_count == 10; };
    auto const increment_count = [](int &message_count) { ++message_count; };
    auto const flush_action    = [](int &message_count) { /*do something with message_count*/
                                                       message_count = 0;
    };
    return make_transition_table(*state<s1> + event<Process>[guard] / flush_action,
                                 state<s1> + event<Process> / increment_count);
  }
};

int main() {
  int message_count = 0;
  boost::sml::sm<StateMachine> state_machine{message_count};
  for (auto i = 0; i < 10; ++i) {
    assert(message_count == i);
    state_machine.process_event(Process{});
  }
  assert(message_count == 10);
  state_machine.process_event(Process{});
  assert(message_count == 0);
}
uyha commented 3 years ago

Please ask if you have any questions