Cornstalks
Cornstalks

Reputation: 38218

State machines with function pointers: how to set the function pointers?

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

Answers (3)

Jay
Jay

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

Alexander Atanasov
Alexander Atanasov

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

unwind
unwind

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

Related Questions