How to access data members in a submachine when entering & exiting and from it's substates
Sorry in advance for the the long code example, I felt I could better explain my goal in code rather than words. I want to store some data in a submachine and use on_entry and on_exit for initialisation and clean-up respectively, and crucially I would like to be able to access that data from substates of the submachine.
Here is a small pair of MSM statemachines which show what I'm trying to achieve
struct ev_transit {
int i;
};
struct ev_act {};
struct ev_exit {};
struct msm_sm_sub_ : public msmf::state_machine_def<msm_sm_sub_> {
struct nested : msm::front::state<> {};
typedef nested initial_state;
template <class Event, class Fsm>
void on_entry(Event const& e, Fsm& f) {
std::cout << "Enter sub machine, i = " << e.i <<std::endl;
i = e.i;
}
template <class Event, class Fsm>
void on_exit(Event const& e, Fsm& f) {
std::cout << "Exit sub machine, i = " << i <<std::endl;
i = 0;
}
struct actions {
template <class Event, class Fsm>
void operator()(const Event& c, Fsm& m, nested& s, nested&) {
std::cout << "Action in nested state, i = " << m.i << std::endl;
}
};
struct transition_table : mpl::vector<
msmf::Row<nested, ev_act, nested, actions, msmf::none>
> {};
int i;
};
using msm_sm_sub = msm::back::state_machine<msm_sm_sub_>;
struct msm_sm_ : msmf::state_machine_def<msm_sm_> {
struct intital : msmf::state<> {};
typedef intital initial_state;
struct transition_table:mpl::vector<
msmf::Row<intital, ev_transit, msm_sm_sub, msmf::none, msmf::none >,
msmf::Row<msm_sm_sub, ev_exit, intital, msmf::none, msmf::none >
> {};
};
typedef msm::back::state_machine<msm_sm_> msm_sm;
Running
msm_sm foo;
foo.process_event(ev_transit{42});
foo.process_event(ev_act{});
foo.process_event(ev_exit{});
gives
Enter sub machine, i = 42
Action in nested state, i = 42
Exit sub machine, i = 42
My initial attempt at implementing this in SML is
struct sml_sub_ {
auto operator()() noexcept {
const auto nested = sml::state<struct nested_>;
const auto nested_act = [this]() {
std::cout << "Action in nested state, i = " << i << std::endl;
};
return sml::make_transition_table (
*nested + sml::event<ev_act> / nested_act
);
}
int i;
};
struct sml_sm {
auto operator()() noexcept {
const auto initial = sml::state<struct initial_>;
const auto nested = sml::state<sml_sub_>;
auto enter_sub = [](const ev_transit& e) {
std::cout << "Enter sub machine, i = " << e.i <<std::endl;
// i = e.i; // ? Any way to access msm_sm_::i
};
auto exit_sub = []() {
std::cout << "Exit sub machine" << std::endl;
// i = 0;
};
return sml::make_transition_table (
*initial + sml::event<ev_transit> = nested,
nested + sml::on_entry<ev_transit> / enter_sub,
nested + sml::on_exit<sml::_> / exit_sub,
nested + sml::event<ev_exit> = initial
);
}
};
As you can see I don't know how to access msm_sm_::i from the entry\exit actions.
Some workarounds I've tried:
- The data example demonstrates a way to get the
on_entryandon_extpart working, but that data is then stored in the outer state machine and inaccessible to sub states of the submachine.
Also it would be preferable to be able to store the data and the entry/exit login in the submachine for organisational reason, but this is hardly a deal breaker.
- The
*initial + sml::event<ev_transit> = nested,entry in the transition table can be augmented to repostev_transit, then a new entry in thesml_sub_can react to this and perform the initialisation. Works well for emulatingon_entrybut I can't figure out a similar trick foron_exit
Here is a file with both machine implementations sml_nested_machine_data.txt
Hi. Was this issue resolved? thanks