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().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
#include
#include
#include
using boost::msm::front::Row;
struct init {};
struct level1 {};
struct level2 {};
struct Level2_: public boost::msm::front::state_machine_def
{
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;
struct Level1_: public boost::msm::front::state_machine_def
{
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;
struct Root_: public boost::msm::front::state_machine_def
{
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::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());
fsm.i_ = root_->i_ + 1;
std::cout << typeid(T).name() << std::endl;
boost::mpl::for_eachboost::mpl::placeholders::_1 >
(init_fsm<T>(&fsm));
}
// normal states
template <typename T>
typename boost::disable_if::type
operator()(boost::msm::wrap<T>&) const
{ }
protected:
RootT* root_;
};
template
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_eachboost::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 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().i_ == 1);
assert(fsm.get_state().get_state().i_ == 2);
return 0;
};
HTH,
Christophe