【发布时间】:2018-06-14 11:18:14
【问题描述】:
我想在状态之间以及整个 SM 和客户端代码(即 SM 之外的代码)之间共享数据和访问。
根据我在网上提出的建议,最好的方法是从基类继承所有状态。
添加一个基类并让所有状态和 SM 从中继承很简单,但是如何将处理程序作为该基类的成员添加到 SM 的后端/前端以及如何初始化它?
这个sample code 可以编译,但是在访问设置在 SubState 中的 fsmHandler 时会崩溃(SubState 通常无法访问根 fsm)!
问题:
我如何才能访问根 SM 及其在 SM 层次结构深处的子机器中的数据?
Q1) 如何解决运行时错误?
Q2) 我如何将数据从客户端代码(在 SM 之外)传递到 SM 感觉不对!有没有更好的方法来做到这一点?它是线程安全的吗?
Q3) 我怎样才能使typedef StateBase_<MyFsm_> StateBase 编译。
如果您能提供一个工作样本,我将不胜感激。 提前感谢您的时间和帮助。
代码:
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;
【问题讨论】:
-
我没有 Q1 和 Q3 的答案,但我知道实现 Q2 的一种方法。这是wandbox.org/permlink/SdlC7nSisYc7wVKG的方法。 process_event() 不是线程安全的。你需要锁定它。
-
@Takatoshi Kondo,因此您建议手动将 fsm 的引用一个接一个地传递到每个子机器中。谢谢,解决方案很简单而且有效;
-
这是题外话。我现在正在度假。我无法在两周内回答。
-
这是因为 fsm_ 和 State2__ 相互依赖。您可以像wandbox.org/permlink/hbB405PRxc2FqG8Y 一样解决它
-
或者您可以简单地共享您的用户定义数据目录,而不是共享父状态机。见wandbox.org/permlink/qeH4ULy1V5GRllfL
标签: c++ boost template-meta-programming boost-msm