Skip to content

Problems with reentering a terminated substate. #440

@lukashausperger

Description

@lukashausperger

Hey there!

We encountered the following issue:

Expected Behavior

Having a look at the following code snippet, we expect that the SubSubState is at Leave3 after trying to enter it for the second time.

Actual Behavior

When we try to reenter SubSubState in SubState for the second time (after leaving it), it stucks at the termination state X.

Steps to Reproduce the Problem

#include <boost/sml.hpp>
#include <cassert>
#include <deque>
#include <iostream>
#include <queue>

namespace sml = boost::sml;

namespace {
struct event_1 {};
struct event_2 {};
struct event_3 {};
struct event_4 {};

struct Leave1 {};
struct Leave2 {};
struct Leave3 {};

struct SubSubState {
  auto operator()() const noexcept {
    using namespace sml;
    return make_transition_table(*state<Leave3> + event<event_4> / process(event_3{}) = X);
  }
};

struct SubState {
  auto operator()() const noexcept {
    using namespace sml;
    return make_transition_table(*state<SubSubState> + event<event_3> / process(event_2{}) = X);
  }
};

struct StateMachine {
  auto operator()() const noexcept {
    using namespace sml;
    return make_transition_table(*state<Leave1> + event<event_1> = state<SubState>,
                                 state<SubState> + event<event_2> = state<Leave1>);
  }
};
}  // namespace

int main(int argv, char** argc) {
  sml::sm<StateMachine, sml::defer_queue<std::deque>, sml::process_queue<std::queue>> stm;
  using namespace sml;
  stm.process_event(event_1{});
  assert(stm.is<decltype(state<SubState>)>(state<SubSubState>));
  assert(stm.is<decltype(state<SubSubState>)>(state<Leave3>));
  stm.process_event(event_4{});
  stm.process_event(event_1{});
  assert(stm.is<decltype(state<SubState>)>(state<SubSubState>));
  assert(stm.is<decltype(state<SubSubState>)>(state<Leave3>));
}

This will output:

int main(int, char**): Assertion `stm.is<decltype(state<SubSubState>)>(state<Leave3>)' failed.

So the last assertion fails.

Specifications

Version: master
OS: Ubuntu 18.04
Compiler: gcc-10, g++-10

Acutally we found the following workaround which solves this issue:
When we change struct SubState{...} to

struct SubState {
  auto operator()() const noexcept {
    using namespace sml;
    return make_transition_table(*state<Leave2> + sml::on_entry<_> / process(event_5{}),
                                 state<Leave2> + event<event_5> = state<SubSubState>,
                                 state<SubSubState> + event<event_3> / process(event_2{}) = X);
  }
};

the last assertion does not fail anymore and SubSubState is a Leave_3 which is the desired behavior.

The question is why isn't it working without this workaround.

Thanks for your support.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions