Как выйти из автомата в иерархическом SM, который разбит на несколько файлов? (используя boost :: MSM)

Есть хороший учебник, который объясняет, как мы можем использовать «exit-pseudo-state» для выхода из автомата, используя boost::MSM, Вот.

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

Когда в главном файле fsm определена подсистема SM, все работает нормально, то есть выход из «псевдо-состояния выхода» приводит к выходу из подсистемы SM в следующее состояние (образец кода)

Реализация sub-SM в отдельном файле, где я должен сделать дополнительный уровень фиктивного наследования, вызывает проблемы.
На этот раз переход к псевдосостоянию выхода во внутренней подсистеме SM не приводит к выходу в следующее состояние в родительской SM. Вот пример кода, показывающий проблему

Как вы можете видеть из вывода ниже, State2::on_exit() отсутствует в конце после выхода из подсостояния21

Testing boost::msm ...
State1::on_entry()
State1::on_exit()
State2::on_entry()
SubState21::on_entry()
SubState21::on_exit()

заранее спасибо за помощь

Код в комплекте:

основной файл:

#include "myfsm.h"
int main()
{
std::cout << "Testing boost::msm ..." << std::endl;
MyFsm fsm;
fsm.start();

fsm.process_event(Event1());
fsm.process_event(Event3());
//fsm.process_event(Event2());
}

основной фсм:

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

#include "state2.h"#include "events.h"
namespace msm = boost::msm;
namespace msmf = boost::msm::front;
namespace mpl = boost::mpl;

struct MyFsm_ : msmf::state_machine_def<MyFsm_>
{
struct State1 : msmf::state<>{
template<class Event, class Fsm> void on_entry(const Event&, Fsm&) const {std::cout << "State1::on_entry()" << std::endl;}
template<class Event, class Fsm> void on_exit(const Event&, Fsm&) const {std::cout << "State1::on_exit()" << std::endl;}
};

struct State2m : State2 {};

// Set initial state
typedef State1 initial_state;

// Transition table
struct transition_table:mpl::vector<
msmf::Row < State1, Event1, State2m, msmf::none, msmf::none >,
msmf::Row < State2m, Event2, State1, msmf::none, msmf::none >,
msmf::Row < State2::exit_pt
<State2_::Exit2>, msmf::none, State1, msmf::none, msmf::none >
>{};

template<class Event, class Fsm>
void no_transition(Event const&, Fsm&, int state){
std::cout<<"no_transiton detected from state: "<< state << std::endl;
}

};
// Pick a back-end
typedef msm::back::state_machine<MyFsm_> MyFsm;

sub-SM, то есть state2.h:

#include <iostream>
#include <boost/msm/back/state_machine.hpp>
#include <boost/msm/front/state_machine_def.hpp>
#include <boost/msm/front/functor_row.hpp>
#include "events.h"
namespace msm = boost::msm;
namespace msmf = boost::msm::front;
namespace mpl = boost::mpl;struct State2_ : msmf::state_machine_def<State2_>{
template<class Event, class Fsm> void on_entry(const Event&, Fsm&) const {std::cout << "State2::on_entry()" << std::endl;}
template<class Event, class Fsm> void on_exit(const Event&, Fsm&) const {std::cout << "State2::on_exit()" << std::endl;}

struct SubState21 : msmf::state<>{
template<class Event, class Fsm> void on_entry(const Event&, Fsm&) const {std::cout << "SubState21::on_entry()" <<std::endl;}
template<class Event, class Fsm> void on_exit(const Event&, Fsm&) const {std::cout << "SubState21::on_exit()" << std::endl;}
};
typedef mpl::vector<SubState21> initial_state;
struct Exit2 : msmf::exit_pseudo_state<msmf::none> {};

struct transition_table:mpl::vector<
msmf::Row < SubState21, Event3, Exit2, msmf::none, msmf::none >
>{};

};
typedef msm::back::state_machine<State2_> State2;

0

Решение

Вам нужно определить msm::back::state_machine в вне из msmf::state_machine_def,

Вот обновленная версия вашего примера:

https://wandbox.org/permlink/DktAL169yjFNnmfl

Есть четыре обновленных пункта.

В state2.h (1)

// 1. move msm::back::state_machine to fsm
// typedef msm::back::state_machine<State2_> State2;

В myfsm.h (2, 3, 4)

struct State2m : State2_ {}; // 2. replaced State2 to State2_
typedef msm::back::state_machine<State2m> State2mm; // 3. define backend here// Transition table
struct transition_table:mpl::vector<
// 4. updated transition table using State2mm
msmf::Row < State1, Event1, State2mm, msmf::none, msmf::none >,
msmf::Row < State2mm, Event2, State1, msmf::none, msmf::none >,
msmf::Row < State2mm::exit_pt
<State2mm::Exit2>, msmf::none, State1, msmf::none, msmf::none >
>{};

В этом случае вы можете сделать более элегантный способ. Вы можете удалить struct State2m : State2_ {}; наследование.

Вот код:

https://wandbox.org/permlink/FO7lEELLtLhiismu

Вы можете определить State2 как следует и использовать State2 в таблице переходов.

typedef msm::back::state_machine<State2_> State2;

// Transition table
struct transition_table:mpl::vector<
msmf::Row < State1, Event1, State2, msmf::none, msmf::none >,
msmf::Row < State2, Event2, State1, msmf::none, msmf::none >,
msmf::Row < State2::exit_pt
<State2::Exit2>, msmf::none, State1, msmf::none, msmf::none >
>{};
1

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector