2012-04-27 38 views
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()); 
    } 
} 

回答

1

那麼,恕我直言,正交區的使用是好的。但是,錯誤處理事件仍然需要由您自己解決。當MSM出錯時,no_transition是唯一的功能。所以,我的做法與你做的一樣。