2010-10-14 70 views
5

我正在使用新的Boost 1.44.0 MSM庫來生成狀態機。在這個狀態機中有兩類事件class1class2class1事件可以由狀態S1S2進行處理,而class2事件只能由狀態S2進行處理。提升MSM只處理內部轉換

一個特殊的class1事件upgrade_req請求從狀態S1升級到狀態S2

,我實現了在升壓:: MSM如下:

// State S1 and S2 allow any class1 events 
struct class1 {}; 
// Only state S2 allows class2 events 
struct class2 {}; 

// an upgrade request is a class1 event that requests an upgrade to state 2 
struct upgrade_req : public class1 {}; 

struct MyFSM : public msm::front::state_machine_def<MyFSM> 
{ 
    /// State 1. Allows any class1 event 
    struct S1 : public msm::front::state<> 
    { 
     /// functor says "processing event in State 1" 
     struct ProcessEvent { /* ... */ }; 

     struct internal_transition_table : mpl::vector< 
      //  Event Action  Guard 
      //  +-------+-------------+------------+ 
      Internal< class1, ProcessEvent, none > 
     > {}; 
    }; // S1 

    /// State 2. Allows any class1 or class2 events 
    struct S2 : public msm::front::state<> 
    { 
     /// functor says "processing event in State 2" 
     struct ProcessEvent { /* ... */ }; 

     struct internal_transition_table : mpl::vector< 
      //  Event Action  Guard 
      //  +-------+-------------+------------+ 
      Internal< class1, ProcessEvent, none >, 
      Internal< class2, ProcessEvent, none > 
     > {}; 
    }; // S2 

    /// everybody starts in state 1 
    typedef S1 initial_state; 

    /// send an error if a class2 event was received for state1 
    struct SendError { /* ... */ }; 

    /// Send a response to the upgrade request 
    struct SendUpgradeRsp { /* ... */ }; 

    /// functor returns true if the request to upgrade to state 2 is OK. 
    struct VerifyUpgradeReq { /* ... */ }; 

    struct transition_table : mpl::vector< 
     // Start Event   Next Action   Guard 
     // +------+-------------+------+----------------+------------------+ 
     Row< S1, class1,  none, none,   none, 
     Row< S1, class2,  S1, SendError,  none >, 
     Row< S1, upgrade_req, S2, SendUpgradRsp, VerifyUpgradeReq >, 

     Row< S2, class1,  none, none,   none, 
     Row< S2, class2,  none, none,   none > 
    > {}; 
}; // MyFSM 

我的問題是,當我用這個,因爲它是永遠不會被主MyFSM::transition_table處理upgrade_req事件。它只能由S1::internal_transition_table處理。

例如:

int main(int argc, char* argv[]) 
{ 
    msm::back::state_machine<MyFSM> sm; 
    sm.start(); 
    sm.process_event(class1()); 
    sm.process_event(upgrade_req()); 
    sm.process_event(class2()); 
    return 0; 
} 

我就是願意這樣做的輸出是:在國家

處理事件1.
升級請求確定。在國家2.

但是,
處理事件我所得到的是這樣的:在國家1
處理事件

處理事件的國家1.
錯誤。收到狀態1中的第2類事件。

有沒有人有關於如何解決此問題的建議?

感謝, PaulH

回答

5

您的問題是內部轉換的優先級比那些在過渡表中定義更高。並且update_req是一個class1,內部transiton觸發。這實際上符合UML標準。 MSM爲您提供了第二種解決方案,您可以使用行中的none作爲transition_table中的目標行來定義S1的內部轉換,而不是使用internal_transition_table。如果在轉換S1 + upgrade_reg - > S2之前定義它,它將有一個較小的prio,並且只有在另一個不能被考慮時纔會嘗試。

如果你絕對需要一個internal_transition_table,那麼你只能提供一個警衛來拒絕class1,如果它不是update_req。

HTH, 克里斯托夫·亨利

PS:我只找到這個帖子靠運氣。發佈到提升用戶列表可以保證你得到更快的答案。