Quantcast
Channel: User Lundin - Code Review Stack Exchange
Viewing all articles
Browse latest Browse all 42

Answer by Lundin for Simple state machine

$
0
0

Implementing state machines with a table with function pointers is very common. The table should however be read-only and preferably stored in flash. This does however seem to be some PC-like ARM with Linux?

The design with a centralized state transition decision-maker is particularly important and your program is well-written there. Picking next state, based on the result from the previous, should be done at one single place in the program, not in each individual state ("stateghetti programming"). With a centralized decision-maker, you can also easily implement a safe mode for the program where it goes upon certain critical errors.

Regarding the state machine/array:

  • typedef enum state_transitions - the enum tag state_transitions is useless and can be removed.
  • At the end of sbState enum, include a member for size such as sbStates or what you wish to call it. Then change the states[9] to states[] and static_assert(sizeof states/sizeof *states == sbStates, "states data inconsistent"); to guarantee data integrity.
  • Assuming char name[255]; will never change, then 255 bytes per array item is wasteful. A char* to a string literal will save loads of read-only memory over this.
  • states should be const.

So you could instead have something like:

static const sbStateDef states[] = {    [sbIdle] =        {"Idle", sbIdleState,           {{sbStartupTrans, sbStartup}, {sbSelfTestTrans, sbSelfTest}}},    [sbSelfTest] =    {"Self Test", sbSelfTestState,  {{sbStartupTrans, sbStartup}, {sbErr, sbIdle}}},    ...};static_assert(sizeof states/sizeof *states == sbStates, "states data inconsistent"); // C11

You can do similar with transitions. Overall, designated array initializers like above, that make use of the enum is strongly recommended for readability and data integrity.

General comments:

  • Never define variables in header files, ever. If you ever find yourself with the need to define a variable in a header, something has gone fundamentally wrong in your program design. In this case you could probably put both the allocation of the state machine and the calling code in main.c.
  • All the while(1) loops mean that you can't change states... I'm assuming this is just place-holders? Such loops are unacceptable in a hosted multi-process system such as Linux. You should probably consider porting this to pthreads and put the thread to sleep when it isn't working.

Viewing all articles
Browse latest Browse all 42

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>