Using GOTO for a FSM in C - c

I am creating a finite state machine in C.
I learned FSM from the hardware point of view (HDL language). So I'm used a switch with one case per state.
I also like to apply the Separation of Concerns concept when programing.
I mean I'd like to get this flow:
Calculate the next state depending on the current state and input flags
Validate this next state (if the user request a transition that is not allowed)
Process the next state when it is allowed
As a start I implemented 3 functions:
static e_InternalFsmStates fsm_GetNextState();
static bool_t fsm_NextStateIsAllowed(e_InternalFsmStates nextState);
static void fsm_ExecuteNewState(e_InternalFsmStates);
At the moment they all contain a big switch-case which is the same:
switch (FSM_currentState) {
case FSM_State1:
[...]
break;
case FSM_State2:
[...]
break;
default:
[...]
break;
}
Now that it works, I'd like to improve the code.
I know that in the 3 functions I'll execute the same branch of the switch.
So I am thinking to use gotos in this way:
//
// Compute next state
//
switch (FSM_currentState) {
case FSM_State1:
next_state = THE_NEXT_STATE
goto VALIDATE_FSM_State1_NEXT_STATE;
case FSM_State2:
next_state = THE_NEXT_STATE
goto VALIDATE_FSM_State2_NEXT_STATE;
[...]
default:
[...]
goto ERROR;
}
//
// Validate next state
//
VALIDATE_FSM_State1_NEXT_STATE:
// Some code to Set stateIsValid to TRUE/FALSE;
if (stateIsValid == TRUE)
goto EXECUTE_STATE1;
else
goto ERROR;
VALIDATE_FSM_State2_NEXT_STATE:
// Some code to Set stateIsValid to TRUE/FALSE;
if (stateIsValid == TRUE)
goto EXECUTE_STATE2;
else
goto ERROR;
//
// Execute next state
//
EXECUTE_STATE1:
// Do what I need for state1
goto END;
EXECUTE_STATE2:
// Do what I need for state2
goto END;
//
// Error
//
ERROR:
// Error handling
goto END;
END:
return; // End of function
Of course, I could do the 3 parts (calculate, validate and process the next state) in a single switch case. But for code readability and code reviews, I feel like it will be easier to separate them.
Finally my question, is it dangerous to use GOTOs in this way?
Would you have any advice when using FSM like that?
Thank you for your comments!
After reading the answers and comments below, here is what I am going to try:
e_FSM_InternalStates nextState = FSM_currentState;
bool_t isValidNextState;
//
// Compute and validate next state
//
switch (FSM_currentState) {
case FSM_State1:
if (FSM_inputFlags.flag1 == TRUE)
{
nextState = FSM_State2;
}
[...]
isValidNextState = fsm_validateState1Transition(nextState);
case FSM_State2:
if (FSM_inputFlags.flag2 == TRUE)
{
nextState = FSM_State3;
}
[...]
isValidNextState = fsm_validateState2Transition(nextState);
}
//
// If nextState is invalid go to Error
//
if (isValidNextState == FALSE) {
nextState = FSM_StateError;
}
//
// Execute next state
//
switch (nextState) {
case FSM_State1:
// Execute State1
[...]
case FSM_State2:
// Execute State1
[...]
case FSM_StateError:
// Execute Error
[...]
}
FSM_currentState = nextState;

