【问题标题】:Boost MSM only processing internal transitionsBoost MSM 仅处理内部转换
【发布时间】:2011-04-25 13:28:25
【问题描述】:

我正在使用新的 Boost 1.44.0 MSM 库来生成状态机。在这个状态机中有两类事件class1class2class1 事件可以由状态S1S2 处理,而class2 事件只能由状态S2 处理。

一个特殊的class1 事件upgrade_req 请求从状态S1 升级到状态S2

我在 Boost::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

我的问题是,当我按原样使用它时,upgrade_req 事件永远不会被主MyFSM::transition_table 处理。它只被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 类事件。

有人对我如何解决此问题有建议吗?

谢谢, 保罗H

【问题讨论】:

    标签: c++ boost state-machine boost-msm


    【解决方案1】:

    您的问题是内部转换的优先级高于转换表中定义的优先级。并且 update_req 是一个 class1,内部转换触发。这实际上是符合 UML 标准的。 MSM 为您提供了第二个解决方案,您可以在transition_table 中定义S1 的内部转换,其中没有作为目标的Row,而不是使用internal_transition_table。如果您在转换 S1 + upgrade_reg -> S2 之前定义它,它将具有较小的优先级,并且只有在无法考虑另一个时才会尝试。

    如果你绝对需要一个 internal_transition_table,那么你只能提供一个保护来拒绝 class1,如果它不是 update_req。

    HTH, 克里斯托夫·亨利

    PS:我只是碰巧发现了这篇文章。发布到提升用户列表将保证您获得更快的答案。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-10-06
      • 2012-06-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多