Boost logo

Boost Users :

Subject: Re: [Boost-users] [msm] access to root fsm
From: Christophe Henry (christophe.j.henry_at_[hidden])
Date: 2013-07-15 16:09:24


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


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net