如何实现 "BaseState" 并访问 boost::msm 中状态机 (SM) 的 back/front 端

How to implement a "BaseState" with access to back/front end of the state-machine (SM) in boost::msm

我想在状态之间以及整个 SM 和客户端代码(即 SM 之外的代码)之间共享数据和访问。

根据我在网上找到的内容,最好的方法是从基础 class.

继承所有状态

添加一个基 class 并使所有状态和 SM 继承自它很简单,但是如何将处理程序作为该基的成员添加到 SM 的 backend/frontend class 我该如何初始化它?

sample code 编译,但在访问 SubState 中设置的 fsmHandler 时崩溃(SubState 通常无法访问根 fsm)!

Questions:

我如何才能访问根 SM 及其在 SM 层次结构深处的子机器中的数据?

Q1) 如何解决运行-时间错误?

Q2) 我将数据从客户端代码(SM 外部)传递到 SM 的方式感觉不对!有更好的方法吗?它是线程安全的吗?

Q3) 如何让typedef StateBase_<MyFsm_> StateBase编译。

如果您能提供一个工作示例,我将不胜感激。 提前感谢您的时间和帮助。

The code:

main.cpp

int main()
{    
    std::cout << "Testing boost::msm ..." << std::endl;
    MyFsm fsm;
    fsm.start();

    MyFsm::State1& tempState = fsm.get_state<MyFsm::State1&>();    
    fsm.m_outerSMData=77;
    tempState.m_fsmHandler = &fsm;


    fsm.process_event(Event1());
    fsm.process_event(Event2());
}

myfsm.h

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

struct Event1{};
struct Event2{};

template<class Fsm>
struct StateBase_{
    //StateBase(Fsm *fsm):m_fsm(fsm){}
    StateBase_(){}
    ~StateBase_(){}

    Fsm *m_fsmHandler;
};

//typedef StateBase_<MyFsm_> StateBase;//How can I make this typedef work?

struct MyFsm_ : msmf::state_machine_def<MyFsm_, StateBase_<MyFsm_> >
{
    struct State1 : msmf::state<StateBase_<MyFsm_>>{
        template<class Event, class Fsm> void on_entry(const Event&, Fsm&) const {std::cout << "State1::on_entry()" << std::endl;}
        template<class Event, class Fsm> void on_exit(const Event&, Fsm&) const {std::cout << "State1::on_exit()" << std::endl;}
    };    

    struct State2_ : msmf::state_machine_def<State2_, StateBase_>{
        template<class Event, class Fsm> void on_entry(const Event&, Fsm&) const {std::cout << "State2::on_entry()" << std::endl;}
        template<class Event, class Fsm> void on_exit(const Event&, Fsm&) const {std::cout << "State2::on_exit()" << std::endl;}

        struct SubState21 : msmf::state<StateBase_>{
            template<class Event, class Fsm> 
            void on_entry(const Event&, Fsm&) const {
                std::cout << "SubState21::on_entry()" 
                <<"OuterSMData= "<<m_fsmHandler->m_outerSMData <<std::endl;
            }
            template<class Event, class Fsm> 
            void on_exit(const Event&, Fsm&) const {
                std::cout << "SubState21::on_exit()" << std::endl;
            }
        };
        typedef mpl::vector<SubState21> initial_state;
    };
    typedef msm::back::state_machine<State2_> State2;
   // Set initial state
   typedef State1 initial_state;

   // Transition table
   struct transition_table:mpl::vector<
         msmf::Row < State1, Event1, State2, msmf::none, msmf::none >,
         msmf::Row < State2, Event2, State1, msmf::none, msmf::none >
   >{};

  template<class Event, class Fsm>
   void no_transition(Event const&, Fsm&, int state){
       std::cout<<"no_transiton detected from state: "<< state << std::endl;
   }

   //void setPtr(int data/*MyFsm_ &fsm*/){State1::m_baseData=10;}
   int m_outerSMData=44;
};
// Pick a back-end
typedef msm::back::state_machine<MyFsm_> MyFsm;

您可以从子状态访问外部状态机。 这是基于您的代码的状态机图。

+-------+--------------------------------------------------------+
| Fsm_  |  member variable: m_outerSMData                        |
+-------+                                                        |
|                                                                |
|         *                                                      |
|         |                                                      |
|         V                                                      |
|     +----------+      +-----------------------------------+    |
|     |  State1  |      |      State2                       |    |
|     +----------+Event1+-----------------------------------+    |
|     |          |----->| on_entry/rootFsm=&f               |    |
|     |          |      | member variable: rootFsm          |    |
|     |          |      |  +---------------------------+    |    |
|     |          |Event2|  | SubState21                |    |    |
|     |          |<-----|  |                           |    |    |
|     |          |      |  | on_entry/                 |    |    |
|     |          |      |  | access                    |    |    |
|     |          |      |  | f.rootFsm->m_outerSMData  |    |    |
|     |          |      |  +---------------------------+    |    |
|     +----------+      +-----------------------------------+    |
+----------------------------------------------------------------+

为了访问外部状态机,State2__需要有MyFsm_的指针。所以我添加了rootFsm作为State2__的成员变量,并在Stete2__::on_entry().

处将外层状态机的指针赋值给它

如果要访问Stete2__::on_entry()处的外部状态机成员,需要MyFsm_定义。所以需要把成员函数State2__::on_entry的声明和定义分开

这是实现目标的关键结构:

struct MyFsm_;         // forward declaration

struct State2__ .... { // class definition

    // member function template declaration
    template<class Event, class Fsm> void on_entry(const Event&, Fsm& f);

    MyFsm_* rootFsm;
};

struct MyFsm_ ... {    // class definition
    // requre State2__ definition here
};

// member function template definition
template<class Event, class Fsm> void State2__::on_entry(const Event&, Fsm& f) {
    // requre MyFsm_ definition here
    rootFsm = &f;
    std::cout << "Print OuterSMData= " << rootFsm->m_outerSMData << std::endl; 
}

这是现场演示: https://wandbox.org/permlink/hbB405PRxc2FqG8Y