Reputation: 38218
This question asks about a finite state machine with 100 states and each state having 100 events, and then does a brief comparison of using an if-else
, switch
statement, or function pointers to implement the state machine.
My question is: if using function pointers, how would the function pointers be appropriately set? With an if-else
or a switch
statement (in which case, would function pointers be more of a hybrid solution)? Or is there another way this is commonly done?
Upvotes: 0
Views: 4532
Reputation: 24895
You could do something like below:
typedef int (*current_state) (void);
typedef int (*nextnew_state) (void);
struct FuncPointerState
{
current_state curr_state;
nextnew_state next_state;
};
/*init_state is the initial function state*/
struct FuncPointerState FpState = {init_state, NULL};
int iRet = 0;
while(1)
{
iRet = FpState.curr_state();
if(iRet<= 0 )
{
return iRet;
}
if(NULL==FpState.next_state)
{
/* State Machine finished it's job */
break;
}
FpState.curr_state = FpState.next_state;
}
Each state function should populate the next_state pointer. Also, you can modify the function pointers to take input arguments.
Upvotes: 1
Reputation: 496
struct state_fn {
void (*handler)(void);
};
static int state;
static struct state_fn[MAX_STATE] = {
{ .handler = handler_state_0, },
{ .handler = handler_state_1, },
{ .handler = handler_state_2, },
};
then call state_fn[state]->handler();
you can optionaly add arguments from the structure. like this:
struct state_fn {
void (*handler)(void *data);
void *data;
}
then call state_fn[state]->handler(state_fn[state]->data);
{ .handler = handler_state_0, .data = "blabla" },
this is handy if one function handler can serve several states.
Upvotes: 1
Reputation: 399763
I would expect each state to be represented by a function, and all states to "know" about each other.
So, the setting could be either directly:
void set_state(void (*state)(void))
{
the_current_state = state;
}
void state_idle(void)
{
printf("oh, hai, boring to be in the idle state, let's switch\n");
set_state(state_busy);
}
this assumes that the current state is modelled by a global function pointer (the_current_state
).
You could of course also let each state return the new state, or maybe NULL
to mean "don't switch".
Upvotes: 2