Boost State Machine Language - 来自 `action` 的 `post` 事件

Boost State Machine Language - `post` event from within an `action`

我已经使用 boost sml 几天了,我已经到了需要 post/从动作中处理事件的地步。
我可以看到它可以直接从转换 table:

完成
using namespace sml;
return make_transition_table(
 *"s1"_s + event<my_event> / process_event(other_event{}) = "s2"_s,
  "s2"_s + event<other_event> = X
);

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

例如,使用 boost statechart,每个州都可以访问 context,并且可以 post_event

sml可以吗?

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

// sml::process_queue is for post event
sml::sm<table, sml::process_queue<std::queue>> sm;

发布的事件需要被推入队列。当当前转换完成时,事件从队列中弹出并处理。为此,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) {

参数进程是可调用的。因此,您可以将 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{});
}

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