[Boost::ext].SML:有没有办法存储回调以便稍后处理事件?

问题描述 投票:0回答:1

我来自 Boost MSM,现在尝试使用 SML 1.1.3 实现相同的状态机。 使用 SML,我无法访问状态机本身,并且被迫使用注入的依赖项。我也大量使用 D-Bus,现在在进行异步 D-Bus 调用时遇到问题。异步 D-Bus 调用是在注入依赖项的方法中进行的。当 D-Bus 调用完成时,将调用依赖项内的回调。我需要一种向状态机发出事件的方法。 存储

sml::back::process
不起作用,我无法确定异步 D-Bus 调用完成后它是否仍然有效。

示例:

    auto queryDBusAction = []( Dep& dep, sml::back::process<Ev_Result> processEvent ) {
        dep.makeAsyncDBusCall( SomeCallback );
    };

...

class Dep
{
public:
    void makeAsyncDBusCall( SomeCallback cb )
    {
        _cb = cb;
        _client.someAsyncDBusCall( boost::bind( &Dep::dbusCallFinished, this, _1 ) );
    }

protected:
    DBusClient _client;
    SomeCallback _cb;

    void dbusCallFinished( Result& result, const DBus::Error& dbusError )
    {
        // Here I need a way/callback to emit an event
        // that gets processed by the state machine
        _cb( Ev_Result{result} );
    }
};

c++ boost c++14 state-machine boost-sml
1个回答
1
投票

为了访问状态机本身,您需要将应用程序类分为基类和子类。 基类具有纯虚成员函数声明。 您可以从 sml 转换表操作调用成员函数。

您需要在定义转换表之后定义子类。 现在,子类可以访问转换表的整个定义。 这意味着 您可以包含 sml::sm

 作为子类的成员

所以你可以从成员函数中调用sml后端的

process_event()

函数。请参阅
memfun1()

#include <iostream> #include <cassert> #include <boost/sml.hpp> #include <boost/asio.hpp> namespace sml = boost::sml; struct e1 {}; struct e2 {}; // Separate member function declarations as the base class struct app_base { virtual void memfun1() = 0; virtual void memfun2(int) const = 0; virtual ~app_base() = default; }; struct app_table { auto operator()() const noexcept { using namespace sml; // I can write member function call in action thanks to base class app_base return make_transition_table( // source event guard action target *"s1"_s + event<e1> [([] { return true; })] / [](app_base& appb) { appb.memfun1(); } = "s2"_s ,"s2"_s + event<e2> / [](app_base& appb) { appb.memfun2(42); } = "s1"_s ); } }; struct app : app_base { app(boost::asio::io_context& ioc):ioc { ioc } {} // post asynchronous callback function that calls process_event() void memfun1() override { std::cout << __PRETTY_FUNCTION__ << std::endl; boost::asio::post( ioc, [this] { std::cout << "async callback is called. call process_event()" << std::endl; sm_.process_event(e2{}); using namespace sml; assert(sm_.is("s1"_s)); } ); } void memfun2(int v) const override { std::cout << __PRETTY_FUNCTION__ << ":" << v << std::endl; } // state machine backend can be a member of application class sml::sm<app_table> sm_ { static_cast<app_base&>(*this) }; boost::asio::io_context& ioc; }; int main() { using namespace sml; boost::asio::io_context ioc; // for async operation example app a { ioc }; assert(a.sm_.is("s1"_s)); a.sm_.process_event(e1{}); assert(a.sm_.is("s2"_s)); ioc.run(); // async loop start until async event will become empty }
可运行演示:

https://wandbox.org/permlink/9XFQAMHuRcMPeU64

© www.soinside.com 2019 - 2024. All rights reserved.