#include #include #include #include #include namespace bs = boost::statechart; using namespace std; // The main event, should be handles by a sub-state and the main state struct update_event; // An event triggering the sub-state to switch struct toggle_event; // A dummy event struct other_event; // Sub-states in 2 orthogonal regions struct state_1A; struct state_1B; struct state_2A; struct state_2B; // Main state struct parent_state; // State machine consisting of the main state struct machine : bs::state_machine { }; typedef boost::mpl::list < state_1A , state_2A > inner_states_t; // The main state has 2 orthogonal sub-states struct parent_state : bs::simple_state { typedef boost::mpl::list < bs::custom_reaction > reactions; bs::result react(const update_event&) { cout << __FUNCTION__ << endl; return discard_event(); } }; struct update_event : bs::event { }; struct other_event : bs::event { }; struct toggle_event : bs::event { }; struct state_1A : bs::simple_state> { typedef boost::mpl::list < bs::custom_reaction , bs::custom_reaction > reactions; state_1A() { cout << __FUNCTION__ << endl; } bs::result react(const toggle_event&) { cout << __FUNCTION__ << endl; return transit(); } bs::result react(const update_event&) { cout << __FUNCTION__ << endl; return forward_event(); } }; struct state_1B : bs::simple_state> { typedef boost::mpl::list < bs::custom_reaction > reactions; state_1B() { cout << __FUNCTION__ << endl; } bs::result react(const toggle_event&) { cout << __FUNCTION__ << endl; return transit(); } }; struct state_2A : bs::simple_state> { typedef boost::mpl::list < bs::custom_reaction > reactions; state_2A() { cout << __FUNCTION__ << endl; } bs::result react(const other_event&) { cout << __FUNCTION__ << endl; return discard_event(); } }; struct state_2B : bs::simple_state> { typedef boost::mpl::list < bs::custom_reaction > reactions; state_2B() { cout << __FUNCTION__ << endl; } bs::result react(const other_event&) { cout << __FUNCTION__ << endl; return discard_event(); } }; int main(int argc, char* argv[]) { machine m; cout << "0. Initiating state machine:" << endl; m.initiate(); cout << endl << "1. Processing 'other_event':" << endl; m.process_event(other_event ()); cout << endl << "2. Processing 'update_event':" << endl; m.process_event(update_event()); cout << endl << "3. Processing 'toggle_event':" << endl; m.process_event(toggle_event()); cout << endl << "4. Processing 'update_event':" << endl; m.process_event(update_event()); cout << endl << "5. Processing 'toggle_event':" << endl; m.process_event(toggle_event()); cout << endl << "6. Processing 'update_event':" << endl; m.process_event(update_event()); return 0; } ////////////////////////////////////////////////////////////////////////// // Program output after building with VC 9 and Boost 1.37.0 // // Note the different event handling in step 6. as compared to step 2. // although the machine should be back in the same state. ////////////////////////////////////////////////////////////////////////// /* 0. Initiating state machine: state_1A::state_1A state_2A::state_2A 1. Processing 'other_event': state_2A::react 2. Processing 'update_event': state_1A::react parent_state::react 3. Processing 'toggle_event': state_1A::react state_1B::state_1B 4. Processing 'update_event': parent_state::react 5. Processing 'toggle_event': state_1B::react state_1A::state_1A 6. Processing 'update_event': parent_state::react */