Steve
Steve

Reputation: 859

State machine implementation in C

I have been trying to implement a state machine in C language and I am not sure whether my implementation is appropriate. I have tried to implement the state diagram in pseudo object manner. So I have declared the public interface of StateMachine "class" in StateMachine.h header file:

typedef enum{
  STATE_01,
  STATE_02,
  STATE_03,
  STATE_04
}state_e;

typedef enum{
  NO_EVENT,
  EVENT_01,
  EVENT_02,
  EVENT_03,
  EVENT_04,
  EVENT_05,
  EVENT_06,
  EVENT_07
}event_e;

// state machine instance
typedef struct{
  state_e currState;
}StateMachine;

extern void InitState(StateMachine*);
extern void ProcSTATE_01(StateMachine*, event_e);
extern void ProcSTATE_02(StateMachine*, event_e);
extern void ProcSTATE_03(StateMachine*, event_e);
extern void ProcSTATE_04(StateMachine*, event_e);
extern void ProcEvent(StateMachine*, event_e);

The implementation of the StateMachine object "methods" is in the StateMachine.c module:

void InitState(StateMachine *sm)
{
    sm->currState = STATE_01;
}


void ProcSTATE_01(StateMachine *sm, event_e event)
{
  if(event == EVENT_01){
    sm->currState = STATE_02;
  }
}

void ProcSTATE_02(StateMachine *sm, event_e event)
{
  // ...
}

void ProcSTATE_03(StateMachine *sm, event_e event)
{
  // ...
}

void ProcSTATE_04(StateMachine *sm, event_e event)
{
  // ...
}


void ProcEvent(StateMachine *sm, event_e event)
{
    switch(sm->currState){
      case STATE_01:
        ProcSTATE_01(sm, event);
      break;

      case STATE_02:
        ProcSTATE_02(sm, event);
      break;

      case STATE_03:
        ProcSTATE_03(sm, event);
      break;

      case STATE_04:
        ProcSTATE_04(sm, event);
      break;

    }
}

The usage of the StateMachine object is following:

int main(int argc, char** argv) {

    StateMachine app;
    ProcEvent(&app, EVENT_01);

    return 0;
}

I would like to ask anybody more experienced whether he can see any potential problems which are connected with this implementation. Thanks for any comments.

Upvotes: 0

Views: 651

Answers (2)

Timobile
Timobile

Reputation: 21

There is no "correct" way to implement a state machine (like the state table aproach mentioned by Doug), but there is code that can give you direct insights about what is easy to use and what is not. There is a book by Miro Samek about using hirarchical state machines in c/c++. There he compares the different styles with the state machine style he has developed. And i must say, his style is the one that is most reasonable and readable to me. Part of the book is also available online at state-machine.com. Your state machine skeleton in fact is very similar to the state machine part of Miros aproach, his aproach also adds a hirarchical transition possibility, queues per state machine, a system tick mechanism, event recycling, a zero event copying policy and so on. If you look at his web-site you will see that your aproach is a good one that can be extended in many, many ways.

Upvotes: 1

Doug
Doug

Reputation: 709

You'll need to think about where your events come from. Do they only get generated from the state transition handlers themselves, or are they exogenous. If they are exogenous, then you'll likely want an event loop external to your handler which pulls off events from a queue and injects them in to the appropriate handler (which might enqueue another event to the queue for later handling). Also, you might want to store your state-event handler functions in an array (indexed on the state number) so you can programmatically call them (instead of having to have a giant switch statement).

Upvotes: 1

Related Questions