Повышение MSM только обработка внутренних переходов - PullRequest
5 голосов
/ 14 октября 2010

Я использую новую библиотеку Boost 1.44.0 MSM для создания конечного автомата. В этом автомате есть два класса событий class1 и class2. События class1 могут обрабатываться состояниями S1 или S2, а события 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.
Ошибка. Получено событие класса 2 в государстве 1.

У кого-нибудь есть предложения, как мне решить эту проблему?

Спасибо, PaulH

1 Ответ

5 голосов
/ 03 ноября 2010

Ваша проблема в том, что приоритет внутренних переходов выше, чем те, которые определены в таблице переходов.И update_req, являющийся class1, внутренний транзит срабатывает.Это на самом деле соответствует стандарту UML.MSM предлагает вам второе решение, вы можете определить внутренний переход S1 со строкой, в которой ни один не будет являться целью внутри transition_table вместо использования internal_transition_table.Если вы определите его ДО перехода S1 + upgrade_reg -> S2, он будет иметь меньший приоритет и будет пробоваться только в том случае, если другой не может рассматриваться.охранник, чтобы отклонить class1, если это не update_req.

HTH, Кристоф Генри

PS: Я нашел этот пост только по счастливой случайности.Публикация в расширенном списке пользователей гарантирует вам гораздо более быстрый ответ.

...