2012-04-27 42 views
2

私はシンプルなステートマシンを持っており、3種類のメッセージを受信し、メッセージの種類によって応答を送信します。正常な状態で正しいメッセージが正しい順序で受信された場合、私の状態マシンは完璧に動作します。ブーストmsmのエラー処理でエラーが発生しました


しかし、予期しないメッセージを受信した場合には、no_transitionnormal_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()); 
    } 
} 

答えて

1

まあ、IMHO、直交領域の使用は良いです。ただし、エラー処理のイベントは、依然として自分で実行する必要があります。 no_transitionは、MSMが間違っている場合の唯一の機能です。あなたと同じようにやっています。

関連する問題