【问题标题】:Boost statechart - pass event data to state constructor using triggering_eventBoost statechart - 使用 triggering_event 将事件数据传递给状态构造函数
【发布时间】:2016-11-16 14:23:19
【问题描述】:

我希望能够将数据从事件传递到由于转换而构建的状态。

从 2009 年的 this 帖子和 2010 年的 this 一篇帖子中,建议使用 triggering_event()。但是,我在任何地方都找不到演示如何使用它的示例。

谁能帮忙?

【问题讨论】:

    标签: c++ boost boost-statechart


    【解决方案1】:

    以下示例是基于 here 描述的电机状态机的 Boost 状态图实现。我没有使用 custom_reaction 将速度从 EvSetSpeed 事件中拉出来(就像这里的其他状态一样),而是将其修改为在 Start 状态的构造函数中调用 triggering_event()。

    注意事项:

    1. boost statechart here 的旧文档指出:“triggering_event 的调用者需要进行类型检查或强制转换返回值”,因为 triggering_event 返回一个 const event_base 指针。
    2. 在构造期间调用 triggering_event 要求调用状态从 state 派生,而不是从 simple_state 派生。这是因为 triggering_event 正在从构造函数访问状态机。对于它的价值,我还注意到文档指出,使用 triggering_event 通常意味着状态机设计存在问题,应该避免。
    3. 也许更熟悉 boost statechart 的人可以对此发表评论,但我发现如果我希望它转换为 Running(如我的反应列表所述),我必须在 Start 状态构造函数中重新发布触发事件。李>

    最后值得一提的是,尝试在状态机初始状态的构造函数中调用 triggering_event 会导致返回 null 值。这是因为初始状态是在调用initial期间构建的,没有触发事件。

    #include <boost/statechart/state_machine.hpp>
    #include <boost/statechart/simple_state.hpp>
    #include <boost/statechart/state.hpp>
    #include <boost/statechart/event.hpp>
    #include <boost/statechart/in_state_reaction.hpp>
    #include <boost/statechart/transition.hpp>
    #include <boost/mpl/list.hpp>
    #include <boost/statechart/custom_reaction.hpp>
    #include <iostream>
    
    namespace mpl = boost::mpl;
    namespace sc = boost::statechart;
    
    class EvHalt : public sc::event< EvHalt > {};
    class EvSetSpeed : public sc::event< EvSetSpeed >
    {
    public:
        EvSetSpeed(int speed) : _speed(speed) {}
        int getSpeed() const { return _speed; };
    
    private:
        int _speed;
    };
    
    class Idle;
    class Start;
    class Stop;
    class Running;
    
    class Motor : public sc::state_machine<Motor, Idle> {};
    
    class Idle : public sc::simple_state<Idle, Motor>
    {
    public:
        typedef mpl::list<
            sc::transition< EvSetSpeed, Start >,
            sc::transition< EvHalt, Idle > > reactions;
    
        Idle() { std::cout << "Entering Idle State" << std::endl; };
        ~Idle() { std::cout << "Exiting Idle State" << std::endl; };
    };
    
    class Start : public sc::state<Start, Motor>
    {
    public:
        typedef mpl::list<
            sc::transition< EvSetSpeed, Running >,
            sc::transition< EvHalt, Stop  > > reactions;
    
        Start(my_context ctx) : _speed(0), my_base(ctx)
        { 
            auto trigEvt = dynamic_cast<const EvSetSpeed*>(triggering_event());
            if (trigEvt) // returns true if trigEvt is indeed an EvSetSpeed event
            {
                _speed = trigEvt->getSpeed();
                post_event(*trigEvt);
                std::cout << "Entering Start State at speed " << _speed << std::endl;
            }
            else
                std::cout << "Entering Start State. Triggering Event is NOT EvSetSpeed." << std::endl;
        };
        ~Start() { std::cout << "Exiting Start State" << std::endl; };
    private:
        int _speed;  // Unused in this example.
    };
    
    class Running : public sc::simple_state<Running, Motor>
    {
    public:
        typedef mpl::list<
            sc::custom_reaction< EvSetSpeed >,
            sc::custom_reaction< EvHalt  > > reactions;
    
        sc::result react(const EvSetSpeed& ev)
        {
            std::cout << "In Running Mode: Set Speed to " << ev.getSpeed() << std::endl;
            return discard_event();
        }
        sc::result react(const EvHalt& ev)
        {
            std::cout << "In Running Mode: Halting Motor" << std::endl;
            post_event(ev);
            return transit<Stop>();
        }
    
        Running() { std::cout << "Entering Running State" << std::endl; };
        ~Running() { std::cout << "Exiting Running State" << std::endl; };
    };
    
    class Stop : public sc::simple_state<Stop, Motor>
    {
    public:
        typedef sc::transition< EvHalt, Idle > reactions;
    
        Stop() { std::cout << "Entering Stop State" << std::endl; };
        ~Stop() { std::cout << "Exiting Stop State" << std::endl; };
    };
    
    int main()
    {
        Motor myMotor;
        myMotor.initiate();
        myMotor.process_event(EvSetSpeed(100));
        myMotor.process_event(EvSetSpeed(200));
        myMotor.process_event(EvHalt());
        myMotor.process_event(EvSetSpeed(300));
        myMotor.process_event(EvHalt());
        myMotor.process_event(EvHalt());
        return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-04-24
      • 1970-01-01
      • 1970-01-01
      • 2019-03-08
      • 1970-01-01
      • 2019-04-25
      • 1970-01-01
      相关资源
      最近更新 更多