Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

state machines tutorials [closed]

I am just wondering if anyone know of some good tutorials on the Internet for developing state machines. Or ebooks?

I am starting working on state machines and just need something general to get me started.

like image 954
ant2009 Avatar asked Sep 03 '09 04:09

ant2009


People also ask

Where can I use state machine?

State Machines are most commonly used when programming user interfaces. When creating a user interface, different user actions send the user interface into different processing segments. Each of these segments will act as states in the State Machine.

How do you read a state machine?

For every inch of paper there is a single letter printed on it–either the letter 'a' or the letter 'b'. The circles are “states” that the machine can be in. The arrows are the transitions. So, if you are in state s and read an 'a', you'll transition to state q.

What is a guard condition?

In UML modeling, a guard condition is a boolean condition that is evaluated when a transition initiates. A transition with a guard condition occurs when the guard condition is evaluated to be true.


2 Answers

State machines are very simple in C if you use function pointers.

Basically you need 2 arrays - one for state function pointers and one for state transition rules. Every state function returns the code, you lookup state transition table by state and return code to find the next state and then just execute it.

int entry_state(void); int foo_state(void); int bar_state(void); int exit_state(void);  /* array and enum below must be in sync! */ int (* state[])(void) = { entry_state, foo_state, bar_state, exit_state}; enum state_codes { entry, foo, bar, end};  enum ret_codes { ok, fail, repeat}; struct transition {     enum state_codes src_state;     enum ret_codes   ret_code;     enum state_codes dst_state; }; /* transitions from end state aren't needed */ struct transition state_transitions[] = {     {entry, ok,     foo},     {entry, fail,   end},     {foo,   ok,     bar},     {foo,   fail,   end},     {foo,   repeat, foo},     {bar,   ok,     end},     {bar,   fail,   end},     {bar,   repeat, foo}};  #define EXIT_STATE end #define ENTRY_STATE entry  int main(int argc, char *argv[]) {     enum state_codes cur_state = ENTRY_STATE;     enum ret_codes rc;     int (* state_fun)(void);      for (;;) {         state_fun = state[cur_state];         rc = state_fun();         if (EXIT_STATE == cur_state)             break;         cur_state = lookup_transitions(cur_state, rc);     }      return EXIT_SUCCESS; } 

I don't put lookup_transitions() function as it is trivial.

That's the way I do state machines for years.

like image 122
qrdl Avatar answered Oct 10 '22 00:10

qrdl


I prefer using function pointers over gigantic switch statements, but in contrast to qrdl's answer I normally don't use explicit return codes or transition tables.

Also, in most cases you'll want a mechanism to pass along additional data. Here's an example state machine:

#include <stdio.h>  struct state; typedef void state_fn(struct state *);  struct state {     state_fn * next;     int i; // data };  state_fn foo, bar;  void foo(struct state * state) {     printf("%s %i\n", __func__, ++state->i);     state->next = bar; }  void bar(struct state * state) {     printf("%s %i\n", __func__, ++state->i);     state->next = state->i < 10 ? foo : 0; }  int main(void) {     struct state state = { foo, 0 };     while(state.next) state.next(&state); } 
like image 20
Christoph Avatar answered Oct 10 '22 02:10

Christoph