Search code examples
c++boostboost-statechart

Multiple deferred events in Boost Statechart


How do multiple deferred events behave in Boost Statechart?

Let's say I have 4 states and 3 events. The non-deferred transitions looks as follows:

S1--(E1)-->S2--(E2)-->S3--(E3)-->S4

The state machine starts in S1. Now events are posted in the following order: E2, E3, E1.

I want the state machine to reach S4 as a result of this sequence of events. What do I have to do in order to achieve this?

  • I obviously have to defer E2 and E3 in S1.
  • I probably also have to defer E3 in S2? I guess otherwise it will be discarded when S2 is reached.

I assume this part of the documentation: http://www.boost.org/doc/libs/1_55_0/libs/statechart/doc/reference.html#process_event contains the answer, but it is very technical (rather a description of the implementation than of the semantics -- the tutorial is not clearer either), and contains lots of references, so it is hard to know for sure.


Solution

  • You need to use sc::deferral to achieve the same. What you want to do can be achieved via following code.

    // States
    struct S1;
    struct S2;
    struct S3;
    struct S4;
    
    
    // Events
    struct E1 : sc::event<E1> {};
    struct E2 : sc::event<E2> {};
    struct E3 : sc::event<E3> {};
    
    struct statemachine : sc::state_machine<statemachine, S1>{};
    
    struct S1 : sc::simple_state<S1, statemachine> {
        typedef mpl::list<
            sc::transition< E1, S2 >,
            sc::deferral< E2 >,
            sc::deferral< E3 >
        > reactions;
    
    };
    
    struct S2 : sc::simple_state<S2, statemachine> {
        typedef sc::transition<E2, S3> reactions;
    };
    
    struct S3 : sc::simple_state<S3, statemachine> {
        typedef sc::transition<E3,S4> reactions;
    };
    
    struct S4 : sc::simple_state<S4, statemachine> {
    };
    
    int main() {
        statemachine sm;
        sm.initiate();
    // Event Sequence E2 -> E3 -> E1
        sm.process_event(E2());
        sm.process_event(E3());
        sm.process_event(E1());
        return 0;
    }
    

    In STATE "S1" , we deferred handling of Events "E2" and "E3" which is subsequently handled in STATE "S2" and "S3"

    Hope its clear..

    Note: you need to add a header file #include <boost/statechart/deferral.hpp> for using sc::deferral