Skip to content

Anonymous transitions are not triggered within sub state machines #653

@Dartgroow

Description

@Dartgroow

Hello,

I faced the issue that anonymous transition does not happen in substate machines upon entering them.
Here is the code example:

#include "sml.hpp"

namespace sml = boost::sml;

namespace {


struct e1 {};
struct e2 {};

struct guard {
    bool operator()() const { return false; }
} guard;


struct SubSubDoneOK{};

  struct subsub {
  auto operator()() const noexcept {
    using namespace sml;
    return make_transition_table(
      *"idle"_s / [] { std::cout << "in subsub sm" << std::endl; } = "s1"_s
      // ,"idle"_s + boost::sml::on_entry<_> / [] { std::cout << "entered subsub" << std::endl; }
      , "s1"_s [ guard ] / [] { std::cout << "Won't be called" << std::endl; } = X
      , "s1"_s / [] { std::cout << "finish sub sub" << std::endl; } = X
      );
  }
  };

  struct SubDoneOK{};
  struct sub {
    struct DoneOK{};
    auto operator()() const noexcept {
      using namespace sml;
      return make_transition_table(
        *"idle"_s / [] { std::cout << "in sub sm" << std::endl; } = "s1"_s
        // ,"idle"_s + boost::sml::on_entry<_> / [] { std::cout << "entered sub" << std::endl; }
        , "s1"_s [ guard ] / [] { std::cout << "Won't be called" << std::endl; } = X
        , "s1"_s / [] { std::cout << "entering s2" << std::endl; } = "s2"_s
        , "s2"_s / [] { std::cout << "enter subsub sm" << std::endl; } = state<subsub>
        , state<subsub> + event<SubSubDoneOK> / [] { std::cout << "exit sub sm" << std::endl; }  = X
      );
  }
};

struct composite {
  auto operator()() const noexcept {
    using namespace sml;
    return make_transition_table(
     *"idle"_s + event<e1> = "s1"_s
     , "s1"_s + event<e2> / [] { std::cout << "entering sub sm" << std::endl; } = state<sub>
     , state<sub> + event<SubDoneOK> / [] { std::cout << "exit main sm" << std::endl; }  = X
    );
  }
};
}  // namespace

int main() {
  sml::sm<composite> sm;

  using namespace sml;

  sm.process_event(e1{});
  sm.process_event(e2{});  // enter sub sm

  if (sm.is<decltype(state<subsub>)>(X)) {
    sm.process_event(SubSubDoneOK{});  // enter sub sm
  }

  if (sm.is<decltype(state<sub>)>(X)) {
    sm.process_event(SubDoneOK{});  // enter sub sm
  }
}

The expected output is something like this:

g++ test.cpp -g -o test && ./test
entering sub sm
in sub sm
entering s2
enter subsub sm
in subsub sm
finish sub sub
exit sub sm
exit main sm

However, the actual output is the following:

g++ test.cpp -g -o test && ./test
entering sub sm

The only working "workaround" is to uncomment the following lines:

      // ,"idle"_s + boost::sml::on_entry<_> / [] { std::cout << "entered subsub" << std::endl; }
      // ,"idle"_s + boost::sml::on_entry<_> / [] { std::cout << "entered sub" << std::endl; }

With these lines uncommented, the output is as expected.

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