2010-10-14 10 views
5

Estoy utilizando la nueva biblioteca Boost 1.44.0 MSM para producir una máquina de estados. En esta máquina de estados existen dos clases de eventos class1 y class2. Los eventos class1 pueden procesarse en cualquiera de los estados S1 o S2, mientras que los eventos class2 solo pueden ser procesados ​​por el estado S2.Boost MSM solo procesa las transiciones internas

Un evento especial class1upgrade_req solicita una actualización del estado S1 al estado S2.

que he implementado en Boost :: HSH de la siguiente manera:

// 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 

Mi problema es que cuando se utiliza esto como es, el evento upgrade_req no es procesada por el principal MyFSM::transition_table. Solo es procesado por S1::internal_transition_table.

Por ejemplo:

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; 
} 

que desearía la salida de este ser: caso

procesamiento en el estado 1.
actualización Solicitud OK.
caso procesamiento en el estado 2.

Pero, lo que me pasa es esto: acontecimiento

procesamiento en el estado 1.
evento de procesamiento en el estado 1.
error. Recibido clase 2 eventos en el estado 1.

¿Alguien tiene una sugerencia sobre cómo puedo solucionar este problema?

Gracias, PaulH

Respuesta

5

su problema es que la prioridad de las transiciones internas es mayor que los definidos en la tabla de transición. Y update_req es una clase 1, el transiton interno se dispara. Esto es realmente conforme al estándar UML. MSM le ofrece una segunda solución, puede definir la transición interna de S1 con una fila sin ninguna como destino dentro de la tabla de transición en lugar de usar una tabla_transición_interno. Si lo define ANTES de la transición S1 + upgrade_reg -> S2, tendrá un prio menor y se probará solo si el otro no se puede considerar.

Si necesita absolutamente una internal_transition_table, solo puede proporcionar un guardia para rechazar class1 si no es un update_req.

HTH, Christophe Henry

PD: Sólo he encontrado este post por la suerte. Publicar en la lista de usuarios de boost le garantizará una respuesta mucho más rápida.

Cuestiones relacionadas