从子状态机延迟事件
Deferring events from sub state machine
在我的项目中,有一个使用boost元状态机实现的状态机。这个主状态机,有一个状态(为了简单起见,我们称之为SubMachineEntry
)代表一个子状态机的入口点:
namespace msmf = boost::msm::front;
namespace msmb = boost::msm::back;
...
msmf::Row < SomeState, enterSub, SubMachineEntry, msmf::none, msmf::none >
...
using SubMachine = msmb::state_machine<SubMachine_>;
这个子状态机执行一些处理,然后我们回到外部状态机,状态
using SubMachineFinished = SubMachine::exit_pt<...>;
,表示子机退出状态。我的问题是,在子状态机退出之前,可能会调度某个事件(toProcessInOuter
),并且应该在子状态机退出后在外部状态机中处理。将该事件在子状态机的所有状态中都延迟是行不通的,它不会传播到 SubMachineFinished
之后的状态。有没有一种方法可以使用 boost MSM 的某种机制来实现这种事件转发,而无需使用某些自定义解决方法?
不幸的是,子机器上的延迟事件无法在 MSM 上的父状态机上进行评估。所以需要在parent state写defer transition
事件从内部状态机评估到外部状态机。如果要延迟事件,可以在父状态中编写延迟转换。
我写了演示它的例子。
见附图。假设 Event2
是您要推迟的事件。您需要将延迟转换写入 State1
。
完整代码如下:
#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 msm = boost::msm;
namespace msmf = boost::msm::front;
namespace mpl = boost::mpl;
// ----- Events
struct Event1 {};
struct Event2 {};
// ----- State machine
struct OuterSm_:msmf::state_machine_def<OuterSm_> {
struct State1_:msmf::state_machine_def<State1_> {
template <class Event,class Fsm>
void on_entry(Event const&, Fsm&) const {
std::cout << "State1::on_entry()" << std::endl;
}
template <class Event,class Fsm>
void on_exit(Event const&, Fsm&) const {
std::cout << "State1::on_exit()" << std::endl;
}
struct SubState1:msmf::state<> {
template <class Event,class Fsm>
void on_entry(Event const&, Fsm&) const {
std::cout << "SubState1::on_entry()" << std::endl;
}
template <class Event,class Fsm>
void on_exit(Event const&, Fsm&) const {
std::cout << "SubState1::on_exit()" << std::endl;
}
};
template <class Fsm,class Event>
void no_transition(Event const& e, Fsm& ,int state) {
std::cout << "No handled event in InnerSm " << typeid(e).name() << " on State " << state << std::endl;
}
struct Exit1:msmf::exit_pseudo_state<msmf::none> {};
// Set initial state
typedef mpl::vector<SubState1> initial_state;
// Transition table
struct transition_table:mpl::vector<
// Start Event Next Action Guard
msmf::Row < SubState1, Event1, Exit1, msmf::none, msmf::none >
> {};
};
struct State2:msmf::state<> {
template <class Event,class Fsm>
void on_entry(Event const&, Fsm&) const {
std::cout << "State2::on_entry()" << std::endl;
}
template <class Event,class Fsm>
void on_exit(Event const&, Fsm&) const {
std::cout << "State2::on_exit()" << std::endl;
}
};
template <class Fsm,class Event>
void no_transition(Event const& e, Fsm& ,int state) {
std::cout << "No handled event in OuterSm " << typeid(e).name() << " on State " << state << std::endl;
}
typedef msm::back::state_machine<State1_> State1;
// Actions
struct Action {
template <class Event, class Fsm, class SourceState, class TargetState>
void operator()(Event const&, Fsm&, SourceState&, TargetState&) const {
std::cout << "Action()" << std::endl;
}
};
// enable deferred events
typedef int activate_deferred_events;
// Set initial state
typedef State1 initial_state;
// Transition table
struct transition_table:mpl::vector<
// Start Event Next Action Guard
msmf::Row < State1::exit_pt
<State1_::Exit1>, msmf::none, State2, msmf::none, msmf::none >,
msmf::Row < State1, Event2, msmf::none, msmf::Defer, msmf::none >,
msmf::Row < State2, Event2, msmf::none, Action, msmf::none >
> {};
};
// Pick a back-end
typedef msm::back::state_machine<OuterSm_> Osm;
int main() {
Osm osm;
osm.start();
std::cout << "> Send Event2()" << std::endl;
osm.process_event(Event2());
std::cout << "> Send Event1()" << std::endl;
osm.process_event(Event1());
return 0;
}
在我的项目中,有一个使用boost元状态机实现的状态机。这个主状态机,有一个状态(为了简单起见,我们称之为SubMachineEntry
)代表一个子状态机的入口点:
namespace msmf = boost::msm::front;
namespace msmb = boost::msm::back;
...
msmf::Row < SomeState, enterSub, SubMachineEntry, msmf::none, msmf::none >
...
using SubMachine = msmb::state_machine<SubMachine_>;
这个子状态机执行一些处理,然后我们回到外部状态机,状态
using SubMachineFinished = SubMachine::exit_pt<...>;
,表示子机退出状态。我的问题是,在子状态机退出之前,可能会调度某个事件(toProcessInOuter
),并且应该在子状态机退出后在外部状态机中处理。将该事件在子状态机的所有状态中都延迟是行不通的,它不会传播到 SubMachineFinished
之后的状态。有没有一种方法可以使用 boost MSM 的某种机制来实现这种事件转发,而无需使用某些自定义解决方法?
不幸的是,子机器上的延迟事件无法在 MSM 上的父状态机上进行评估。所以需要在parent state写defer transition
事件从内部状态机评估到外部状态机。如果要延迟事件,可以在父状态中编写延迟转换。 我写了演示它的例子。
见附图。假设 Event2
是您要推迟的事件。您需要将延迟转换写入 State1
。
完整代码如下:
#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 msm = boost::msm;
namespace msmf = boost::msm::front;
namespace mpl = boost::mpl;
// ----- Events
struct Event1 {};
struct Event2 {};
// ----- State machine
struct OuterSm_:msmf::state_machine_def<OuterSm_> {
struct State1_:msmf::state_machine_def<State1_> {
template <class Event,class Fsm>
void on_entry(Event const&, Fsm&) const {
std::cout << "State1::on_entry()" << std::endl;
}
template <class Event,class Fsm>
void on_exit(Event const&, Fsm&) const {
std::cout << "State1::on_exit()" << std::endl;
}
struct SubState1:msmf::state<> {
template <class Event,class Fsm>
void on_entry(Event const&, Fsm&) const {
std::cout << "SubState1::on_entry()" << std::endl;
}
template <class Event,class Fsm>
void on_exit(Event const&, Fsm&) const {
std::cout << "SubState1::on_exit()" << std::endl;
}
};
template <class Fsm,class Event>
void no_transition(Event const& e, Fsm& ,int state) {
std::cout << "No handled event in InnerSm " << typeid(e).name() << " on State " << state << std::endl;
}
struct Exit1:msmf::exit_pseudo_state<msmf::none> {};
// Set initial state
typedef mpl::vector<SubState1> initial_state;
// Transition table
struct transition_table:mpl::vector<
// Start Event Next Action Guard
msmf::Row < SubState1, Event1, Exit1, msmf::none, msmf::none >
> {};
};
struct State2:msmf::state<> {
template <class Event,class Fsm>
void on_entry(Event const&, Fsm&) const {
std::cout << "State2::on_entry()" << std::endl;
}
template <class Event,class Fsm>
void on_exit(Event const&, Fsm&) const {
std::cout << "State2::on_exit()" << std::endl;
}
};
template <class Fsm,class Event>
void no_transition(Event const& e, Fsm& ,int state) {
std::cout << "No handled event in OuterSm " << typeid(e).name() << " on State " << state << std::endl;
}
typedef msm::back::state_machine<State1_> State1;
// Actions
struct Action {
template <class Event, class Fsm, class SourceState, class TargetState>
void operator()(Event const&, Fsm&, SourceState&, TargetState&) const {
std::cout << "Action()" << std::endl;
}
};
// enable deferred events
typedef int activate_deferred_events;
// Set initial state
typedef State1 initial_state;
// Transition table
struct transition_table:mpl::vector<
// Start Event Next Action Guard
msmf::Row < State1::exit_pt
<State1_::Exit1>, msmf::none, State2, msmf::none, msmf::none >,
msmf::Row < State1, Event2, msmf::none, msmf::Defer, msmf::none >,
msmf::Row < State2, Event2, msmf::none, Action, msmf::none >
> {};
};
// Pick a back-end
typedef msm::back::state_machine<OuterSm_> Osm;
int main() {
Osm osm;
osm.start();
std::cout << "> Send Event2()" << std::endl;
osm.process_event(Event2());
std::cout << "> Send Event1()" << std::endl;
osm.process_event(Event1());
return 0;
}