如何退出拆分为多个文件的分层 SM 中的子机? (使用 boost::MSM)
How to exit a submachine in a hierarchial-SM that is split into multiple files? (using boost::MSM)
有一个很好的教程解释了我们如何使用 "exit-pseudo-state" 从使用 boost::MSM
、here.
的 submachine 退出
但是我需要将我的 SM 拆分成多个文件,以使其易于管理,这就是问题所在。
当在主 fsm 文件中定义子 SM 时,一切正常,即从 "exit-pseudo-state" 退出导致从子 SM 退出到下一个状态(sample code)
在单独的文件中实现子 SM,我必须在其中进行额外级别的虚拟继承,这会导致问题。
这次到内部子 SM 中的退出伪状态的转换不会触发到父 SM 中下一个状态的退出。 Here 是显示问题的示例代码。
从下面的输出可以看出,退出substate21
后最后缺少State2::on_exit()
Testing boost::msm ...
State1::on_entry()
State1::on_exit()
State2::on_entry()
SubState21::on_entry()
SubState21::on_exit()
提前感谢您的帮助
包含代码:
主文件:
#include "myfsm.h"
int main()
{
std::cout << "Testing boost::msm ..." << std::endl;
MyFsm fsm;
fsm.start();
fsm.process_event(Event1());
fsm.process_event(Event3());
//fsm.process_event(Event2());
}
主 fsm:
#include <boost/msm/back/state_machine.hpp>
#include <boost/msm/front/state_machine_def.hpp>
#include <boost/msm/front/functor_row.hpp>
#include "state2.h"
#include "events.h"
namespace msm = boost::msm;
namespace msmf = boost::msm::front;
namespace mpl = boost::mpl;
struct MyFsm_ : msmf::state_machine_def<MyFsm_>
{
struct State1 : msmf::state<>{
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 State2m : State2 {};
// Set initial state
typedef State1 initial_state;
// Transition table
struct transition_table:mpl::vector<
msmf::Row < State1, Event1, State2m, msmf::none, msmf::none >,
msmf::Row < State2m, Event2, State1, msmf::none, msmf::none >,
msmf::Row < State2::exit_pt
<State2_::Exit2>, msmf::none, 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;
}
};
// Pick a back-end
typedef msm::back::state_machine<MyFsm_> MyFsm;
sub-SM 即 state2.h:
#include <iostream>
#include <boost/msm/back/state_machine.hpp>
#include <boost/msm/front/state_machine_def.hpp>
#include <boost/msm/front/functor_row.hpp>
#include "events.h"
namespace msm = boost::msm;
namespace msmf = boost::msm::front;
namespace mpl = boost::mpl;
struct State2_ : msmf::state_machine_def<State2_>{
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<>{
template<class Event, class Fsm> void on_entry(const Event&, Fsm&) const {std::cout << "SubState21::on_entry()" <<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;
struct Exit2 : msmf::exit_pseudo_state<msmf::none> {};
struct transition_table:mpl::vector<
msmf::Row < SubState21, Event3, Exit2, msmf::none, msmf::none >
>{};
};
typedef msm::back::state_machine<State2_> State2;
您需要在 msmf::state_machine_def
的 外部 定义 msm::back::state_machine
。
这是您示例的更新版本:
https://wandbox.org/permlink/DktAL169yjFNnmfl
有四个更新点。
在state2.h
(1)
// 1. move msm::back::state_machine to fsm
// typedef msm::back::state_machine<State2_> State2;
在myfsm.h
(2, 3, 4)
struct State2m : State2_ {}; // 2. replaced State2 to State2_
typedef msm::back::state_machine<State2m> State2mm; // 3. define backend here
// Transition table
struct transition_table:mpl::vector<
// 4. updated transition table using State2mm
msmf::Row < State1, Event1, State2mm, msmf::none, msmf::none >,
msmf::Row < State2mm, Event2, State1, msmf::none, msmf::none >,
msmf::Row < State2mm::exit_pt
<State2mm::Exit2>, msmf::none, State1, msmf::none, msmf::none >
>{};
在这种情况下,你可以做更优雅的方式。您可以删除 struct State2m : State2_ {};
继承。
代码如下:
https://wandbox.org/permlink/FO7lEELLtLhiismu
您可以如下定义State2
并在转换table.
中使用State2
typedef msm::back::state_machine<State2_> State2;
// 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 >,
msmf::Row < State2::exit_pt
<State2::Exit2>, msmf::none, State1, msmf::none, msmf::none >
>{};
有一个很好的教程解释了我们如何使用 "exit-pseudo-state" 从使用 boost::MSM
、here.
但是我需要将我的 SM 拆分成多个文件,以使其易于管理,这就是问题所在。
当在主 fsm 文件中定义子 SM 时,一切正常,即从 "exit-pseudo-state" 退出导致从子 SM 退出到下一个状态(sample code)
在单独的文件中实现子 SM,我必须在其中进行额外级别的虚拟继承,这会导致问题。 这次到内部子 SM 中的退出伪状态的转换不会触发到父 SM 中下一个状态的退出。 Here 是显示问题的示例代码。
从下面的输出可以看出,退出substate21
后最后缺少State2::on_exit()
Testing boost::msm ...
State1::on_entry()
State1::on_exit()
State2::on_entry()
SubState21::on_entry()
SubState21::on_exit()
提前感谢您的帮助
包含代码:
主文件:
#include "myfsm.h"
int main()
{
std::cout << "Testing boost::msm ..." << std::endl;
MyFsm fsm;
fsm.start();
fsm.process_event(Event1());
fsm.process_event(Event3());
//fsm.process_event(Event2());
}
主 fsm:
#include <boost/msm/back/state_machine.hpp>
#include <boost/msm/front/state_machine_def.hpp>
#include <boost/msm/front/functor_row.hpp>
#include "state2.h"
#include "events.h"
namespace msm = boost::msm;
namespace msmf = boost::msm::front;
namespace mpl = boost::mpl;
struct MyFsm_ : msmf::state_machine_def<MyFsm_>
{
struct State1 : msmf::state<>{
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 State2m : State2 {};
// Set initial state
typedef State1 initial_state;
// Transition table
struct transition_table:mpl::vector<
msmf::Row < State1, Event1, State2m, msmf::none, msmf::none >,
msmf::Row < State2m, Event2, State1, msmf::none, msmf::none >,
msmf::Row < State2::exit_pt
<State2_::Exit2>, msmf::none, 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;
}
};
// Pick a back-end
typedef msm::back::state_machine<MyFsm_> MyFsm;
sub-SM 即 state2.h:
#include <iostream>
#include <boost/msm/back/state_machine.hpp>
#include <boost/msm/front/state_machine_def.hpp>
#include <boost/msm/front/functor_row.hpp>
#include "events.h"
namespace msm = boost::msm;
namespace msmf = boost::msm::front;
namespace mpl = boost::mpl;
struct State2_ : msmf::state_machine_def<State2_>{
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<>{
template<class Event, class Fsm> void on_entry(const Event&, Fsm&) const {std::cout << "SubState21::on_entry()" <<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;
struct Exit2 : msmf::exit_pseudo_state<msmf::none> {};
struct transition_table:mpl::vector<
msmf::Row < SubState21, Event3, Exit2, msmf::none, msmf::none >
>{};
};
typedef msm::back::state_machine<State2_> State2;
您需要在 msmf::state_machine_def
的 外部 定义 msm::back::state_machine
。
这是您示例的更新版本:
https://wandbox.org/permlink/DktAL169yjFNnmfl
有四个更新点。
在state2.h
(1)
// 1. move msm::back::state_machine to fsm
// typedef msm::back::state_machine<State2_> State2;
在myfsm.h
(2, 3, 4)
struct State2m : State2_ {}; // 2. replaced State2 to State2_
typedef msm::back::state_machine<State2m> State2mm; // 3. define backend here
// Transition table
struct transition_table:mpl::vector<
// 4. updated transition table using State2mm
msmf::Row < State1, Event1, State2mm, msmf::none, msmf::none >,
msmf::Row < State2mm, Event2, State1, msmf::none, msmf::none >,
msmf::Row < State2mm::exit_pt
<State2mm::Exit2>, msmf::none, State1, msmf::none, msmf::none >
>{};
在这种情况下,你可以做更优雅的方式。您可以删除 struct State2m : State2_ {};
继承。
代码如下:
https://wandbox.org/permlink/FO7lEELLtLhiismu
您可以如下定义State2
并在转换table.
State2
typedef msm::back::state_machine<State2_> State2;
// 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 >,
msmf::Row < State2::exit_pt
<State2::Exit2>, msmf::none, State1, msmf::none, msmf::none >
>{};