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;
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:
1) The data example demonstrates a way to get the on_entry and on_ext part 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.
2) The *initial + sml::event<ev_transit> = nested, entry in the transition table can be augmented to repost ev_transit, then a new entry in the sml_sub_ can react to this and perform the initialisation. Works well for emulating on_entry but I can't figure out a similar trick for on_exit
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
andon_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
Running
gives
My initial attempt at implementing this in SML is
As you can see I don't know how to access
msm_sm_::i
from the entry\exit actions.Some workarounds I've tried:
1) The data example demonstrates a way to get the
on_entry
andon_ext
part 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.
2) 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_entry
but I can't figure out a similar trick foron_exit
Here is a file with both machine implementations sml_nested_machine_data.txt