2015-06-18 3 views
1

У меня есть два подчиненных SM внутри моего основного SM. Я хочу, чтобы иметь возможность прыгать в любой из основного SM, но также перейти от одного sub SM к другому SM. Но я не могу. Я могу перейти от основного SM к sub SMs и от один от SM SM в другой, но когда я добавляю «взаимные» переходы между sub SM, компиляция терпит неудачу с ~ 10 ошибками, жалующимися на разные вещи , Я полагаю, это связано с тем, что компилятор переходит в рекурсивный спин.Прыжки между sub SMs в boost :: msm

Я предполагаю, что могу добавить фиктивное состояние в основной SM с анонимным переходом в целевой SM SM. Но тогда я потерял бы реальное событие, которое вызвало переход, и я не хочу этого (он содержит данные).

Вот некоторый тестовый код с ошибочной строкой закомментировать

#include <iostream> 

#include <boost/msm/back/state_machine.hpp> 
#include <boost/msm/front/state_machine_def.hpp> 
#include <boost/msm/front/functor_row.hpp> 

namespace { 

    using namespace boost::msm; 
    using namespace boost::msm::front; 
    namespace mpl = boost::mpl; 

    struct EvGotoSub1 {}; 
    struct EvGotoSub2 {}; 

    struct MainSM_; 
    using Main = back::state_machine<MainSM_>;  
    struct Sub1SM_; 
    using Sub1 = back::state_machine<Sub1SM_>; 
    struct Sub2SM_; 
    using Sub2 = back::state_machine<Sub2SM_>; 

    struct Sub1SM_ : state_machine_def<Sub1SM_> { 
     struct Started : state<> { }; 
     using initial_state = mpl::vector<Started>; 
     struct transition_table:mpl::vector< 
     Row<Started, EvGotoSub2, Sub2, none, none> 
     > {}; 
    }; 

    struct Sub2SM_ : state_machine_def<Sub2SM_> { 
     struct Started : state<> { }; 
     using initial_state = mpl::vector<Started>; 
     struct transition_table:mpl::vector< 
     // Uncomment line below to break things 
     //Row<Started, EvGotoSub1, Sub1, none, none> 
     > {}; 
    }; 

    struct MainSM_ : state_machine_def<MainSM_> { 
     struct Started : state<> { }; 
     using initial_state = mpl::vector<Started>; 
     struct transition_table:mpl::vector< 
     Row<Started, EvGotoSub1, Sub1, none, none>, 
     Row<Started, EvGotoSub2, Sub2, none, none> 
     > {}; 
    }; 
} 

int main() { 

    Main main; 
    main.start(); 
    main.process_event(EvGotoSub1()); 
    main.process_event(EvGotoSub2()); 
    main.process_event(EvGotoSub1()); 
} 

ответ

1

Я предполагаю, что вы не хотите, чтобы гнездо Sub2 внутри Sub1 и наоборот, но оба submachines в Main без вложенности , Вы можете выйти из одного автомата и перейти к другому, используя pseudo exit states.

Эти выходные состояния просто переадресовать входящие события, которые затем можно перейти к другой автоматчиков, определяя дополнительные переходы в таблице переходов Main:

#include <iostream> 

#include <boost/msm/back/state_machine.hpp> 
#include <boost/msm/front/state_machine_def.hpp> 
#include <boost/msm/front/functor_row.hpp> 

namespace { 

    using namespace boost::msm; 
    using namespace boost::msm::front; 
    namespace mpl = boost::mpl; 

    struct EvGotoSub1 { EvGotoSub1(int d1):d1(d1){} int d1;}; 
    struct EvGotoSub2 { EvGotoSub2(int d2):d2(d2){} int d2;}; 

    struct MainSM_; 
    using Main = back::state_machine<MainSM_>;  
    struct Sub1SM_; 
    using Sub1 = back::state_machine<Sub1SM_>; 
    struct Sub2SM_; 
    using Sub2 = back::state_machine<Sub2SM_>; 

    struct Sub1SM_ : state_machine_def<Sub1SM_> { 
     struct Started : state<> { template <class Event,class Fsm> void on_entry(const Event& e, Fsm&) const { std::cout << "SUB2SM_ Started::on_entry(): d1="<<e.d1 << std::endl; } }; 
     struct Exit : exit_pseudo_state<EvGotoSub2> {}; 
     using initial_state = mpl::vector<Started>; 
     struct transition_table:mpl::vector< 
     Row<Started, EvGotoSub2, Exit, none, none> 
     > {}; 
    }; 

    struct Sub2SM_ : state_machine_def<Sub2SM_> { 
     struct Started : state<> { template <class Event,class Fsm> void on_entry(const Event& e, Fsm&) const { std::cout << "SUB2SM_ Started::on_entry(): d2="<<e.d2 << std::endl; } }; 
     struct Exit : exit_pseudo_state<EvGotoSub1> {}; 
     using initial_state = mpl::vector<Started>; 
     struct transition_table:mpl::vector< 
     Row<Started, EvGotoSub1, Exit, none, none> 
     > {}; 
    }; 

    struct MainSM_ : state_machine_def<MainSM_> { 
     struct Started : state<> { }; 
     using initial_state = mpl::vector<Started>; 
     struct transition_table:mpl::vector< 
     Row<Started, EvGotoSub1, Sub1, none, none>, 
     Row<Started, EvGotoSub2, Sub2, none, none>, 
     Row<Sub2::exit_pt<Sub2SM_::Exit>, EvGotoSub1, Sub1, none, none>, 
     Row<Sub1::exit_pt<Sub1SM_::Exit>, EvGotoSub2, Sub2, none, none> 
     > {}; 
    }; 
} 


int main() { 

    Main main; 
    main.start(); 
    main.process_event(EvGotoSub1(0)); 
    main.process_event(EvGotoSub2(1)); 
    main.process_event(EvGotoSub1(2)); 
} 

Живой пример: http://coliru.stacked-crooked.com/a/d491442b38a24e82

Как вам может видеть, событие не утеряно, а переадресовано.

Хороший источник информации о состояниях псевдовыхода можно найти по адресу http://redboltz.wikidot.com/exit-point-pseudo-state.

+0

Да, ваши предположения верны. Это именно то, что я искал! – Kalle

Смежные вопросы