|
Boost Users : |
Subject: Re: [Boost-users] [msm] access to root fsm
From: Sam Fisher (infest21h_at_[hidden])
Date: 2013-07-18 05:01:50
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
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