[Statechart] Order of Trigger/Event/Guard at state transition
Hi all, I've tried to use the Statechart library for modelling a simple state machine. I've created three states and three transitions between them and added some debug outputs. When I've looked to the debug outputs I've wondered a little bit. I've thought that the processing of events are in the order 1) exit actions of source state 2) transition actions and 3) entry actions of target state. When I look at my result I see the order 1) transition action 2) exit action of source state and 3) entry action of target state. Does anybody know what I'm doing wrong here? Best regards, Franz #include <iostream> #include "FSMSimple.h" using namespace std; int main(int argc, char * argv[]) { // Instanciate the FSM ... FSMSimple sm; // ... and start it sm.initiate(); // Process some events ... cout << "trigger event 'Event1'" << endl; sm.process_event(Event1()); cout << "trigger event 'Event2'" << endl; sm.process_event(Event2()); return 0; } #include "FSMSimple.h" #include <iostream> using namespace std; // The FSM void FSMSimple::action1(const Event1 & /*e*/) { cout << "process action 'action1'" << endl; } void FSMSimple::action2(const Event2 & /*e*/) { cout << "process action 'action2'" << endl; } void FSMSimple::action3(const Event2 & /*e*/) { cout << "process action 'action3'" << endl; } bool FSMSimple::guard1() { cout << "process guard 'guard1'" << endl; return true; } // FSM state 'StateA' StateA::StateA() { cout << "enter state 'StateA'" << endl; } StateA::~StateA() { cout << "leave state 'StateA'" << endl; } // FSM state 'StateB' StateB::StateB() { cout << "enter state 'StateB'" << endl; } StateB::~StateB() { cout << "leave state 'StateB'" << endl; } sc::result StateB::react(const Event2 & e) { if (context<FSMSimple>().guard1()) { context<FSMSimple>().action3(e); return transit<StateC>(); } else { context<FSMSimple>().action2(e); return transit<StateA>(); } } // FSM state 'StateC' StateC::StateC() { cout << "enter state 'StateC'" << endl; } StateC::~StateC() { cout << "leave state 'StateC'" << endl; } #ifndef FSMSIMPLE_H #define FSMSIMPLE_H #include <iostream> #include <boost/mpl/list.hpp> #include <boost/statechart/event.hpp> #include <boost/statechart/state_machine.hpp> #include <boost/statechart/simple_state.hpp> #include <boost/statechart/custom_reaction.hpp> #include <boost/statechart/transition.hpp> namespace mpl = boost::mpl; namespace sc = boost::statechart; // FSM events struct Event1 : sc::event<Event1> { Event1() { std::cout << "process event 'Event1'" << std::endl; } }; struct Event2 : sc::event<Event2> { Event2() { std::cout << "process event 'Event2'" << std::endl; } }; // FSM initial state struct StateA; // The FSM struct FSMSimple : sc::state_machine<FSMSimple, StateA> { void action1(const Event1 & e); void action2(const Event2 & e); void action3(const Event2 & e); bool guard1(); }; // FSM states (forward declarations) struct StateA; struct StateB; struct StateC; // FSM states struct StateA : sc::simple_state<StateA, FSMSimple> { typedef mpl::list< sc::transition<Event1, StateB, FSMSimple, &FSMSimple::action1> > reactions; StateA(); ~StateA(); }; struct StateB : sc::simple_state<StateB, FSMSimple> { typedef mpl::list< sc::custom_reaction<Event2> > reactions; StateB(); ~StateB(); sc::result react(const Event2 & e); }; struct StateC : sc::simple_state<StateC, FSMSimple> { typedef mpl::list< > reactions; StateC(); ~StateC(); }; #endif // FSMSIMPLE_H enter state 'StateA' trigger event 'Event1' process event 'Event1' leave state 'StateA' process action 'action1' enter state 'StateB' trigger event 'Event2' process event 'Event2' process guard 'guard1' process action 'action3' leave state 'StateB' enter state 'StateC' leave state 'StateC'
Hi Franz
I've tried to use the Statechart library for modelling a simple state machine. I've created three states and three transitions between them and added some debug outputs. When I've looked to the debug outputs I've wondered a little bit. I've thought that the processing of events are in the order 1) exit actions of source state 2) transition actions and 3) entry actions of target state. When I look at my result I see the order 1) transition action 2) exit action of source state and 3) entry action of target state.
I assume you are referring to the following sequence in the output:
trigger event 'Event2' process event 'Event2' process guard 'guard1' process action 'action3' leave state 'StateB' enter state 'StateC'
Does anybody know what I'm doing wrong here?
Yes, it seems you are confusing the react member function of a state with a transition function. I'm referring to the following code fragment:
sc::result StateB::react(const Event2 & e) { if (context<FSMSimple>().guard1()) { context<FSMSimple>().action3(e);
This is a direct call to action3 ...
return transit<StateC>();
... and this is where the transition actually takes place. In order to let the transition action execute at the right time, you should replace the code:
context<FSMSimple>().action3(e); return transit<StateC>();
with // untested code return transit<StateC>(&FSMSimple::action3, e); Please see: <http://www.boost.org/doc/libs/1_37_0/libs/statechart/doc/tutorial.html#TransitionActions> Please let me know whether that works for you. Thanks & Regards, -- Andreas Huber When replying by private email, please remove the words spam and trap from the address shown in the header.
participants (2)
-
Andreas Huber
-
Franz Alt