【问题标题】:How to Pass data to the current boost meta state machine(MSM) substate如何将数据传递到当前的升压元状态机 (MSM) 子状态
【发布时间】:2015-09-08 00:38:07
【问题描述】:

在下面的例子中,在当前执行还在substate1的时候,我想不断的给substate1传递数据,然后根据数据发送Event3或者Event1。看起来 MSM 只支持使用 (process_event()) 发送事件,但我不确定如何将数据连续发送到当前状态。

#include <iostream>
#include <boost/msm/back/state_machine.hpp>
#include <boost/msm/front/state_machine_def.hpp>
#include <boost/msm/front/functor_row.hpp>

namespace {
    namespace msm = boost::msm;
    namespace msmf = boost::msm::front;
    namespace mpl = boost::mpl;

    // ----- Events
    struct Event1 {};
    struct Event2 {};
    struct Event3 {};

    // ----- State machine
    struct OuterSm_:msmf::state_machine_def<OuterSm_>
    {
        struct State1_:msmf::state_machine_def<State1_>
        {
            template <class Event,class Fsm>
            void on_entry(Event const&, Fsm&) const {
                BOOST_STATIC_ASSERT((boost::is_convertible<Fsm, OuterSm_>::value));
                std::cout << "State1::on_entry()" << std::endl;
            }
            template <class Event,class Fsm>
            void on_exit(Event const&, Fsm&) const {
                BOOST_STATIC_ASSERT((boost::is_convertible<Fsm, OuterSm_>::value));
                std::cout << "State1::on_exit()" << std::endl;
            }

            struct SubState1:msmf::state<> {
                template <class Event,class Fsm>
                void on_entry(Event const&, Fsm&) const {
                    BOOST_STATIC_ASSERT((boost::is_convertible<Fsm, State1_>::value));
                    std::cout << "SubState1::on_entry()" << std::endl;
                }
                template <class Event,class Fsm>
                void on_exit(Event const&, Fsm&) const {
                    BOOST_STATIC_ASSERT((boost::is_convertible<Fsm, State1_>::value));
                    std::cout << "SubState1::on_exit()" << std::endl;
                }
            };
            struct SubState2:msmf::state<> {
                template <class Event,class Fsm>
                void on_entry(Event const&, Fsm&) const {
                    BOOST_STATIC_ASSERT((boost::is_convertible<Fsm, State1_>::value));
                    std::cout << "SubState2::on_entry()" << std::endl;
                }
                template <class Event,class Fsm>
                void on_exit(Event const&, Fsm&) const {
                    BOOST_STATIC_ASSERT((boost::is_convertible<Fsm, State1_>::value));
                    std::cout << "SubState2::on_exit()" << std::endl;
                }
            };

            // Set initial state
            typedef mpl::vector<SubState1> initial_state;
            // Transition table
            struct transition_table:mpl::vector<
                //          Start      Event   Next       Action      Guard
                msmf::Row < SubState1, Event2, SubState2, msmf::none, msmf::none >,
                msmf::Row < SubState2, Event3, SubState1, msmf::none, msmf::none >
                > {};
        };
        struct State2:msmf::state<>
        {
            template <class Event,class Fsm>
            void on_entry(Event const&, Fsm&) const {
                BOOST_STATIC_ASSERT((boost::is_convertible<Fsm, OuterSm_>::value));
                std::cout << "State2::on_entry()" << std::endl;
            }
            template <class Event,class Fsm>
            void on_exit(Event const&, Fsm&) const {
                BOOST_STATIC_ASSERT((boost::is_convertible<Fsm, OuterSm_>::value));
                std::cout << "State2::on_exit()" << std::endl;
            }
        };

        typedef msm::back::state_machine<State1_> State1;

        // Set initial state
        typedef State1 initial_state;
        // Transition table
        struct transition_table:mpl::vector<
            //          Start   Event   Next    Action      Guard
            msmf::Row < State1, Event1, State2, msmf::none, msmf::none >
        > {};
    };

    // Pick a back-end
    typedef msm::back::state_machine<OuterSm_> Osm;

    void test()
    {        
        Osm osm;
        osm.start(); 

        std::cout << "> Send Event2()" << std::endl;
        osm.process_event(Event2());
        std::cout << "> Send Event1()" << std::endl;
        osm.process_event(Event1());
    }
}

int main()
{
    test();
    return 0;
}

输出:

State1::on_entry()
SubState1::on_entry()
> Send Event2()
SubState1::on_exit()
SubState2::on_entry()
> Send Event1()
SubState2::on_exit()
State1::on_exit()
State2::on_entry()

