私はシンプルなステートマシンを持っており、3種類のメッセージを受信し、メッセージの種類によって応答を送信します。正常な状態で正しいメッセージが正しい順序で受信された場合、私の状態マシンは完璧に動作します。ブーストmsmのエラー処理でエラーが発生しました
しかし、予期しないメッセージを受信した場合には、no_transition
がnormal_workflow
状態によって処理されなければならないerror_detected
イベントを、発火しなければならない、と呼ばれています。しかし、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());
}
}