如何实现"BaseState"?可以在boost :: msm中访问状态机(SM)的后端 [英] How to implement a "BaseState" with access to back/front end of the state-machine (SM) in boost::msm
问题描述
我想在状态之间以及整个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屋!