State Machine 1
int event_1 = 0; StateMachine *stateMachine = allocStateMachine(NULL, NULL); State *S_1 = allocateState(stateMachine, NULL, stateMachine); State *S_2 = allocateState(stateMachine, NULL, stateMachine); State *S_3 = allocateState(stateMachine, NULL, stateMachine);
addTransition(S_1, S_2, event_1, 0); addTransition(S_2, S_3, event_1, 0); addTransition(S_3, S_1, event_1, 0);
The last parameter of this function will be explained later.
makeDefault(S_1);
startStateMachine(stateMachine);
sendEvent(stateMachine, 1);
//Function that should be executed when S_1 is entered void S1Entered() { printf("S_1 is entered\n"); } //Function that should be executed when S_2 is exited void S2Exited() { printf("S_2 is exited\n"); } //Function that should be executed when S_3 is entered void S3Entered() { printf("S_3 is entered\n"); }
setEntryWork(S_1, &S1Entered); setExitWork(S_2, &S2Exited); setEntryWork(S_3, &S3Entered);
We can achieve the same behavior (namely that sending event_2 quits the state machine, regardless of which state the state machine is in) by grouping states S_1, S_2 and S_3. This is done by creating a new top-level state and making the three original states children of the new state. The following diagram shows the new state machine.
State Machine 2
int event_1 = 0; int event_2 = 1; StateMachine *stateMachine = allocStateMachine(NULL, NULL); State *MS_1 = allocateState(stateMachine, NULL, stateMachine); State *S_2 = allocateState(stateMachine, NULL, stateMachine); State *S_1_1 = allocateState(MS_1, NULL, stateMachine); State *S_1_2 = allocateState(MS_1, NULL, stateMachine); State *S_1_3 = allocateState(MS_1, NULL, stateMachine); makeDefault(MS_1); makeDefault(S_1_1); addTransition(S_1_1, S_1_2, event_1, 0); addTransition(S_1_2, S_1_3, event_1, 0); addTransition(S_1_3, S_1_1, event_1, 0); addTransition(MS_1, S_2, event_2, 0);
Such behavior can easily be modeled using history states. A history state is a property that can be attached to a state and save the child state that the parent state was in the last time the parent state was exited.
A transition to the history state of a state is in fact a transition to the child state that the state machine had previously saved; the state machine automatically "forwards" the transition to the real child state.
The following diagram shows the state machine after the interrupt mechanism has been added.
State Machine 3
int event_3 = 2; State *S_3 = allocateState(stateMachine, NULL, stateMachine); addTransition(MS_1, S_3, event_3, 0); addTransition(S_3, MS_1, event_3, 1);
int event_3 = 2; State *S_3 = allocateState(stateMachine, NULL, stateMachine); makeHistoryStateDefault(MS_1, S_1_1); addTransition(MS_1, S_3, event_3, 0); addTransition(S_3, MS_1, event_3, 0);
freeStateMachine(stateMachine);
#include <stdio.h> #include <unistd.h> #include "StateMachine.h" int main(int argc, char** argv) { int i; int event_1 = 0; int event_2 = 1; int event_3 = 2; StateMachine *stateMachine = allocStateMachine("SM", "[SM]"); State *MS_1 = allocateState(stateMachine, "MS_1", stateMachine); State *S_2 = allocateState(stateMachine, "S_2", stateMachine); State *S_3 = allocateState(stateMachine, "S_3", stateMachine); State *S_1_1 = allocateState(MS_1, "S_1_1", stateMachine); State *S_1_2 = allocateState(MS_1, "S_1_2", stateMachine); State *S_1_3 = allocateState(MS_1, "S_1_3", stateMachine); makeDefault(MS_1); makeDefault(S_1_1); addTransition(S_1_1, S_1_2, event_1, 0); addTransition(S_1_2, S_1_3, event_1, 0); addTransition(S_1_3, S_1_1, event_1, 0); addTransition(MS_1, S_2, event_2, 0); addTransition(MS_1, S_3, event_3, 0); addTransition(S_3, HS_1, event_3, 1); setDbgParam(stateMachine, STATE_WORK_DBG); startStateMachine(stateMachine); do { printf("[Test program] Next event : "); scanf("%d", &i); sendEvent(stateMachine, i); }while(i >= 0 && i <= 2); freeStateMachine(stateMachine); return 0; }
Previous: mainpage