2
我有一個簡單的狀態機,它接收3種類型的消息,並根據消息類型它發送相應的響應。在正常情況下,當正確的消息以正確的順序接收時,我的狀態機工作正常。錯誤處理在升壓msm
但對於在受到意外的消息的情況下,no_transition
被調用,它必須火error_detected
事件,必須由normal_workflow
狀態進行處理。但是no_transition
被稱爲2次,因爲有2個正交區域。但是隻在normal_workflow
的情況下需要火災error_detected
事件。那麼如何確定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());
}
}