boost-ext / sml

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

issue with double deferring #416

Open FE-EnricoSartori opened 3 years ago

FE-EnricoSartori commented 3 years ago

In the following example, a state machine containing 3 initial states is proposed. All these states should transit to the exit state when the event e1 is received. In order to propagate such event to all the initial states, it is deferred two times. The expectation is not satisfied since only the first defer works properly.

Example:

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

namespace sml = boost::sml;

namespace {

struct e1 {};

struct defer_and_process {
  auto operator()() const noexcept {
    using namespace sml;
    return make_transition_table(
       *"s1"_s  + event<e1> / defer = X
      ,*"s2"_s  + event<e1> / defer = X
      ,*"s3"_s  + event<e1> = X
    );
  }
};
}  // namespace

int main() {

  using namespace sml;
  sm<defer_and_process, sml::defer_queue<std::deque>, sml::process_queue<std::queue>> sm;

  assert(sm.is("s1"_s, "s2"_s, "s3"_s));

  sm.process_event(e1{});

  std::cout << sm.is(X,X,"s3"_s) << std::endl;  // TRUE - Expected to be FALSE
  std::cout << sm.is(X,X,X) << std::endl;       // FALSE - Expected to be TRUE
}

Is this the correct behavior? How can I implement the expected behavior?

kris-jusiak commented 3 years ago

Agree, s3 should transition to X in this case :thinking: Seems like an issue :bug: I'll take a look, thanks for reporting it @FE-EnricoSartori :+1:

Maverobot commented 3 years ago

For some reason, I cannot reproduce it. sm.is(X,X,X) is always true no matter how many defers are used, which is also a strange behavior..

kris-jusiak commented 3 years ago

Hmm, master seems to yield the correct result :thinking:

Maverobot commented 3 years ago

The program ends with (X,X,X) even if no defer is used.

Is this the expected behavior?

GuiCodron commented 3 years ago

Orthogonal regions all process the event. There is no need to add defer to allow all state machine to transition to X.

Defer is used to allow the next state to handle the event, in your case it would allow X to use the event (which has no sense).

Le mer. 18 nov. 2020 à 01:24, Zheng Qu notifications@github.com a écrit :

The program ends with (X,X,X) even if no defer is used.

Is this the expected behavior?

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/boost-ext/sml/issues/416#issuecomment-729295540, or unsubscribe https://github.com/notifications/unsubscribe-auth/AC3DS4JLOXRMGM7WXG2F5ZTSQMH3DANCNFSM4TYMWW6A .

Maverobot commented 3 years ago

@GuiCodron Thanks for the explanation. Just out of curiosity, is there a way to only allow the "first" (or a certain) state in the orthogonal region to handle the event?

GuiCodron commented 3 years ago

I don't know of a built-in way to do it, I think it goes a bit against how orthogonal regions are meant to be used.

My guess would be to use different events if you want each region to behave differently. If this event is not meant to be caught by a region if another region handles it, it might mean that using orthogonal regions is not the right solution for your problem but you need distinct states (not orthogonal).

If you can share a representation of your state machine and how you would like to use this event disabling feature, we could try to help you.

Le mer. 18 nov. 2020 à 09:54, Zheng Qu notifications@github.com a écrit :

@GuiCodron https://github.com/GuiCodron Thanks for the explanation. Just out of curiosity, is there a way to only allow the "first" (or a certain) state in the orthogonal region to handle the event?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/boost-ext/sml/issues/416#issuecomment-729533418, or unsubscribe https://github.com/notifications/unsubscribe-auth/AC3DS4KRN6AIPBPWAMUNYVDSQODUDANCNFSM4TYMWW6A .