如何实现"BaseState"?可以在boost :: msm中访问状态机(SM)的后端 [英] How to implement a "BaseState" with access to back/front end of the state-machine (SM) in boost::msm

查看:120
本文介绍了如何实现"BaseState"?可以在boost :: msm中访问状态机(SM)的后端的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I want to share data and access between states as well as the SM as a whole and the client code (i.e. the code outside the SM).

根据我在网上提出的内容,最好的方法是从基类继承所有状态.

Based on what I've come up with on the net, the best way would be to inherit all states from a base class.

添加基类并设置所有状态&从中继承的SM很简单,但是如何将处理程序作为此基类的成员添加到SM的后端/前端,又如何对其进行初始化?

Adding a base class and making all states & the SM to inherit from that is simple, but how can I add the handler to the backend/frontend of the SM as a member of this base class and how can I initialize it?

示例代码可以编译,但是在访问SubState中设置的fsmHandler时崩溃(SubState会通常无法访问根fsm)!

This sample code compiles, but crashes when accessing the fsmHandler set in the SubState (the SubState would not normally have access to the root fsm)!

问题:

如何在SM层次结构深处的子计算机中访问根SM及其数据?

How can I get access to the root-SM and its data in the submachines deep down the SM-hierarchy?

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

Q1) How can I solve the run-time error?

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

Q2) How I pass data from client code (outside the SM) to the SM doesn't feel right! Is there a better way of doing this? Is it thread safe?

Q3)如何使typedef StateBase_<MyFsm_> StateBase进行编译.

Q3) How can I make typedef StateBase_<MyFsm_> StateBase compile.

如果您能提供一个有效的样本,我将不胜感激. 感谢您的时间&提前帮助.

I would really appreciate if you could provide a working sample. Thanks for your time & help in advance.

代码:

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;

推荐答案

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

You can access the outer state machine from the sub state. This is the state machine diagram based on your code.

+-------+--------------------------------------------------------+
| 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()处将外部状态机的指针分配给它.

In order to access the outer state machine, State2__ need to have the pointer of MyFsm_. So I added rootFsm as the member variable of State2__ and assigns the pointer of the outer state machine to it at Stete2__::on_entry().

如果要访问Stete2__::on_entry()上的外部状态机成员,则需要MyFsm_定义.因此,您需要将成员函数State2__::on_entry的定义和定义分开.

If you want to access the member of the outer state machine at the Stete2__::on_entry(), you need the definition of MyFsm_. So you need to separate the member function State2__::on_entry's decralation and definition.

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

Here is a key structure to achieve the goal:

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

这篇关于如何实现"BaseState"?可以在boost :: msm中访问状态机(SM)的后端的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