我有一个简单的状态机,它接收 3 种类型的消息,并根据消息类型发送相应的响应。在正常情况下,当以正确的顺序接收到正确的消息时,我的状态机运行良好。
但是在收到意外消息的情况下,no_transition
调用它必须触发 error_detected
事件,必须由normal_workflow
状态处理。但是no_transition
被称为 2 次,因为有 2 个正交区域。但我只需要在状态的情况下发生火灾error_detected
事件normal_workflow
。那么如何确定当前的活动状态no_trasition
呢?这是我的代码,
#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 <boost/msm/front/euml/common.hpp>
#include <boost/msm/front/euml/operator.hpp>
#include <boost/msm/front/euml/state_grammar.hpp>
namespace msm = boost::msm;
namespace mpl = boost::mpl;
using namespace msm::front;
using namespace msm::front::euml;
namespace
{
// events
//
struct received_type_1_msg { received_type_1_msg(){ std::cout << "received_type_1_msg" << std::endl; } };
struct received_type_2_msg { received_type_2_msg(){ std::cout << "received_type_2_msg" << std::endl; } };
struct received_type_3_msg { received_type_3_msg(){ std::cout << "received_type_3_msg" << std::endl; } };
struct err_detected { err_detected(){ std::cout << "err_detected" << std::endl; } };
// front end
//
struct test_sm_ : public msm::front::state_machine_def<test_sm_>
{
// states
//
struct idle : public msm::front::state<>
{
template <class event,class fsm>
void on_entry(event const& evt,fsm& sm)
{
std::cout << "idle" << std::endl;
}
};
struct wait_type_2_msg : public msm::front::state<>
{
template <class event,class fsm>
void on_entry(event const& evt,fsm& sm)
{
std::cout << "wait_type_1_msg"<< std::endl;
}
};
struct wait_type_3_msg : public msm::front::state<>
{
template <class event,class fsm>
void on_entry(event const& evt,fsm& sm)
{
std::cout << "wait_type_3_msg"<< std::endl;
}
};
struct normal_workflow : public msm::front::state<>
{
template <class event,class fsm>
void on_entry(event const& evt,fsm& sm)
{
std::cout << "normal_workflow"<< std::endl;
}
};
// initial state
//
typedef mpl::vector2<idle, normal_workflow> initial_state;
// transition actions
//
struct send_type_1_rsp
{
template<class event, class fsm, class src_state, class dst_state>
void operator()(event const& evt, fsm&, src_state&, dst_state&)
{
std::cout << "send_type_1_rsp"<< std::endl;
}
};
struct send_type_2_rsp
{
template<class event, class fsm, class src_state, class dst_state>
void operator()(event const& evt, fsm&, src_state&, dst_state&)
{
std::cout << "send_type_2_rsp"<< std::endl;
}
};
struct send_type_3_rsp
{
template<class event, class fsm, class src_state, class dst_state>
void operator()(event const& evt, fsm&, src_state&, dst_state&)
{
std::cout << "send_type_3_rsp"<< std::endl;
}
};
struct send_error_rsp
{
template<class event, class fsm, class src_state, class dst_state>
void operator()(event const& evt, fsm&, src_state&, dst_state&)
{
std::cout << "send_error_rsp"<< std::endl;
}
};
struct transition_table : mpl::vector<
// Start Event Next Action Guard
// +---------------------------+-------------------------------+---------------------------+------------------------------+--------+
Row < idle , received_type_1_msg , wait_type_2_msg , send_type_1_rsp , none >,
Row < wait_type_2_msg , received_type_2_msg , wait_type_3_msg , send_type_2_rsp , none >,
Row < wait_type_3_msg , received_type_3_msg , idle , send_type_3_rsp , none >,
// +---------------------------+-------------------------------+---------------------------+------------------------------+--------+
Row < normal_workflow , err_detected , idle , send_error_rsp , none >
// +---------------------------+-------------------------------+---------------------------+------------------------------+--------+
>{};
// no transition
//
template <class fsm,class event>
void no_transition(event const& e, fsm& sm,int state)
{
std::cout << "no transition" << std::endl;
//sm.process_event(err_detected());
}
};
typedef msm::back::state_machine<test_sm_> test_sm;
}
int main(int argc, char** argv)
{
test_sm sm;
sm.start();
sm.process_event(received_type_1_msg());
sm.process_event(received_type_2_msg());
// wrong message received
//
sm.process_event(received_type_2_msg());
return 0;
}
一种解决方案是通过使用传递给no_transition
. 还有其他解决方案吗?因为这样的东西看起来不太好:
template <class fsm,class event>
void no_transition(event const& e, fsm& sm,int state)
{
// without this condition err_detected event will fired twise, because sm have 2 regions
//
if(state == 3)
{
// call this event only in NORMAL_WORKFLOW state, because it handled within this state
//
sm.process_event(err_detected());
}
}