Boost 状态机语言 - 从“action”中“post”事件

hdo*_*adu 1 c++ boost state-machine boost-sml

我使用boost sml几天了,我已经到了需要在操作中发布/处理事件的地步。
我可以看到它可以直接从转换表完成:

using namespace sml;
return make_transition_table(
 *"s1"_s + event<my_event> / process_event(other_event{}) = "s2"_s,
  "s2"_s + event<other_event> = X
);
Run Code Online (Sandbox Code Playgroud)

但我的用例是不同的:
我有一个状态,它有一个actionforon-entry事件,它做了一些工作,并最终触发一个事件(来自withinstate action)。

例如,对于boost statechart,每个州都可以访问 且context可以post_event

这可能吗sml

Tak*_*ndo 5

有可能的。你需要做两件事。一种是将boost::sml::queue模板参数设置为boost::sml::sm.

// sml::process_queue is for post event
sml::sm<table, sml::process_queue<std::queue>> sm;
Run Code Online (Sandbox Code Playgroud)

发布的事件需要被推入队列。当前转换完成后,将从队列中弹出事件并进行处理。为了做到这一点,Boost.SML 需要一些队列。sml::process_queue<std::queue>提供队列类型。您可以传递任何满足队列概念且行为相同的类型std::queue

另一种是sml::back::process<comma_separated_list_of_processed_event_types>为操作处理程序设置参数,如下所示:

[](auto const& /*ev*/, sml::back::process<other_event /*, my_event*/ > process) {
Run Code Online (Sandbox Code Playgroud)

参数过程是可调用的。所以你可以process作为函数调用。当您调用时process(event),事件将发布到队列中。

这是一个示例代码:

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

int main() {
    namespace sml = boost::sml;

    struct my_event {};
    struct other_event {};

    struct table {
        auto operator()() const noexcept {
            using namespace sml;
            return make_transition_table(

               *"s1"_s + event<my_event> / 
                // In order to post event in the action,
                // you need to define the action handler as follows.
                // The key is the second parameter.
                // `sml::back::process` is posting event callable type.
                // You need to pass all event types that are posted in the action handler
                // as the template argument.
                // Unfortunately you cannot write `sml::back::process<_>` for all events.
                [](auto const& /*ev*/, sml::back::process<other_event /*, my_event*/ > process) {
                    std::cout << "before post" << std::endl;
                    process(other_event{});
                    std::cout << "after post" << std::endl;
                } = "s2"_s,

                "s2"_s + event<other_event> = X,

                // entry exit log
                "s1"_s + sml::on_entry<_> / [] { std::cout << "s1 on entry" << std::endl; },
                "s1"_s + sml::on_exit<_>  / [] { std::cout << "s1 on exit"  << std::endl; },
                "s2"_s + sml::on_entry<_> / [] { std::cout << "s2 on entry" << std::endl; },
                "s2"_s + sml::on_exit<_>  / [] { std::cout << "s2 on exit"  << std::endl; }
            );
        };
    };

    // sml::process_queue is for post event
    sml::sm<table, sml::process_queue<std::queue>> sm;
    sm.process_event(my_event{});
}
Run Code Online (Sandbox Code Playgroud)

现场演示: https: //wandbox.org/permlink/yueELv7SoFbPCEW1