Boost logo

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