While goto has its benefits in C, it should be used sparesly and with extreme caution. What you intend is no recommendable use-case.
Your code will be less maintainable and more confusing. switch/case is actually some kind of "calculated" goto (thats's why there are case labels).
You are basicaly thinking the wrong way. For a state-machine, you should first verify input, then calculate the next state, then the output. There are various ways to do so, but it is often a good idea to use two switches and - possibly - a single error-handling label or a error-flag:
bool error_flag = false;
while ( run_fsm ) {
switch ( current_state ) {
case STATE1:
if ( input1 == 1 )
next_state = STATE2;
...
else
goto error_handling; // use goto
error_flag = true; // or the error-flag (often better)
break;
...
}
if ( error_flag )
break;
switch ( next_state ) {
case STATE1:
output3 = 2;
// if outputs depend on inputs, similar to the upper `switch`
break;
...
}
current_state = next_state;
}
error_handling:
...
This way you are transitioning and verifying input at once. This makes senase, as you have to evaluate the inputs anyway to set the next state, so invalid input just falls of the tests naturally.
An alternative is to have an output_state and state variable instead of next_state and current_state. In the first switch you set output_state and state, the second is switch ( output_state ) ....
If the single cases become too long, you should use functions to determine the next_state and/or output_state/outputs. It depends very much on the FSM (number of inputs, outputs, states, complexity (e.g. one-hot vs. "encoded" - if you are family with HDL, you will know).
If you need more complex error-handling (e.g. recover) inside the loop, leave the loop as-is and add an outer loop, possibly change the error-flag to an error-code and add another switch for it in the outer loop. Depending on complexity, pack the inner loop into its own function, etc.
Sidenote: The compiler might very well optimize the structured approach (without goto) to the same/similar code as with the goto

Whether it is "dangerous" is probably somewhat a matter of opinion. The usual reason people say to avoid GOTO is that it tends to lead to spaghetti code that's hard to follow. Is that an absolute rule? Probably not, but I think it's definitely fair to say that it is the trend. Secondarily, most programmers at this point are trained to believe that GOTO is bad, so, even if it's not in some case, you may run into some level of maintainability issue with other people coming into the project later.
How much risk you have in your case, probably depends on how big of a chunk of code you're going to have under those state labels and how sure you are that it won't change much. More code (or potential for large revisions), means more risk. In addition to just straight questions of readability, you'll have increased chances for assignments to variables interfering between cases or being dependent on the path you took to get to a certain state. Using functions helps with this (in many cases) by creating local scope for variables.
All in all, I would recommend avoiding the GOTO.

You don't really need to use switch-case, it will actually get optimized away by the compiler into machine code with a function pointer jump table. Switch-cases for state machines tend to be somewhat hard to read, especially the more complex ones.
The spaghetti-gotos are unacceptable and bad programming practice: there are a few valid uses of goto, this is not one of them.
Instead, consider to have a one-line state machine which looks like:
state = STATE_MACHINE[state]();
Here is an answer of mine (taken from the electrical engineering site, it pretty much applies universally) which is based on a function-pointer lookup table.
typedef enum
{
STATE_S1,
STATE_S2,
...
STATE_N // the number of states in this state machine
} state_t;
typedef state_t (*state_func_t)(void);
state_t do_state_s1 (void);
state_t do_state_s2 (void);
static const state_func_t STATE_MACHINE [STATE_N] =
{
&do_state_s1,
&do_state_s2,
...
};
void main()
{
state_t state = STATE_S1;
while (1)
{
state = STATE_MACHINE[state]();
}
}
state_t do_state_s1 (void)
{
state_t result = STATE_S1;
// stuff
if (...)
result = STATE_S2;
return result;
}
state_t do_state_s2 (void)
{
state_t result = STATE_S2;
// other stuff
if (...)
result = STATE_S1;
return result;
}
You can easily modify the function signatures to contain an error code as well, such as for example:
typedef err_t (*state_func_t)(state_t*);
with functions as
err_t do_state_s1 (state_t* state);
in which case the caller would end up as:
error = STATE_MACHINE[state](&state);
if(error != NO_ERROR)
{
// handle errors here
}
Leave all error handling to the caller as show in the above example.

My rule of thumb is to use GOTOs only to jump forward in the code, but never backwards. In the end this boils down to using GOTO only for exception handling, which otherwise doesn't exist in C.
In your particular case I would absolutely not recommend the use of GOTO.

Related

Uses for never-ending loops

What are some uses of never-ending loops? They are usually bad news in programming, but is there ever a time when you want a loop to never end?
Infinite loops are only bad news when they are not intended or their use has unintended consequences. If you use them with intent there is no difference from any other classification of loop you might consider. However you will still end up breaking things despite intentional use. It is common to use this form when you want to access the iterator or index component after the loop has been terminated, for example:
index = 0;
result = null;
for (;;)
result = foo(index);
if (bar(result))
break;
index += result;
use(index, result);
Note that mutating data outside of the loop's scope may be very undesirable depending on the context, so whether or not this is a good use case really depends on the context. For another similar example, an actual iterator may be the object desired outside of the loop, but initializing it within the loop header would not allow access outside of the loop. An infinite loop would resolve this problem.
for (foo.iterator(); foo.hasNext(); ) {
use(foo.next());
}
keep_using(foo.next()); // throws an error
Additionally, infinite loops can in some cases improve readability, especially if there are many break conditions but they might not all derive from mutually exclusive units. For example, imagine we have the following:
for (;;) {
if (condition1)
break;
else if (condition2)
do_stuff();
else if (condition3)
break;
else
do_something();
}
This can be rewritten using the three components of a loop as:
for (condition = true; condition; iteration) {
if (condition1 || condition3)
condition = false;
else if (condition2)
do_stuff();
else
do_something();
}
However if we introduce a small amount of change (at least in terms of characters on the screen) to the original code:
for (;;) {
if (condition1);
break;
if (condition2);
do_stuff();
if (condition3);
break;
else
do_something();
}
The rewrite becomes this thing that requires us to lug around this extra variable:
for (condition = true; condition; iteration) {
if (condition1)
condition = false;
if (condition2) {
do_stuff();
condition = true;
}
if (condition3)
condition = false;
else {
do_something();
condition = true;
}
}
This can quickly become difficult to read and maintain as the loop body, and especially the complexity grows, for example if condition were actually many different conditions such as a || b || c < d || (e > f) && (a > f); or, the loop contained several nested loops. Though you might apply the same logic to other the original changed version.
Another readability related example involves verbose initialization, though admittedly not a very good use case:
for (more_long = some_ridiculously_long.initialization_statement.longer_than.Long_Long_Mans_Sakeru_gummy();
more_long < lots_of && more_long < break_conditions
maybe_even_an_update_that_hangs_at_ninety_nine_percent) {
...
}

Adding "else" at the end of an if-else statement [duplicate]

Our organization has a required coding rule (without any explanation) that:
if … else if constructs should be terminated with an else clause
Example 1:
if ( x < 0 )
{
x = 0;
} /* else not needed */
Example 2:
if ( x < 0 )
{
x = 0;
}
else if ( y < 0 )
{
x = 3;
}
else /* this else clause is required, even if the */
{ /* programmer expects this will never be reached */
/* no change in value of x */
}
What edge case is this designed to handle?
What also concerns me about the reason is that Example 1 does not need an else but Example 2 does. If the reason is re-usability and extensibility, I think else should be used in both cases.
As mentioned in another answer, this is from the MISRA-C coding guidelines. The purpose is defensive programming, a concept which is often used in mission-critical programming.
That is, every if - else if must end with an else, and every switch must end with a default.
There are two reasons for this:
Self-documenting code. If you write an else but leave it empty it means: "I have definitely considered the scenario when neither if nor else if are true".
Not writing an else there means: "either I considered the scenario where neither if nor else if are true, or I completely forgot to consider it and there's potentially a fat bug right here in my code".
Stop runaway code. In mission-critical software, you need to write robust programs that account even for the highly unlikely. So you could see code like
if (mybool == TRUE)
{
}
else if (mybool == FALSE)
{
}
else
{
// handle error
}
This code will be completely alien to PC programmers and computer scientists, but it makes perfect sense in mission-critical software, because it catches the case where the "mybool" has gone corrupt, for whatever reason.
Historically, you would fear corruption of the RAM memory because of EMI/noise. This is not much of an issue today. Far more likely, memory corruption occurs because of bugs elsewhere in the code: pointers to wrong locations, array-out-of-bounds bugs, stack overflow, runaway code etc.
So most of the time, code like this comes back to slap yourself in the face when you have written bugs during the implementation stage. Meaning it could also be used as a debug technique: the program you are writing tells you when you have written bugs.
EDIT
Regarding why else is not needed after every single if:
An if-else or if-else if-else completely covers all possible values that a variable can have. But a plain if statement is not necessarily there to cover all possible values, it has a much broader usage. Most often you just wish to check a certain condition and if it is not met, then do nothing. Then it is simply not meaningful to write defensive programming to cover the else case.
Plus it would clutter up the code completely if you wrote an empty else after each and every if.
MISRA-C:2012 15.7 gives no rationale why else is not needed, it just states:
Note: a final else statement is not required for a simple if
statement.
Your company followed MISRA coding guidance. There are a few versions of these guidelines that contain this rule, but from MISRA-C:2004†:
Rule 14.10 (required): All if … else if constructs shall be terminated
with an else clause.
This rule applies whenever an if statement is followed by one or more
else if statements; the final else if shall be followed by an else
statement. In the case of a simple if statement then the else
statement need not be included. The requirement for a final else
statement is defensive programming. The else statement shall either
take appropriate action or contain a suitable comment as to why no
action is taken. This is consistent with the requirement to have a
final default clause in a switch statement. For example this code
is a simple if statement:
if ( x < 0 )
{
log_error(3);
x = 0;
} /* else not needed */
whereas the following code demonstrates an if, else if construct
if ( x < 0 )
{
log_error(3);
x = 0;
}
else if ( y < 0 )
{
x = 3;
}
else /* this else clause is required, even if the */
{ /* programmer expects this will never be reached */
/* no change in value of x */
}
In MISRA-C:2012, which supersedes the 2004 version and is the current recommendation for new projects, the same rule exists but is numbered 15.7.
Example 1:
in a single if statement programmer may need to check n number of conditions and performs single operation.
if(condition_1 || condition_2 || ... condition_n)
{
//operation_1
}
In a regular usage performing a operation is not needed all the time when if is used.
Example 2:
Here programmer checks n number of conditions and performing multiple operations. In regular usage if..else if is like switch you may need to perform a operation like default. So usage else is needed as per misra standard
if(condition_1 || condition_2 || ... condition_n)
{
//operation_1
}
else if(condition_1 || condition_2 || ... condition_n)
{
//operation_2
}
....
else
{
//default cause
}
† Current and past versions of these publications are available for purchase via the MISRA webstore (via).
This is the equivalent of requiring a default case in every switch.
This extra else will Decrease code coverage of your program.
In my experience with porting linux kernel , or android code to different platform many time we do something wrong and in logcat we see some error like
if ( x < 0 )
{
x = 0;
}
else if ( y < 0 )
{
x = 3;
}
else /* this else clause is required, even if the */
{ /* programmer expects this will never be reached */
/* no change in value of x */
printk(" \n [function or module name]: this should never happen \n");
/* It is always good to mention function/module name with the
logs. If you end up with "this should never happen" message
and the same message is used in many places in the software
it will be hard to track/debug.
*/
}
Only a brief explanation, since I did this all about 5 years ago.
There is (with most languages) no syntactic requirement to include "null" else statement (and unnecessary {..}), and in "simple little programs" there is no need. But real programmers don't write "simple little programs", and, just as importantly, they don't write programs that will be used once and then discarded.
When one write an if/else:
if(something)
doSomething;
else
doSomethingElse;
it all seems simple and one hardly sees even the point of adding {..}.
But some day, a few months from now, some other programmer (you would never make such a mistake!) will need to "enhance" the program and will add a statement.
if(something)
doSomething;
else
doSomethingIForgot;
doSomethingElse;
Suddenly doSomethingElse kinda forgets that it's supposed to be in the else leg.
So you're a good little programmer and you always use {..}. But you write:
if(something) {
if(anotherThing) {
doSomething;
}
}
All's well and good until that new kid makes a midnight modification:
if(something) {
if(!notMyThing) {
if(anotherThing) {
doSomething;
}
else {
dontDoAnything; // Because it's not my thing.
}}
}
Yes, it's improperly formatted, but so is half the code in the project, and the "auto formatter" gets bollixed up by all the #ifdef statements. And, of course, the real code is far more complicated than this toy example.
Unfortunately (or not), I've been out of this sort of thing for a few years now, so I don't have a fresh "real" example in mind -- the above is (obviously) contrived and a bit hokey.
This, is done to make the code more readable, for later references and to make it clear, to a later reviewer, that the remaining cases handled by the last else, are do nothing cases, so that they are not overlooked somehow at first sight.
This is a good programming practice, which makes code reusable and extend-able.
I would like to add to – and partly contradict – the previous answers. While it is certainly common to use if-else if in a switch-like manner that should cover the full range of thinkable values for an expression, it is by no means guaranteed that any range of possible conditions is fully covered. The same can be said about the switch construct itself, hence the requirement to use a default clause, which catches all remaining values and can, if not otherwise required anyway, be used as an assertion safeguard.
The question itself features a good counter-example: The second condition does not relate to x at all (which is the reason why I often prefer the more flexible if-based variant over the switch-based variant). From the example it is obvious that if condition A is met, x should be set to a certain value. Should A not be met, then condition B is tested. If it is met, then x should receive another value. If neither A nor B are met, then x should remain unchanged.
Here we can see that an empty else branch should be used to comment on the programmer's intention for the reader.
On the other hand, I cannot see why there must be an else clause especially for the latest and innermost if statement. In C, there is no such thing as an 'else if'. There is only if and else. Instead, the construct should formally be indented this way (and I should have put the opening curly braces on their own lines, but I don't like that):
if (A) {
// do something
}
else {
if (B) {
// do something else (no pun intended)
}
else {
// don't do anything here
}
}
Should any standard happen to require curly braces around every branch, then it would contradict itself if it mentioned "if ... else if constructs" at the same time.
Anyone can imagine the ugliness of deeply nested if else trees, see here on a side note. Now imagine that this construct can be arbitrarily extended anywhere. Then asking for an else clause in the end, but not anywhere else, becomes absurd.
if (A) {
if (B) {
// do something
}
// you could to something here
}
else {
// or here
if (B) { // or C?
// do something else (no pun intended)
}
else {
// don't do anything here, if you don't want to
}
// what if I wanted to do something here? I need brackets for that.
}
In the end, it comes down for them to defining precisely what is meant with an "if ... else if construct"
The basic reason is probably code coverage and the implicit else: how will the code behave if the condition is not true? For genuine testing, you need some way to see that you have tested with the condition false. If every test case you have goes through the if clause, your code could have problems in the real world because of a condition that you did not test.
However, some conditions may properly be like Example 1, like on a tax return: "If the result is less than 0, enter 0." You still need to have a test where the condition is false.
Logically any test implies two branches. What do you do if it is true, and what do you do if it is false.
For those cases where either branch has no functionality, it is reasonable to add a comment about why it doesn't need to have functionality.
This may be of benefit for the next maintenance programmer to come along. They should not have to search too far to decide if the code is correct. You can kind of Prehunt the Elephant.
Personally, it helps me as it forces me to look at the else case, and evaluate it. It may be an impossible condition, in which case i may throw an exception as the contract is violated. It may be benign, in which case a comment may be enough.
Your mileage may vary.
Most the time when you just have a single if statement, it's probably one of reasons such as:
Function guard checks
Initialization option
Optional processing branch
Example
void print (char * text)
{
if (text == null) return; // guard check
printf(text);
}
But when you do if .. else if, it's probably one of reasons such as:
Dynamic switch-case
Processing fork
Handling a processing parameter
And in case your if .. else if covers all possibilities, in that case your last if (...) is not needed, you can just remove it, because at that point the only possible values are the ones covered by that condition.
Example
int absolute_value (int n)
{
if (n == 0)
{
return 0;
}
else if (n > 0)
{
return n;
}
else /* if (n < 0) */ // redundant check
{
return (n * (-1));
}
}
And in most of these reasons, it's possible something doesn't fit into any of the categories in your if .. else if, thus the need to handle them in a final else clause, handling can be done through business-level procedure, user notification, internal error mechanism, ..etc.
Example
#DEFINE SQRT_TWO 1.41421356237309504880
#DEFINE SQRT_THREE 1.73205080756887729352
#DEFINE SQRT_FIVE 2.23606797749978969641
double square_root (int n)
{
if (n > 5) return sqrt((double)n);
else if (n == 5) return SQRT_FIVE;
else if (n == 4) return 2.0;
else if (n == 3) return SQRT_THREE;
else if (n == 2) return SQRT_TWO;
else if (n == 1) return 1.0;
else if (n == 0) return 0.0;
else return sqrt(-1); // error handling
}
This final else clause is quite similar to few other things in languages such as Java and C++, such as:
default case in a switch statement
catch(...) that comes after all specific catch blocks
finally in a try-catch clause
Our software was not mission critical, yet we also decided to use this rule because of defensive programming.
We added a throw exception to the theoretically unreachable code (switch + if-else). And it saved us many times as the software failed fast e.g. when a new type has been added and we forgot to change one-or-two if-else or switch. As a bonus it made super easy to find the issue.
Well, my example involves undefined behavior, but sometimes some people try to be fancy and fails hard, take a look:
int a = 0;
bool b = true;
uint8_t* bPtr = (uint8_t*)&b;
*bPtr = 0xCC;
if(b == true)
{
a += 3;
}
else if(b == false)
{
a += 5;
}
else
{
exit(3);
}
You probably would never expect to have bool which is not true nor false, however it may happen. Personally I believe this is problem caused by person who decides to do something fancy, but additional else statement can prevent any further issues.
I'm currently working with PHP. Creating a registration form and a login form. I am just purely using if and else. No else if or anything that is unnecessary.
If user clicks submits button -> it goes to the next if statement... if username is less than than 'X' amount of characters then alert. If successful then check password length and so on.
No need for extra code such as an else if that could dismiss reliability for server load time to check all the extra code.
As this question on boolean if/else if was closed as a duplicate. As well, there are many bad answers here as it relates to safety-critical.
For a boolean, there are only two cases. In the boolean instance, following the MISRA recommendation blindly maybe bad. The code,
if ( x == FALSE ) {
// Normal action
} else if (x == TRUE ) {
// Fail safe
}
Should just be refactored to,
if ( x == FALSE ) {
// Normal action
} else {
// Fail safe
}
Adding another else increases cyclometric complexity and makes it far harder to test all branches. Some code maybe 'safety related'; Ie, not a direct control function that can cause an unsafe event. In this code, it is often better to have full testability without instrumentation.
For truly safety functional code, it might make sense to separate the cases to detect a fault in this code and have it reported. Although I think logging 'x' on the failure would handle both. For the other cases, it will make the system harder to test and could result in lower availability depending on what the second 'error handling' action is (see other answers where exit() is called).
For non-booleans, there may be ranges that are nonsensical. Ie, they maybe some analog variable going to a DAC. In these cases, the if(x > 2) a; else if(x < -2) b; else c; makes sense for cases where deadband should not have been sent, etc. However, these type of cases do not exist for a boolean.

Call a function when counter reaches some value without if statement

Lets say I have a function named loop(). In this loop() I increment a counter count.
I have few functions, A(), B(), C(), etc.
I want to call each one of these functions when the counter reaches some value (different for every function).
My current code looks like:
static unsigned int count = 0;
void loop(){
if (count == VALUE_ONE)
A();
if (count == VALUE_TWO)
B();
if (count == VALUE_THREE)
C();
..... //more cases
if (count == MAX_VAL)
count = 0;
else
count++;
}
VALUE_* are #defines so they are not being changed during the program.
Right now I am using regular if statements to check the counter value. But I want to avoid using the if statement to avoid branch mispredictions.
Is there a better way to do this? Something that will actually avoid branch mispredictions etc?
Edit:
The goal here is to optimize this part of code in order to make it in faster, as for now it sometimes doesn't finish until the time it should. I am aware that there might be a problem with function A(), B(), etc, but for now I am asking about this specific case.
To make it clear, VALUE_ONE, VALUE_TWO, VALUE_THREE, etc might be very large values and not increasing by 1. For example it might be:
#define VALUE_ONE 20
#define VALUE_TWO 1500
#define VALUE_THREE 99777
My compiler version is: gcc (GCC) 4.4.7
Why in the world are you worried about branch misprediction? Do you have a working program? Does it run too slowly? Have you narrowed the problem to branch misprediction in the code you present? Unless the answer to each of those questions is "yes", you are engaging in premature optimization.
Moreover, the conditional branches in the code you present appear to be highly predictable, at least if the counter is expected routinely to reach values in the tens or hundreds of thousands or more, as the updated example code seems to indicate. A misprediction rate on the order of 0.00001 or less -- which is about what you could expect -- will not have a measurable performance impact. Indeed, handling code such as you've presented is the bread and butter of branch prediction. You could hardly ask for a case more friendly to a branch-prediction unit.
In any event, since you are concerned about branch misprediction, your question must be not so much about avoiding the if statements in particular, but about avoiding conditional logic in general. As such, a switch construct probably is not better, at least not for the situation you describe, wherein you want to call functions only for a handful of the large number of distinct values the function will see, sprinkled across a wide range. Although the compiler could, in principle, implement such a switch via a jump table, it is unlikely to do so in your case because of how large the needed table would be, and how few of the elements would differ from the one for the default case.
A hash table has also been discussed, but that's no better, because then either you need conditional logic to distinguish between cache hits and cache misses, or else your hash table must for every input provide a function (pointer) to be called. Calling a function on every iteration would be far more costly than what you are doing now.
Additionally, you need a perfect hash function to avoid conditional logic in the HT implementation. If the possible values of your counter are bounded by a small enough number that a hash table / perfect hash could be used to avoid conditional logic, then a plain array of function pointers would be lighter-weight than a hash table, and could serve the same purpose. It would still have the same problem with function-call overhead, however. If you insist on avoiding conditional logic then this would probably be the best way to go for your particular problem. But don't.
Leave optimisations to the compiler in the first place. Concentrate on writing human-readable code. Optimise only iff you have a timing problem and after you profiled the code. Then concentrate on the hot-spots. If some code is good for branch-prediction is hard to predict with modern CPUs.
Use a switch (for an easier to read introduction please check a good C book) statement to make the code better readable:
switch ( count ) {
case VALUE_ONE:
f1();
break;
case VALUE_TWO:
f2();
break;
...
default:
// be aware to catch illegal/forgotten values, unless you
// are absolutely sure they can be ignored safely.
// still having a default label is good style to signal "I
// though about it".
break;
}
That is not only the most readable version, but also gives the compiler the best chance to optimize the code.
If the values are just increasing by 1 (1, 2, 3, ...), modern compilers will automatically generate a jump-table, even for partial successions (1, 2, 3, 7, 8, etc.), so that is as fast as a manually created function-table. If they are not, it still often will generate something like if ... else if ... else if ... constructs.
Note the case-labels must be constant-expressions.
Edit: After you clarified the values may not be adcascent, my answer still holds true. Depending on the number of compare-values, the switch still is the best solution unless prooved wrong. Try this first, profile and only optimise iff necessary. A hash-table might not be worth the effort.
Even if you'd use a hash-function, the switch above will come in handy. Just use the hash-value instead of count.
I'm skeptical whether the original function is a bottleneck or an effective place to be optimizing. But hey, I like puzzles...
Given that the count is incrementing and the match values are increasing, you really only need to test against the upcoming match value. And while you can't use your match values as an array index you could create states that can be used as an array index. Try something like this.
static unsigned int count = 0;
typedef enum
{
WAITING_FOR_VALUE_ONE = 0,
WAITING_FOR_VALUE_TWO,
WAITING_FOR_VALUE_THREE,
...,
WAITING_FOR_MAX_VALUE,
MAX_STATES
} MyStates;
static MyStates state = WAITING_FOR_VALUE_ONE;
void waitForValueOne()
{
if (count == VALUE_ONE)
{
A();
state++;
}
}
void waitForValueTwo()
{
if (count == VALUE_TWO)
{
B();
state++;
}
}
void waitForMaxValue()
{
if (count == MAX_VAL)
{
count = 0;
state = 0;
}
}
void (*stateHandlers[MAX_STATES]) () =
{
waitForValueOne,
waitForValueTwo,
waitForValueThree,
...
waitForMaxValue
}
void loop()
{
(*stateHandlers[state])();
count++;
}
After count reaches MAX_VAL, your original implementation will run the next loop with count = 0 whereas my implementation will run the next loop with count = 1. But I'm sure you can fix that if it's important.
Update:
I don't like how loop called the state handler every count. It really only needs to call the state handler when there is a match. And also the comparison doesn't need to be repeated in every state handler function if it's performed in loop. Here are a few edits that implement this improvement.
static MyStates state = WAITING_FOR_VALUE_ONE;
static unsigned int matchValue = VALUE_ONE;
void waitForValueOne()
{
A();
state++;
matchValue = VALUE_TWO;
}
void waitForValueTwo()
{
B();
state++;
matchValue = VALUE_THREE;
}
void waitForMaxValue()
{
count = 0;
state = 0;
matchValue = VALUE_ONE;
}
void loop()
{
if (count == matchValue)
{
(*stateHandlers[state])();
}
count++;
}
In your case I can't see any reason for an optimiziation.
But in the case your interrupt will be fired every 20µs and your handler consumes 50% of the complete cpu time, as you check aginst 200 values, then and only then you could change your code.
For an incrementing counter, you only need a single if as you always know which value will be the next one.
void isr(void)
{
count++;
if (count == nextValue)
{
if ( count == VALUE_ONE )
{
A();
nextValue=VALUE_TWO;
}
else if ( count == VALUE_TWO )
{
B();
nextValue=VALUE_THREE;
}
...
}
}
In 99% of the time, the ISR() only needs to increment the counter and check that the value isn't reached.
In reallity, I would use an array of actions and times, instead of the if else if block.

How to deal with function exits on a function that has several exit points?

I'm more of a student than I am a seasoned programmer and the other day I was refactoring a piece of code I wrote some time ago. In there, there was a function that was rather big in code size and had a structure like this:
if (eval)
return code;
...
if (different test)
return another code;
...
In all there were about 6 or 7 return points some of them with cleanup code inside of the branch. Some of them also responded to erroneous situations, paths where the function wouldn't fully process the input but rather return an error code.
Even though the code was commented and all it seemed to me hard on the eyes and difficult to read. So I was wondering if there are any best practices on the matter.
Reading code from all around the net I found different approaches to this matter. For example one would follow this scheme:
do {
whole body of the function;
while (false);
clean up code if necessary;
return code;
Mainly to be able to use break; sentences in different evaluations (since we were inside a loop) to exit the loop, do the cleanup if necessary and return the exit code. But that feels the same as gotos to me, with the limitation that they place to go to would only be forward in code.
Another one would be similar to mine, but have only one return statement at the end of the function and having a variable to hold error codes.
You can use goto for that.
code = firstCode;
if (condition != 0)
goto label;
code = secondCode;
if (anotherCondition != 0)
goto label;
label:
clean_up_code_if_necessary()
exit(code); // may be you should return from the function
but there could be many other options depending on the specific case.
Here is frequently used linux kernel idiom. When something fails, it rolls back and cleanup after previously executed code.
if(do_a()==FAIL)
goto fail_a;
if(do_b()==FAIL)
goto fail_c;
if(do_c()==FAIL)
goto fail_c;
/* rest of the code goes here */
/* if it's ok then set err to 0 and jump to ok */
err = 0;
goto ok;
// otherwise unroll what have been done
fail_c:
undo_c();
fail_b:
undo_b();
fail_a:
undo_a();
ok:
return err;
well , we need do differentiate between C and C++ , the way of handling things is quite different between C and C++.
In C , I would recommend use an Enum which states the current state of of the code , for example:
enum {State1,State2,Invalid_Argument,Error}
then , create a function that checkes whatever it needs, then return some constant from the enum above as return value:
int check_statement(arg1,arg2...)
and at last , use a switch case on the function above:
switch(check_statment(...)){
case state1:
...
return ...
case Error:
...
return..
}

Is there a typical state machine implementation pattern?

We need to implement a simple state machine in C.
Is a standard switch statement the best way to go?
We have a current state (state) and a trigger for the transition.
switch(state)
{
case STATE_1:
state = DoState1(transition);
break;
case STATE_2:
state = DoState2(transition);
break;
}
...
DoState2(int transition)
{
// Do State Work
...
if(transition == FROM_STATE_2) {
// New state when doing STATE 2 -> STATE 2
}
if(transition == FROM_STATE_1) {
// New State when moving STATE 1 -> STATE 2
}
return new_state;
}
Is there a better way for simple state machines
EDIT:
For C++, I think the Boost Statechart library might be the way to go. However, it does not help with C. Lets concentrate on the C use case.
I prefer to use a table driven approach for most state machines:
typedef enum { STATE_INITIAL, STATE_FOO, STATE_BAR, NUM_STATES } state_t;
typedef struct instance_data instance_data_t;
typedef state_t state_func_t( instance_data_t *data );
state_t do_state_initial( instance_data_t *data );
state_t do_state_foo( instance_data_t *data );
state_t do_state_bar( instance_data_t *data );
state_func_t* const state_table[ NUM_STATES ] = {
do_state_initial, do_state_foo, do_state_bar
};
state_t run_state( state_t cur_state, instance_data_t *data ) {
return state_table[ cur_state ]( data );
};
int main( void ) {
state_t cur_state = STATE_INITIAL;
instance_data_t data;
while ( 1 ) {
cur_state = run_state( cur_state, &data );
// do other program logic, run other state machines, etc
}
}
This can of course be extended to support multiple state machines, etc. Transition actions can be accommodated as well:
typedef void transition_func_t( instance_data_t *data );
void do_initial_to_foo( instance_data_t *data );
void do_foo_to_bar( instance_data_t *data );
void do_bar_to_initial( instance_data_t *data );
void do_bar_to_foo( instance_data_t *data );
void do_bar_to_bar( instance_data_t *data );
transition_func_t * const transition_table[ NUM_STATES ][ NUM_STATES ] = {
{ NULL, do_initial_to_foo, NULL },
{ NULL, NULL, do_foo_to_bar },
{ do_bar_to_initial, do_bar_to_foo, do_bar_to_bar }
};
state_t run_state( state_t cur_state, instance_data_t *data ) {
state_t new_state = state_table[ cur_state ]( data );
transition_func_t *transition =
transition_table[ cur_state ][ new_state ];
if ( transition ) {
transition( data );
}
return new_state;
};
The table driven approach is easier to maintain and extend and simpler to map to state diagrams.
You might have seen my answer to another C question where I mentioned FSM! Here is how I do it:
FSM {
STATE(x) {
...
NEXTSTATE(y);
}
STATE(y) {
...
if (x == 0)
NEXTSTATE(y);
else
NEXTSTATE(x);
}
}
With the following macros defined
#define FSM
#define STATE(x) s_##x :
#define NEXTSTATE(x) goto s_##x
This can be modified to suit the specific case. For example, you may have a file FSMFILE that you want to drive your FSM, so you could incorporate the action of reading next char into the the macro itself:
#define FSM
#define STATE(x) s_##x : FSMCHR = fgetc(FSMFILE); sn_##x :
#define NEXTSTATE(x) goto s_##x
#define NEXTSTATE_NR(x) goto sn_##x
now you have two types of transitions: one goes to a state and read a new character, the other goes to a state without consuming any input.
You can also automate the handling of EOF with something like:
#define STATE(x) s_##x : if ((FSMCHR = fgetc(FSMFILE) == EOF)\
goto sx_endfsm;\
sn_##x :
#define ENDFSM sx_endfsm:
The good thing of this approach is that you can directly translate a state diagram you draw into working code and, conversely, you can easily draw a state diagram from the code.
In other techniques for implementing FSM the structure of the transitions is buried in control structures (while, if, switch ...) and controlled by variables value (tipically a state variable) and it may be a complex task to relate the nice diagram to a convoluted code.
I learned this technique from an article appeared on the great "Computer Language" magazine that, unfortunately, is no longer published.
In Martin Fowler's UML Distilled, he states (no pun intended) in Chapter 10 State Machine Diagrams (emphasis mine):
A state diagram can be implemented in three main ways: nested switch, the State pattern, and
state tables.
Let's use a simplified example of the states of a mobile phone's display:
Nested switch
Fowler gave an example of C# code, but I've adapted it to my example.
public void HandleEvent(PhoneEvent anEvent) {
switch (CurrentState) {
case PhoneState.ScreenOff:
switch (anEvent) {
case PhoneEvent.PressButton:
if (powerLow) { // guard condition
DisplayLowPowerMessage(); // action
// CurrentState = PhoneState.ScreenOff;
} else {
CurrentState = PhoneState.ScreenOn;
}
break;
case PhoneEvent.PlugPower:
CurrentState = PhoneState.ScreenCharging;
break;
}
break;
case PhoneState.ScreenOn:
switch (anEvent) {
case PhoneEvent.PressButton:
CurrentState = PhoneState.ScreenOff;
break;
case PhoneEvent.PlugPower:
CurrentState = PhoneState.ScreenCharging;
break;
}
break;
case PhoneState.ScreenCharging:
switch (anEvent) {
case PhoneEvent.UnplugPower:
CurrentState = PhoneState.ScreenOff;
break;
}
break;
}
}
State pattern
Here's an implementation of my example with the GoF State pattern:
State Tables
Taking inspiration from Fowler, here's a table for my example:
Source State Target State Event Guard Action
--------------------------------------------------------------------------------------
ScreenOff ScreenOff pressButton powerLow displayLowPowerMessage
ScreenOff ScreenOn pressButton !powerLow
ScreenOn ScreenOff pressButton
ScreenOff ScreenCharging plugPower
ScreenOn ScreenCharging plugPower
ScreenCharging ScreenOff unplugPower
Comparison
Nested switch keeps all the logic in one spot, but the code can be hard to read when there are a lot of states and transitions. It's possibly more secure and easier to validate than the other approaches (no polymorphism or interpreting).
The State pattern implementation potentially spreads the logic over several separate classes, which may make understanding it as a whole a problem. On the other hand, the small classes are easy to understand separately. The design is particularly fragile if you change the behavior by adding or removing transitions, as they're methods in the hierarchy and there could be lots of changes to the code. If you live by the design principle of small interfaces, you'll see this pattern doesn't really do so well. However, if the state machine is stable, then such changes won't be needed.
The state tables approach requires writing some kind of interpreter for the content (this might be easier if you have reflection in the language you're using), which could be a lot of work to do up front. As Fowler points out, if your table is separate from your code, you could modify the behavior of your software without recompiling. This has some security implications, however; the software is behaving based on the contents of an external file.
Edit (not really for C language)
There is a fluent interface (aka internal Domain Specific Language) approach, too, which is probably facilitated by languages that have first-class functions. The Stateless library exists and that blog shows a simple example with code. A Java implementation (pre Java8) is discussed. I was shown a Python example on GitHub as well.
I also have used the table approach. However, there is overhead. Why store a second list of pointers? A function in C without the () is a const pointer. So you can do:
struct state;
typedef void (*state_func_t)( struct state* );
typedef struct state
{
state_func_t function;
// other stateful data
} state_t;
void do_state_initial( state_t* );
void do_state_foo( state_t* );
void do_state_bar( state_t* );
void run_state( state_t* i ) {
i->function(i);
};
int main( void ) {
state_t state = { do_state_initial };
while ( 1 ) {
run_state( state );
// do other program logic, run other state machines, etc
}
}
Of course depending on your fear factor (i.e. safety vs speed) you may want to check for valid pointers. For state machines larger than three or so states, the approach above should be less instructions than an equivalent switch or table approach. You could even macro-ize as:
#define RUN_STATE(state_ptr_) ((state_ptr_)->function(state_ptr_))
Also, I feel from the OP's example, that there is a simplification that should be done when thinking about / designing a state machine. I don't thing the transitioning state should be used for logic. Each state function should be able to perform its given role without explicit knowledge of past state(s). Basically you design for how to transition from the state you are in to another state.
Finally, don't start the design of a state machine based on "functional" boundaries, use sub-functions for that. Instead divide the states based on when you will have to wait for something to happen before you can continue. This will help minimize the number of times you have to run the state machine before you get a result. This can be important when writing I/O functions, or interrupt handlers.
Also, a few pros and cons of the classic switch statement:
Pros:
it is in the language, so it is documented and clear
states are defined where they are called
can execute multiple states in one function call
code common to all states can be executed before and after the switch statement
Cons:
can execute multiple states in one function call
code common to all states can be executed before and after the switch statement
switch implementation can be slow
Note the two attributes that are both pro and con. I think the switch allows the opportunity for too much sharing between states, and the interdependency between states can become unmanageable. However for a small number of states, it may be the most readable and maintainable.
there is also the logic grid which is more maintainable as the state machine gets bigger
For a simple state machine just use a switch statement and an enum type for your state. Do your transitions inside the switch statement based on your input. In a real program you would obviously change the "if(input)" to check for your transition points. Hope this helps.
typedef enum
{
STATE_1 = 0,
STATE_2,
STATE_3
} my_state_t;
my_state_t state = STATE_1;
void foo(char input)
{
...
switch(state)
{
case STATE_1:
if(input)
state = STATE_2;
break;
case STATE_2:
if(input)
state = STATE_3;
else
state = STATE_1;
break;
case STATE_3:
...
break;
}
...
}
switch() is a powerful and standard way of implementing state machines in C, but it can decrease maintainability down if you have a large number of states. Another common method is to use function pointers to store the next state. This simple example implements a set/reset flip-flop:
/* Implement each state as a function with the same prototype */
void state_one(int set, int reset);
void state_two(int set, int reset);
/* Store a pointer to the next state */
void (*next_state)(int set, int reset) = state_one;
/* Users should call next_state(set, reset). This could
also be wrapped by a real function that validated input
and dealt with output rather than calling the function
pointer directly. */
/* State one transitions to state one if set is true */
void state_one(int set, int reset) {
if(set)
next_state = state_two;
}
/* State two transitions to state one if reset is true */
void state_two(int set, int reset) {
if(reset)
next_state = state_one;
}
I found a really slick C implementation of Moore FSM on the edx.org course Embedded Systems - Shape the World UTAustinX - UT.6.02x, chapter 10, by Jonathan Valvano and Ramesh Yerraballi....
struct State {
unsigned long Out; // 6-bit pattern to output
unsigned long Time; // delay in 10ms units
unsigned long Next[4]; // next state for inputs 0,1,2,3
};
typedef const struct State STyp;
//this example has 4 states, defining constants/symbols using #define
#define goN 0
#define waitN 1
#define goE 2
#define waitE 3
//this is the full FSM logic coded into one large array of output values, delays,
//and next states (indexed by values of the inputs)
STyp FSM[4]={
{0x21,3000,{goN,waitN,goN,waitN}},
{0x22, 500,{goE,goE,goE,goE}},
{0x0C,3000,{goE,goE,waitE,waitE}},
{0x14, 500,{goN,goN,goN,goN}}};
unsigned long currentState; // index to the current state
//super simple controller follows
int main(void){ volatile unsigned long delay;
//embedded micro-controller configuration omitteed [...]
currentState = goN;
while(1){
LIGHTS = FSM[currentState].Out; // set outputs lines (from FSM table)
SysTick_Wait10ms(FSM[currentState].Time);
currentState = FSM[currentState].Next[INPUT_SENSORS];
}
}
For simple cases, you can use your switch style method. What I have found that works well in the past is to deal with transitions too:
static int current_state; // should always hold current state -- and probably be an enum or something
void state_leave(int new_state) {
// do processing on what it means to enter the new state
// which might be dependent on the current state
}
void state_enter(int new_state) {
// do processing on what is means to leave the current state
// might be dependent on the new state
current_state = new_state;
}
void state_process() {
// switch statement to handle current state
}
I don't know anything about the boost library, but this type of approach is dead simple, doesn't require any external dependencies, and is easy to implement.
You might want to look into the libero FSM generator software. From a state description language and/or a (windows) state diagram editor you may generate code for C, C++, java and many others ... plus nice documentation and diagrams.
Source and binaries from iMatix
This article is a good one for the state pattern (though it is C++, not specifically C).
If you can put your hands on the book "Head First Design Patterns", the explanation and example are very clear.
One of my favourite patterns is the state design pattern. Respond or behave differently to the same given set of inputs.
One of the problems with using switch/case statements for state machines is that as you create more states, the switch/cases becomes harder/unwieldy to read/maintain, promotes unorganized spaghetti code, and increasingly difficult to change without breaking something. I find using design patterns helps me to organize my data better, which is the whole point of abstraction.
Instead of designing your state code around what state you came from, instead structure your code so that it records the state when you enter a new state. That way, you effectively get a record of your previous state. I like #JoshPetit's answer, and have taken his solution one step further, taken straight from the GoF book:
stateCtxt.h:
#define STATE (void *)
typedef enum fsmSignal
{
eEnter =0,
eNormal,
eExit
}FsmSignalT;
typedef struct fsm
{
FsmSignalT signal;
// StateT is an enum that you can define any which way you want
StateT currentState;
}FsmT;
extern int STATECTXT_Init(void);
/* optionally allow client context to set the target state */
extern STATECTXT_Set(StateT stateID);
extern void STATECTXT_Handle(void *pvEvent);
stateCtxt.c:
#include "stateCtxt.h"
#include "statehandlers.h"
typedef STATE (*pfnStateT)(FsmSignalT signal, void *pvEvent);
static FsmT fsm;
static pfnStateT UsbState ;
int STATECTXT_Init(void)
{
UsbState = State1;
fsm.signal = eEnter;
// use an enum for better maintainability
fsm.currentState = '1';
(*UsbState)( &fsm, pvEvent);
return 0;
}
static void ChangeState( FsmT *pFsm, pfnStateT targetState )
{
// Check to see if the state has changed
if (targetState != NULL)
{
// Call current state's exit event
pFsm->signal = eExit;
STATE dummyState = (*UsbState)( pFsm, pvEvent);
// Update the State Machine structure
UsbState = targetState ;
// Call the new state's enter event
pFsm->signal = eEnter;
dummyState = (*UsbState)( pFsm, pvEvent);
}
}
void STATECTXT_Handle(void *pvEvent)
{
pfnStateT newState;
if (UsbState != NULL)
{
fsm.signal = eNormal;
newState = (*UsbState)( &fsm, pvEvent );
ChangeState( &fsm, newState );
}
}
void STATECTXT_Set(StateT stateID)
{
prevState = UsbState;
switch (stateID)
{
case '1':
ChangeState( State1 );
break;
case '2':
ChangeState( State2);
break;
case '3':
ChangeState( State3);
break;
}
}
statehandlers.h:
/* define state handlers */
extern STATE State1(void);
extern STATE State2(void);
extern STATE State3(void);
statehandlers.c:
#include "stateCtxt.h:"
/* Define behaviour to given set of inputs */
STATE State1(FsmT *fsm, void *pvEvent)
{
STATE nextState;
/* do some state specific behaviours
* here
*/
/* fsm->currentState currently contains the previous state
* just before it gets updated, so you can implement behaviours
* which depend on previous state here
*/
fsm->currentState = '1';
/* Now, specify the next state
* to transition to, or return null if you're still waiting for
* more stuff to process.
*/
switch (fsm->signal)
{
case eEnter:
nextState = State2;
break;
case eNormal:
nextState = null;
break;
case eExit:
nextState = State2;
break;
}
return nextState;
}
STATE State3(FsmT *fsm, void *pvEvent)
{
/* do some state specific behaviours
* here
*/
fsm->currentState = '2';
/* Now, specify the next state
* to transition to
*/
return State1;
}
STATE State2(FsmT *fsm, void *pvEvent)
{
/* do some state specific behaviours
* here
*/
fsm->currentState = '3';
/* Now, specify the next state
* to transition to
*/
return State3;
}
For most State Machines, esp. Finite state machines, each state will know what its next state should be, and the criteria for transitioning to its next state. For loose state designs, this may not be the case, hence the option to expose the API for transitioning states. If you desire more abstraction, each state handler can be separated out into its own file, which are equivalent to the concrete state handlers in the GoF book. If your design is simple with only a few states, then both stateCtxt.c and statehandlers.c can be combined into a single file for simplicity.
In my experience using the 'switch' statement is the standard way to handle multiple possible states. Although I am surpirsed that you are passing in a transition value to the per-state processing. I thought the whole point of a state machine was that each state performed a single action. Then the next action/input determines which new state to transition into. So I would have expected each state processing function to immediately perform whatever is fixed for entering state and then afterwards decide if transition is needed to another state.
There is a book titled Practical Statecharts in C/C++.
However, it is way too heavyweight for what we need.
For compiler which support __COUNTER__ , you can use them for simple (but large) state mashines.
#define START 0
#define END 1000
int run = 1;
state = START;
while(run)
{
switch (state)
{
case __COUNTER__:
//do something
state++;
break;
case __COUNTER__:
//do something
if (input)
state = END;
else
state++;
break;
.
.
.
case __COUNTER__:
//do something
if (input)
state = START;
else
state++;
break;
case __COUNTER__:
//do something
state++;
break;
case END:
//do something
run = 0;
state = START;
break;
default:
state++;
break;
}
}
The advantage of using __COUNTER__ instead of hard coded numbers is that you
can add states in the middle of other states, without renumbering everytime everything.
If the compiler doesnt support __COUNTER__, in a limited way its posible to use with precaution __LINE__
You can use minimalist UML state machine framework in c. https://github.com/kiishor/UML-State-Machine-in-C
It supports both finite and hierarchical state machine. It has only 3 API's, 2 structures and 1 enumeration.
The State machine is represented by state_machine_t structure. It is an abstract structure that can be inherited to create a state machine.
//! Abstract state machine structure
struct state_machine_t
{
uint32_t Event; //!< Pending Event for state machine
const state_t* State; //!< State of state machine.
};
State is represented by pointer to state_t structure in the framework.
If framework is configured for finite state machine then state_t contains,
typedef struct finite_state_t state_t;
// finite state structure
typedef struct finite_state_t{
state_handler Handler; //!< State handler function (function pointer)
state_handler Entry; //!< Entry action for state (function pointer)
state_handler Exit; //!< Exit action for state (function pointer)
}finite_state_t;
The framework provides an API dispatch_event to dispatch the event to the state machine and two API's for the state traversal.
state_machine_result_t dispatch_event(state_machine_t* const pState_Machine[], uint32_t quantity);
state_machine_result_t switch_state(state_machine_t* const, const state_t*);
state_machine_result_t traverse_state(state_machine_t* const, const state_t*);
For further details on how to implement hierarchical state machine refer the GitHub repository.
code examples
https://github.com/kiishor/UML-State-Machine-in-C/blob/master/demo/simple_state_machine/readme.md
https://github.com/kiishor/UML-State-Machine-in-C/blob/master/demo/simple_state_machine_enhanced/readme.md
In C++, consider the State pattern.
Your question is similar to "is there a typical Data Base implementation pattern"?
The answer depends upon what do you want to achieve? If you want to implement a larger deterministic state machine you may use a model and a state machine generator.
Examples can be viewed at www.StateSoft.org - SM Gallery. Janusz Dobrowolski
I would also prefer a table driven approach. I have used switch statements in the past. The main problem I have encountered is debugging transitions and ensuring that the designed state machine has been implemented properly. This occurred in cases where there was a large number of states and events.
With the table driven approach are the states and transitions are summarized in one place.
Below is a demo of this approach.
/*Demo implementations of State Machines
*
* This demo leverages a table driven approach and function pointers
*
* Example state machine to be implemented
*
* +-----+ Event1 +-----+ Event2 +-----+
* O---->| A +------------------->| B +------------------->| C |
* +-----+ +-----+ +-----+
* ^ |
* | Event3 |
* +-----------------------------------------------------+
*
* States: A, B, C
* Events: NoEvent (not shown, holding current state), Event1, Event2, Event3
*
* Partly leveraged the example here: http://web.archive.org/web/20160808120758/http://www.gedan.net/2009/03/18/finite-state-machine-matrix-style-c-implementation-function-pointers-addon/
*
* This sample code can be compiled and run using GCC.
* >> gcc -o demo_state_machine demo_state_machine.c
* >> ./demo_state_machine
*/
#include <stdio.h>
#include <assert.h>
// Definitions of state id's, event id's, and function pointer
#define N_STATES 3
#define N_EVENTS 4
typedef enum {
STATE_A,
STATE_B,
STATE_C,
} StateId;
typedef enum {
NOEVENT,
EVENT1,
EVENT2,
EVENT3,
} Event;
typedef void (*StateRoutine)();
// Assert on number of states and events defined
static_assert(STATE_C==N_STATES-1,
"Number of states does not match defined number of states");
static_assert(EVENT3==N_EVENTS-1,
"Number of events does not match defined number of events");
// Defining State, holds both state id and state routine
typedef struct {
StateId id;
StateRoutine routine;
} State;
// General functions
void evaluate_state(Event e);
// State routines to be executed at each state
void state_routine_a(void);
void state_routine_b(void);
void state_routine_c(void);
// Defining each state with associated state routine
const State state_a = {STATE_A, state_routine_a};
const State state_b = {STATE_B, state_routine_b};
const State state_c = {STATE_C, state_routine_c};
// Defning state transition matrix as visualized in the header (events not
// defined, result in mainting the same state)
State state_transition_mat[N_STATES][N_EVENTS] = {
{ state_a, state_b, state_a, state_a},
{ state_b, state_b, state_c, state_b},
{ state_c, state_c, state_c, state_a}};
// Define current state and initialize
State current_state = state_a;
int main()
{
while(1) {
// Event to receive from user
int ev;
printf("----------------\n");
printf("Current state: %c\n", current_state.id + 65);
printf("Event to occur: ");
// Receive event from user
scanf("%u", &ev);
evaluate_state((Event) ev); // typecast to event enumeration type
printf("-----------------\n");
};
return (0);
}
/*
* Determine state based on event and perform state routine
*/
void evaluate_state(Event ev)
{
//Determine state based on event
current_state = state_transition_mat[current_state.id][ev];
printf("Transitioned to state: %c\n", current_state.id + 65);
// Run state routine
(*current_state.routine)();
}
/*
* State routines
*/
void state_routine_a() {
printf("State A routine ran. \n");
}
void state_routine_b() {
printf("State B routine ran. \n");
}
void state_routine_c() {
printf("State C routine ran. \n");
}
Boost has the statechart library. http://www.boost.org/doc/libs/1_36_0/libs/statechart/doc/index.html
I can't speak to the use of it, though. Not used it myself (yet)

Resources