
On 16.07.2013 0:09, Christophe Henry wrote: Hi,
Hi,
I have main fsm with two sub-levels. The problem is, the sub-fsms need data which is held in root fsm, like:
Ah yes, a classical one, I really need to take care of this. I intend to provide something variadic but I had no time to do it yet :(
...
3. Maybe, there is a easier way to communicate between sub-fsm's?
The easiest would be eiher: - to call outer.get_state<SubFsm&>().data=... - pass in the constructor of SubFsm a pointer to the outer.
Indeed it would, but I'm too lazy to manually iterate all sub-fsm's to do the same thing... Finally, I took the second way.
As both still form a cycle, better would be a pointer to an interface, or even better, to a type_erasure type representing the minimum needed interface of the outer fsm. A boost::function would do too. I personally use type_erasure.
in init_fsm struct I already have generic fsm type, how can type_erasure fit here? test code: #include <iostream> #include <assert.h> #include <boost/msm/back/state_machine.hpp> #include <boost/msm/front/state_machine_def.hpp> #include <boost/msm/front/functor_row.hpp> using boost::msm::front::Row; struct init {}; struct level1 {}; struct level2 {}; struct Level2_: public boost::msm::front::state_machine_def<Level2_> { struct Empty : public boost::msm::front::state<> {}; typedef boost::mpl::vector<Empty> initial_state; struct transition_table : public boost::mpl::vector<> {}; int i_; // some data }; typedef boost::msm::back::state_machine<Level2_> Level2; struct Level1_: public boost::msm::front::state_machine_def<Level1_> { struct Empty : public boost::msm::front::state<> {}; typedef boost::mpl::vector<Empty> initial_state; struct transition_table : public boost::mpl::vector< Row < Empty, level2, Level2 > > {}; int i_; }; typedef boost::msm::back::state_machine<Level1_> Level1; struct Root_: public boost::msm::front::state_machine_def<Root_> { struct Empty : public boost::msm::front::state<> {}; struct Init : public boost::msm::front::state<> {}; struct InitAction { template <typename RootT> struct init_fsm { init_fsm(RootT* root) : root_(root) { } // sub-FSM template <typename T> typename boost::enable_if<typename boost::msm::back::is_composite_state<T>::type, void>::type operator()(boost::msm::wrap<T>&) const { typedef typename T::stt stt; typedef typename boost::msm::back::generate_state_set<stt>::type all_states; auto& fsm(root_->get_state<T&>()); fsm.i_ = root_->i_ + 1; std::cout << typeid(T).name() << std::endl; boost::mpl::for_each<all_states, boost::msm::wrap<boost::mpl::placeholders::_1> > (init_fsm<T>(&fsm)); } // normal states template <typename T> typename boost::disable_if<typename boost::msm::back::is_composite_state<T>::type, void>::type operator()(boost::msm::wrap<T>&) const { } protected: RootT* root_; }; template <typename EVT, typename FSM, typename SourceState, typename TargetState> void operator()(EVT&, FSM& fsm, SourceState&, TargetState&) const { typedef typename FSM::stt stt; typedef typename boost::msm::back::generate_state_set<stt>::type all_states; boost::mpl::for_each<all_states, boost::msm::wrap<boost::mpl::placeholders::_1> > (init_fsm<FSM>(&fsm)); } }; typedef boost::mpl::vector<Empty> initial_state; struct transition_table : public boost::mpl::vector< Row < Empty, init, Init, InitAction >, Row < Init, level1, Level1 > > {}; int i_; // some data }; typedef boost::msm::back::state_machine<Root_> fsm_t; int main() { fsm_t fsm; fsm.i_ = 0; fsm.start(); fsm.process_event(init()); fsm.process_event(level1()); fsm.process_event(level2()); assert(fsm.i_ == 0); assert(fsm.get_state<Level1&>().i_ == 1); assert(fsm.get_state<Level1&>().get_state<Level2&>().i_ == 2); return 0; };
HTH, Christophe