2010-10-14 82 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:我只找到这个帖子靠运气。发布到提升用户列表可以保证你得到更快的答案。