
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 :(
struct SomeAction { template <typename EVT, typename FSM, typename SourceState, typename TargetState> void operator()(EVT&, FSM& fsm, SourceState&, TargetState&) const { // ... } };
Instance of fsm here might be root fsm as well as sub-fsm. I see two possible solutions:
1. use sm_ptr policy and store parent pointer in each sub-fsm In this case access might look like this:
fsm.parent_->data; (access from 1-level fsm) fsm.parent_->parent_->data; (access from 2-level fsm)
doesn't look so nice, besides, documentation states that using sm_ptr is deprecated.
It's deprecated because it was a bad solution, and an ugly one too.
2. recursively traverse all states, detect fsm's and store root pointer
typedef RootFSM::stt stt; typedef boost::msm::back::generate_state_set<stt>::type all_states;
boost::mpl::for_each<all_states, boost::msm::wrap<mpl::placeholders::_1> > (find_sub_fsm<stt>());
template <typename stt> struct find_sub_fsm { template <class StateType> void operator()(boost::msm::wrap<StateType>& state) const { // ??? // state.root_ = &g_root; // do the recurs } };
How to detect that StateType is sub-fsm?
You have is_composite_state<StateType>::type but it's still quite a bit of metaprogramming with some enable_if. Something like (untested) template <class StateType> typename ::boost::enable_if<typename is_composite_state<T>::type,void>::type void operator()(boost::msm::wrap<StateType>& state) const // submachines template <class StateType> typename ::boost::disable_if<typename is_composite_state<T>::type,void>::type void operator()(boost::msm::wrap<StateType>& state) const // normal states
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. 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. HTH, Christophe