Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to achieve shallow history behavior? #588

Open
aplotskin opened this issue Aug 11, 2023 · 1 comment
Open

How to achieve shallow history behavior? #588

aplotskin opened this issue Aug 11, 2023 · 1 comment

Comments

@aplotskin
Copy link

Expected Behavior

The docs show support for UML Shallow History as (✓) and UML Deep history as (~) [not sure what ~ is intended to indicate vs -].

Actual Behavior

Implementation with the (H) init tag on a state behaves like deep history, not shallow. Is there a way to induce shallow history behavior?

Steps to Reproduce the Problem

I have expanded the history example below:

//
// Copyright (c) 2016-2020 Kris Jusiak (kris at jusiak dot net)
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include <boost/sml.hpp>
#include <cassert>
#include <iostream>

namespace sml = boost::sml;

namespace {

// subsub does not have a history init, just a normal default init
struct subsub {
  auto operator()() const noexcept {
    using namespace sml;
    // clang-format off
    return make_transition_table(

      "s1"_s <= *"idle"_s + "e1"_e / [] { std::cout << "subsub:e1" << std::endl; },

    // verbose entries/exits
      "idle"_s + on_entry<_>     / []{std::cout << "entering subsub/idle" << std::endl;},
      "idle"_s + sml::on_exit<_> / []{std::cout << "exiting subsub/idle" << std::endl;},
      "s1"_s + on_entry<_>       / []{std::cout << "entering subsub/s1" << std::endl;},
      "s1"_s + sml::on_exit<_>   / []{std::cout << "exiting subsub/s1" << std::endl;}

    );
    // clang-format on
  }
};

struct sub {
  auto operator()() const noexcept {
    using namespace sml;
    // clang-format off
    return make_transition_table(

      "s1"_s        <= "idle"_s(H) + "e1"_e  / [] { std::cout << "sub:e1" << std::endl; },
      state<subsub> <= "s1"_s      + "e2"_e  / [] { std::cout << "sub:e2" << std::endl; },

    // verbose entries/exits
      "idle"_s + on_entry<_>          / []{std::cout << "entering sub/idle" << std::endl;},
      "idle"_s + sml::on_exit<_>      / []{std::cout << "exiting sub/idle" << std::endl;},
      "s1"_s + on_entry<_>            / []{std::cout << "entering sub/s1" << std::endl;},
      "s1"_s + sml::on_exit<_>        / []{std::cout << "exiting sub/s1" << std::endl;},  
      state<subsub> + on_entry<_>     / []{std::cout << "entering sub/subsub" << std::endl;},
      state<subsub> + sml::on_exit<_> / []{std::cout << "exiting sub/subsub" << std::endl;}
    );
    // clang-format on
  }
};

struct history {
  auto operator()() const noexcept {
    using namespace sml;
    // clang-format off
    return make_transition_table(
      state<sub> <= *"idle"_s  + "e1"_e / [] { std::cout << "history:e1" << std::endl; }
    , "s1"_s     <= state<sub> + "e3"_e / [] { std::cout << "history:e3" << std::endl; }
    , state<sub> <= "s1"_s     + "e4"_e / [] { std::cout << "history:e4 enter sub again" << std::endl; },

    // verbose entries/exits
    "idle"_s + on_entry<_>       / []{ std::cout << "history: entering idle>" << std::endl;},
    "idle"_s + sml::on_exit<_>   / []{ std::cout << "history: exiting idle" << std::endl;},
    "s1"_s + on_entry<_>         / []{ std::cout << "history: entering s1>" << std::endl;},
    "s1"_s + sml::on_exit<_>     / []{ std::cout << "history: exiting s1" << std::endl;},
    state<sub> + on_entry<_>     / []{ std::cout << "history: entering state<sub>" << std::endl;},
    state<sub> + sml::on_exit<_> / []{ std::cout << "history: exiting state<sub>" << std::endl;}
    );
    // clang-format on
  }
};
}  // namespace

int main() {
  sml::sm<history> sm;
  using namespace sml;
  std::cout << std::endl << ">>>>>>  " << "e1 processing" << std::endl; 
  sm.process_event("e1"_e());  // enter sub

  std::cout << std::endl << ">>>>>>  " << "e1 processing again" << std::endl; 
  sm.process_event("e1"_e());  // in sub

  std::cout << std::endl << ">>>>>>  " << "e3 processing" << std::endl;
  sm.process_event("e3"_e());  // exit sub

  std::cout << std::endl << ">>>>>>  " << "e4 processing" << std::endl;
  sm.process_event("e4"_e());  // enter sub again

  std::cout << std::endl << ">>>>>>  " << "e2 processing (activate subsub)" << std::endl;
  sm.process_event("e2"_e());  // in sub again now with subsub

  std::cout << std::endl << ">>>>>>  " << "e1 processing again (progress subsub from default)" << std::endl; 
  sm.process_event("e1"_e());  // move subsub

  std::cout << std::endl << ">>>>>>  " << "e3 processing" << std::endl;
  sm.process_event("e3"_e());  // exit sub

  std::cout << std::endl << ">>>>>>  " << "e4 processing (shallow history should now have subsub in idle)" << std::endl;
  sm.process_event("e4"_e());  // enter sub again

}

Output:

history: entering idle>

>>>>>>  e1 processing
history: exiting idle
history:e1
history: entering state<sub>
entering sub/idle

>>>>>>  e1 processing again
exiting sub/idle
sub:e1
entering sub/s1

>>>>>>  e3 processing
exiting sub/s1
history: exiting state<sub>
history:e3
history: entering s1>

>>>>>>  e4 processing
history: exiting s1
history:e4 enter sub again
history: entering state<sub>
entering sub/s1

>>>>>>  e2 processing (activate subsub)
exiting sub/s1
sub:e2
entering sub/subsub
entering subsub/idle

>>>>>>  e1 processing again (progress subsub from default)
exiting subsub/idle
subsub:e1
entering subsub/s1

>>>>>>  e3 processing
exiting subsub/s1
exiting sub/subsub
history: exiting state<sub>
history:e3
history: entering s1>

>>>>>>  e4 processing (shallow history should see subsub in idle)
history: exiting s1
history:e4 enter sub again
history: entering state<sub>
entering sub/subsub
entering subsub/s1
@Alex0vSky
Copy link

I think ~ means approximately.

(1) In mathematics, the tilde (~) stands for equivalence; for example, a ~ b means "a is equivalent to b" (not equal, but comparable). It also stands for approximation. Officially written as two tildes, one over the other, the single tilde has become acceptable; for example, ~100 means "approximately 100."

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants