我尝试使用boost :: MSM来实现一个简单的状态机以进行测试。有几个事件必须按正确的顺序处理,所以我推迟了其他事件,这些事件目前是不允许的。我尝试推迟转换表中的事件,有一个地方可以查找它,尽管要查看所有状态,他们推迟了什么事件。
我尝试更改转换行以更改其优先级,但它没有帮助。如果我取消从live_got_image到live_wait_for_image的匿名转换,它会按预期工作,但我想自动转换为重复进入状态live_wait_for_image / live_got_image,直到ev_stop_live被发送。
我期待以下输出:
entering: fsm_master
entering: not_ready
no transition from state 0 on event struct `anonymous namespace'::ev_stop_live
leaving: not_ready
starting: live_wait_for_image
leaving: live_wait_for_image
starting: live_got_image
leaving: live_got_image
entering: not_ready
但实际上我得到以下输出:
entering: fsm_master
entering: not_ready
no transition from state 0 on event struct `anonymous namespace'::ev_stop_live
leaving: not_ready
starting: live_wait_for_image
leaving: live_wait_for_image
starting: live_got_image
leaving: live_got_image
starting: live_wait_for_image
我使用boost 1.57.0和MSVC-2013(VS-12)。
有人能给我一个有用的提示吗?
乔治
以下是代码:
#include <iostream>
// back-end
#include <boost/msm/back/state_machine.hpp>
//front-end
#include <boost/msm/front/state_machine_def.hpp>
#include <boost/msm/front/functor_row.hpp>
namespace msm = boost::msm;
namespace mpl = boost::mpl;
namespace
{
using namespace boost::msm::front;
// events
struct ev_start_stop {};
struct ev_start_live {};
struct ev_stop_live {};
struct ev_learn {};
struct ev_load {};
struct ev_got_image { int payload; };
// front end: define the FSM structure
struct fsm_master_ : public msm::front::state_machine_def<fsm_master_> {
typedef int activate_deferred_events;
template <class Event, class FSM>
void on_entry(Event const&, FSM&)
{
std::cout << "entering: fsm_master" << std::endl;
}
template <class Event, class FSM>
void on_exit(Event const&, FSM&)
{
std::cout << "leaving: fsm_master" << std::endl;
}
// the fsm states which are not sub state machines
struct not_ready : public msm::front::state<> {
template <class Event, class FSM>
void on_entry(Event const&, FSM&) { std::cout << "entering: not_ready" << std::endl; }
template <class Event, class FSM>
void on_exit(Event const&, FSM&) { std::cout << "leaving: not_ready" << std::endl; }
};
// The list of FSM states
struct live_wait_for_image : public msm::front::state<>
{
template <class Event, class FSM>
void on_entry(Event const&, FSM&) { std::cout << "starting: live_wait_for_image" << std::endl; }
template <class Event, class FSM>
void on_exit(Event const&, FSM&) { std::cout << "leaving: live_wait_for_image" << std::endl; }
};
struct live_got_image : public msm::front::state<>
{
// here we got the image and we can check, if we need to react on an external event
// otherwise transit to wait_for_image and fetch the next image
template <class Event, class FSM>
void on_entry(Event const&, FSM&) { std::cout << "starting: live_got_image" << std::endl; }
template <class Event, class FSM>
void on_exit(Event const&, FSM&) { std::cout << "leaving: live_got_image" << std::endl; }
};
// ---------------------------------------------------
// initial state: fsm_master_
typedef not_ready initial_state;
typedef fsm_master_ l;
struct transition_table : mpl::vector<
// Start Event Next Action Guard
// +---------------------+----------------+-------------------+-------------------+----------------+
_row < not_ready, ev_start_live, live_wait_for_image >,
_row < live_wait_for_image, ev_got_image, live_got_image >,
Row < live_wait_for_image, ev_stop_live, none , Defer , none >,
_row < live_got_image, none, live_wait_for_image >,
_row < live_got_image, ev_stop_live, not_ready >
// +---------------------+----------------+-------------------+-------------------+----------------+
> {};
// Replaces the default no-transition response.
template <class FSM, class Event>
void no_transition(Event const& e, FSM&, int state)
{
std::cout << "no transition from state " << state
<< " on event " << typeid(e).name() << std::endl;
}
};
// back-end: fsm_master
typedef msm::back::state_machine<fsm_master_> fsm_master;
}
void test() {
fsm_master s;
s.start();
s.process_event(ev_stop_live()); // this gets no transitioned
s.process_event(ev_start_live()); // this one enters live
s.process_event(ev_stop_live()); // this gets defered
s.process_event(ev_got_image()); // this one enters got_image and the stop live should get processed.
// now we should be in not ready again, but we are still in live_wait_for_image
}
int main()
{
test();
return 0;
}
答案 0 :(得分:1)
我从Christophe的邮件列表中得到了以下答案:
您好,
我尝试使用boost :: MSM来实现一个简单的状态机进行测试 目的。有几个事件必须在右边处理 订单,所以我推迟了目前不允许的其他事件。我试试 推迟转换表中的事件,有一个地方可以查找 尽管有所有州看,但他们推迟了什么事。
我尝试更改转换行以更改其优先级,但它 没有帮助。如果我解开从live_got_image到的匿名过渡 live_wait_for_image,它按预期工作,但我想转换 自动重复进入状态 live_wait_for_image / live_got_image,直到ev_stop_live被发送。
我担心它不起作用。根据MSM试图遵循的UML标准,匿名转换具有比延迟事件更高的优先级。如果队列中有延迟事件,您可以在匿名转换中使用保护来禁用它,例如:
struct OnlyIfNoDeferred
{
template<class Event, class Fsm, class SourceState, class TargetState>
bool operator()(Event const &, Fsm & aFsm, SourceState &, TargetState &)
{
return aFsm.get_deferred_queue().empty();
}
};
当我们谈论匿名过渡时,我会反复阅读,但请注意不要添加另一个匿名过渡,否则你可能会进入无限循环的匿名过渡。
HTH,