boost-ext / sml

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

Deferred event only defers once #586

Open lambdaknight opened 10 months ago

lambdaknight commented 10 months ago

Expected Behavior

Multiple deferrals in a row should all be handled.

Actual Behavior

Only the first deferral triggers.

Steps to Reproduce the Problem

#include <cstdio>
#include <cassert>
#include <deque>
#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 defer_chain
{
    auto operator()() const noexcept
    {
        using namespace sml;
        return make_transition_table(
            * "s0"_s + event<e1> / defer = "s1"_s
            , "s1"_s + event<e1> / defer = "s2"_s
            , "s2"_s + event<e1> / defer = "s3"_s
            , "s3"_s + event<e1>         = X
        );
    }
};

int main()
{
    using namespace sml;

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

    sm.process_event(e1{});
}

https://godbolt.org/z/o39z4sMje

Specifications

Alex0vSky commented 8 months ago

Now everything is working fine. And there was a merge. Here is the answer from this https://godbolt.org/z/o39z4sMje:

ASM generation compiler returned: 0
Execution build compiler returned: 0
Program returned: 0
[defer_chain][process_event] boost::sml::back::on_entry<boost::sml::back::_, boost::sml::back::initial>
[defer_chain][process_event] e1
[defer_chain][transition] s0 -> s1
[defer_chain][process_event] e1
[defer_chain][transition] s1 -> s2
[defer_chain][process_event] e1
[defer_chain][transition] s2 -> s3
[defer_chain][process_event] e1
[defer_chain][transition] s3 -> terminate

Should we close it?