kender
Joined: 09 Aug 2004 Posts: 768 Location: Silicon Valley
|
pointers to functions as a state machine |
Posted: Mon Oct 23, 2006 10:26 pm |
|
|
I’ll show a rudimentary pointer-to-function based state machine as a compared to a rudimentary nested switch state machine. Imagine a device that has a set of states (STATE1, STATE2, etc) and a set of messages (MSG1, MSG2, etc).
Rudimentary nested switch state machine
Code: |
int g_iState;
void AllStateHandlers(int iMessage)
{
switch (g_iState) // first layer of nested switch statement
{
case STATE1:
switch (iMessage) // second layer of nested switch statement
{
case MSG1:
// do something1
break;
case MSG2:
// do something2
g_iState = STATE2; // transition to a different state (for a change)
break;
// ... other message handlers
}
break;
case STATE2:
switch (iMessage)
{
// message handlers for STATE2
}
break
case STATE3:
// ...
// more states
}
}
#int_rtcc
void isr_rtcc // an example source of a message, that needs state-dependent handling
{
AllStateHandlers(MSG2); // Call a message handler, which will navigate through the switch statement to the current current state
}
void main()
{
g_iState = STATE1; // go to some initial state on startup
} |
Pointer-to-function based state machine Code: |
typedef void (*State) (int iMessage); // a typedef for a pointer-to-function
// Current state of the device is a pointer-to-function.
// Note that there are no state flags.
State g_pfState;
void State1(int iMessage) // Note that the name of the function is the same as the name of the state
{
switch (iMessage) // 1-layer of switch. No nested switch.
{
case MSG1:
// do something1
break;
case MSG2:
// do something2
g_pfState = &State2; // to transition to a different state we need to change the pointer
break;
// ... other message handlers
}
}
void State2(int iMessage)
{
switch (iMessage)
{
// message handlers
}
}
#int_rtcc
void isr_rtcc // an example source of a message, that needs state-dependent handling
{
g_pfState(MSG2); // Call a message handler through the pointer-to-function
}
void main()
{
g_iState = &State1; // go to some initial state on startup
} |
Advantages of the pointer-to-function approach
There’s no nested switch, so the code is more readable, more modular and executes somewhat faster.
Disadvantages of the pointer-to-function approach
The flags are replaced by a pointer-to-function. The pointer-to-function doesn’t have a “physical” meaning, which makes it more difficult to understand what state the device is in. |
|