2

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.

Jens Müller
  • 302
  • 4
  • 13

1 Answers1

4

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

Daksh Gupta
  • 7,554
  • 2
  • 25
  • 36
  • Thanks for the good explanation. So I don't need to defer E3 again in S2, like struct S2 : sc::simple_state { typedef mpl::list< sc::transition, sc::deferral< E3 > > reactions; }; ? – Jens Müller Jan 03 '17 at 09:46
  • 1
    @Jens Muller : No, once deferred, the event remains in outside queue, which will be executed every time a new state transition happens. They will remain in queue till it handled by any one of the subsequent event handlers – Daksh Gupta Jan 03 '17 at 10:49
  • @DKG Suppose the order of events is E1, E3, E2. Then we are in S2 when we receive the E3 event. Is it deferred? If not, can E3 also be deferred in S2? – Gary Jackson Jul 24 '17 at 15:24
  • Answering my own question: The deferral of E3 in S2 is necessary if an E3 can arrive in S2. – Gary Jackson Jul 24 '17 at 16:52