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

deferred event not processed when in any orthogonal region other than first #611

Open
TPHandford opened this issue Feb 15, 2024 · 0 comments

Comments

@TPHandford
Copy link

Expected Behavior

Deferred events should be reprocessed when transitioning into a new state

Actual Behavior

If the state is not in the first orthogonal region of the state machine, the deferred event is not processed

Steps to Reproduce the Problem

  1. See following code https://godbolt.org/z/r6zYxWKGM
  2. The code contains two state machines which use deferred tasks and orthogonal regions. The two state machines are identical except for the order in which the orthogonal regions are defined. Deferred tasks only work in the version that contains them in the first orthogonal region.

Specifications

  • Version: 1.1.9
  • Platform: Any

Code

For reference, here is the code that reproduces the problem (in the compiler explorer):

  #include <cstdio>
  #include <cassert>
  #include <deque>
  #include <https://raw.githubusercontent.com/boost-experimental/sml/master/include/boost/sml.hpp>

namespace sml = boost::sml;

struct sm_logger
{
    template <class SM, class TEvent>
    void log_process_event(const TEvent&)
    {
        printf("[%s][process_event] %s\n", sml::aux::get_type_name<SM>(), sml::aux::get_type_name<TEvent>());
    }

    template <class SM, class TSrcState, class TDstState>
    void log_state_change(const TSrcState& src, const TDstState& dst)
    {
        printf("[%s][transition] %s -> %s\n", sml::aux::get_type_name<SM>(), src.c_str(), dst.c_str());
    }
};

struct e1 {};
struct e2 {};
struct e3 {};

struct dummy1 {};
struct dummy2 {};
struct defer_chain_first_region
{
    auto operator()() const noexcept
    {
        using namespace sml;
        return make_transition_table(
            * "s0"_s + event<e1> / defer
            ,"s0"_s + event<e2>  = "s1"_s
            ,"s1"_s + event<e1> = "s0"_s
            ,* "dummy1"_s + event<dummy1> = X
            ,* "dummy2"_s + event<dummy2> = X
        );
    }
};

// identical to previous state machine except that first and second regions swapped
struct defer_chain_second_region
{
    auto operator()() const noexcept
    {
        using namespace sml;
        return make_transition_table(
            * "dummy1"_s + event<dummy1> = X
            ,* "s0"_s + event<e1> / defer
            ,"s0"_s + event<e2>  = "s1"_s
            ,"s1"_s + event<e1> = "s0"_s
            ,* "dummy2"_s + event<dummy2> = X
        );
    }
};


int main()
{
    using namespace sml;

    printf("Test defer in first region\n");
    sm_logger logger;
    sml::sm<defer_chain_first_region, sml::defer_queue<std::deque>
                       , sml::logger<sm_logger>
                       > sm_first{logger};

    sm_first.process_event(e1{});
    sm_first.process_event(e2{});
    sm_first.process_event(e3{});

    assert(sm_first.is("s0"_s));
    if (!sm_first.is("s0"_s))
    {
        printf("*** defer not processed correctly - final state transition missing! ***\n");
    }
    

    printf("\nTest defer in second region\n");

    sml::sm<defer_chain_second_region, sml::defer_queue<std::deque>
                       , sml::logger<sm_logger>
                       > sm_second{logger};

    sm_second.process_event(e1{});
    sm_second.process_event(e2{});
    sm_second.process_event(e3{});

    assert(sm_second.is("s0"_s));
    if (!sm_second.is("s0"_s))
    {
        printf("*** defer not processed correctly - final state transition missing! ***\n");
    }

}
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

1 participant