0

Let's say I have a finite-state-machine which looks like this:

while(1){
    swtich(case){
        case ONE:
            do_thingone();
            if(parameter1 == 0)
                case = TWO;
        break;
        case TWO:
            do_thingtwo();
            do_thingthree();
            if(parameter1 == 1)
                case = ONE;
            if(parameter0 == 0)
                case = THREE;
        break;
//and so on
    }
}

With a boolean paramter p_master I want to change between two finite-state-machines with similar, yet different content.

while(1){
    switch(state){
        state STATE_0:
            switch(case){
                case ONE:
                    do_onething();
                    if(parameter1 == 0)
                        case = TWO;
                break;
              //case TWO:
            }
        break;

        case STATE_1:
            switch(case){
                case ONE:
                    do_anotherthing();
                    if(parameter1 == 0)
                        case = TWO;
                break;
              //case TWO:
            }
        break;
    }
}

I don't want to check and switch case via an

if(p_master == 0)

or vice versa every iteration, as I think this will create too much overhead (p_master only changes every 100th or 1000th iteration, it even is perfectly ok for it to never change at all!). Is there a more elegant way to change between a case and another than conditions ins the finite-state-machine loop?
Note: p_master can be triggered as an interrupt at CPU level!

unwind
  • 391,730
  • 64
  • 469
  • 606
  • Why would this cause much overhead? It's a simple branch, and if it rarely changes, should be easily handled by the branch predictor. – Nathan Fellman Nov 25 '13 at 12:35
  • Hint: don't use the word `case` as a variable. It's a reserved word and even if it works it's likely to cause confusion (for example: with the syntax highlighting). – Kninnug Nov 25 '13 at 12:44
  • Nathan, it can change rarely, that is right. But I always have to check if it has changed or not, and I want to find a more elegant solution for this checking! – kernelpanic Nov 25 '13 at 12:51

3 Answers3

3

Move the switch statement into a function and adjust a function pointer. Having a dedicated "handler" function for each state (and each handler can define what handler is next) is pretty common when implementing finite state machines in C. It also nicely maps to the state machine diagrams you might look at (one handler function per state).

See this question for some inspiration.

Community
  • 1
  • 1
Frerich Raabe
  • 90,689
  • 19
  • 115
  • 207
0

Function pointers.

typedef void (*State_T) (void);

void state_1(void);
void state_2(void);

void doStuff(void) {
    State_T currentState = state_1;
    while(...) {
        currentState();
    }
}
user694733
  • 15,208
  • 2
  • 42
  • 68
0

If you only have a few such states and you can change the flags, why not roll them into one switch:

switch(state | case){
    case STATE_0 | ONE:
        do_onething();
        if(parameter1 == 0)
            case = TWO;
            break;
    case STATE_0 | TWO:
        break;
    case STATE_1 | ONE:
        do_onething();
        if(parameter1 == 0)
            case = TWO;
            break;
    case STATE_1 | TWO:
        break;
}
Cory Nelson
  • 29,236
  • 5
  • 72
  • 110
  • Thank you, altough this does not solve my actual problem, it is good to know things can be done like this. I will remember this! – kernelpanic Nov 25 '13 at 12:55