【问题讨论】:

    标签: boost boost-msm


    【解决方案1】:

    您可以使用get_state 从状态机中检索状态,然后您可以在该状态上调用任意方法,例如sendData() 在您的示例(live example)的以下修改中:

    #include <iostream>
    #include <boost/msm/back/state_machine.hpp>
    #include <boost/msm/front/state_machine_def.hpp>
    #include <boost/msm/front/functor_row.hpp>
    
    namespace {
        namespace msm = boost::msm;
        namespace msmf = boost::msm::front;
        namespace mpl = boost::mpl;
    
        // ----- Events
        struct Event1 {};
        struct Event2 {};
        struct Event3 {};
    
        // ----- State machine
        struct OuterSm_:msmf::state_machine_def<OuterSm_>
        {
            struct State1_:msmf::state_machine_def<State1_>
            {
                template <class Event,class Fsm>
                void on_entry(Event const&, Fsm&) const {
                    BOOST_STATIC_ASSERT((boost::is_convertible<Fsm, OuterSm_>::value));
                    std::cout << "State1::on_entry()" << std::endl;
                }
                template <class Event,class Fsm>
                void on_exit(Event const&, Fsm&) const {
                    BOOST_STATIC_ASSERT((boost::is_convertible<Fsm, OuterSm_>::value));
                    std::cout << "State1::on_exit()" << std::endl;
                }
    
                struct SubState1:msmf::state<> {
                    template <class Event,class Fsm>
                    void on_entry(Event const&, Fsm&) const {
                        BOOST_STATIC_ASSERT((boost::is_convertible<Fsm, State1_>::value));
                        std::cout << "SubState1::on_entry()" << std::endl;
                    }
                    template <class Event,class Fsm>
                    void on_exit(Event const&, Fsm&) const {
                        BOOST_STATIC_ASSERT((boost::is_convertible<Fsm, State1_>::value));
                        std::cout << "SubState1::on_exit()" << std::endl;
                    }
    
                    void sendData(const std::string& data)
                    {
                        std::cout << "data received in Substate1:" << data << std::endl;
                    }
                };
                struct SubState2:msmf::state<> {
                    template <class Event,class Fsm>
                    void on_entry(Event const&, Fsm&) const {
                        BOOST_STATIC_ASSERT((boost::is_convertible<Fsm, State1_>::value));
                        std::cout << "SubState2::on_entry()" << std::endl;
                    }
                    template <class Event,class Fsm>
                    void on_exit(Event const&, Fsm&) const {
                        BOOST_STATIC_ASSERT((boost::is_convertible<Fsm, State1_>::value));
                        std::cout << "SubState2::on_exit()" << std::endl;
                    }
                };
    
                // Set initial state
                typedef mpl::vector<SubState1> initial_state;
                // Transition table
                struct transition_table:mpl::vector<
                    //          Start      Event   Next       Action      Guard
                    msmf::Row < SubState1, Event2, SubState2, msmf::none, msmf::none >,
                    msmf::Row < SubState2, Event3, SubState1, msmf::none, msmf::none >
                    > {};
            };
            struct State2:msmf::state<>
            {
                template <class Event,class Fsm>
                void on_entry(Event const&, Fsm&) const {
                    BOOST_STATIC_ASSERT((boost::is_convertible<Fsm, OuterSm_>::value));
                    std::cout << "State2::on_entry()" << std::endl;
                }
                template <class Event,class Fsm>
                void on_exit(Event const&, Fsm&) const {
                    BOOST_STATIC_ASSERT((boost::is_convertible<Fsm, OuterSm_>::value));
                    std::cout << "State2::on_exit()" << std::endl;
                }
            };
    
            typedef msm::back::state_machine<State1_> State1;
    
            // Set initial state
            typedef State1 initial_state;
            // Transition table
            struct transition_table:mpl::vector<
                //          Start   Event   Next    Action      Guard
                msmf::Row < State1, Event1, State2, msmf::none, msmf::none >
            > {};
        };
    
        // Pick a back-end
        typedef msm::back::state_machine<OuterSm_> Osm;
    
        void test()
        {        
            Osm osm;
            osm.start(); 
    
            Osm::State1& state1 = osm.get_state<Osm::State1&>();
            Osm::State1::SubState1& substate1 = state1.get_state<Osm::State1::SubState1&>();
            substate1.sendData("hello from outside");
    
            std::cout << "> Send Event2()" << std::endl;
            osm.process_event(Event2());
            std::cout << "> Send Event1()" << std::endl;
            osm.process_event(Event1());
        }
    }
    
    int main()
    {
        test();
        return 0;
    }
    

    输出:

    State1::on_entry()
    SubState1::on_entry()
    data received in Substate1:hello from outside
    > Send Event2()
    SubState1::on_exit()
    SubState2::on_entry()
    > Send Event1()
    SubState2::on_exit()
    State1::on_exit()
    State2::on_entry()
    

    【讨论】:

    • 非常感谢,这帮助我获得了子机的状态并能够分辨出该状态属于哪台机器(如果你有几个!)!点赞!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-21
    • 1970-01-01
    • 1970-01-01
    • 2013-06-06
    • 1970-01-01
    相关资源
    最近更新 更多