To handle situation, where we need to do some cleanup activities, boost::statechart provides some mechanisms which are being discussed below
A function with a signature void exit(){...} could be defined for every state. This only thing to remember is that the function gets called ONLY IF state gets terminated because state machine is moved to another state. This function will not get called, if the state is terminated because a state machine itself is terminated
// States
struct firstState;
struct secondState;
// State Events
struct event_MoveToSecond : sc::event<event_MoveToSecond> {};
// State Machines
struct statemachine : sc::state_machine<statemachine, firstState> {};
struct firstState : sc::simple_state<firstState, statemachine>
{
firstState() { cout << "In State => firstState" << endl; }
typedef sc::transition<event_MoveToSecond, secondState> reactions;
void exit() { cout << "exit() called in State => firstState" << endl; }
};
struct secondState : sc::simple_state<secondState, statemachine> {
secondState() { cout << "In State => secondState" << endl; }
void exit() { cout << "exit() called in State => secondState" << endl; }
};
// The main
int main() {
statemachine sm;
sm.initiate();
sm.process_event(event_MoveToSecond());
return 0;
}
In the above example, the exit() function gets called for firstState and not for secondState because secondState is terminated with the state machine.
NOTE: The exit() function gets called before destructor, so it's perfectly okay to treat exit() as a class member function and do the thing(s) which is otherwise not recommended in destructors
There is no difference between the behaviour of exit in Inner States. It will be called when the state is transitioned from one state to another state.
As with Outer States, the exit() functions shall not be called when the state machine is terminated.
In this chapter, we learnt about using the inbuilt error handling mechanism of boost::statechart