I work with embedded stuff, and I have some software module that manages hardware. This module has state, and state transitions are complicated: depending on events, the module could go from state A
to state B
or probably to C
. But, when it exits some state, it should perform some actions with the hardware, in order to keep it in correct state too.
For rather simple modules, I just have a couple of functions like this:
enum state_e {
MY_STATE__A,
MY_STATE__B,
};
static enum state_e _cur_state;
void state_on_off(enum state_e state, bool on)
{
switch (state){
case MY_STATE__A:
if (on){
//-- entering the state A
prepare_hardware_1(for_state_a);
prepare_hardware_2(for_state_a);
} else {
//-- exiting the state A
finalize_hardware_2(for_state_a);
finalize_hardware_1(for_state_a);
}
break;
case MY_STATE__B:
if (on){
//-- entering the state B
prepare_hardware_1(for_state_b);
prepare_hardware_2(for_state_b);
} else {
//-- exiting the state B
finalize_hardware_2(for_state_b);
finalize_hardware_1(for_state_b);
}
break;
}
}
void state_set(enum state_e new_state)
{
state_on_off(_cur_state, false);
_cur_state = new_state;
state_on_off(_cur_state, true);
}
Obviously, we need to keep all necessary actions for all states in the _state_on_off()
function, and when we need to move to another state, we just call _state_set(new_state)
and state transition goes smoothly independently of the direction: all needed actions are performed.
But it works for simple situations only. What if we have something in common between states MY_STATE__B
and MY_STATE__C
, so that when state is changed from MY_STATE__B
to MY_STATE__C
and back we should perform only shortened desctruction / construction? But when we go to some other state (say, to MY_STATE__A
), we should perform full destruction.
What comes to mind is substates. So we have one state MY_STATE__BC
, and substates like MY_BC_SUBSTATE__B
and MY_BC_SUBSTATE__C
; and of course we have its own function like _state_bc_on_off()
. Even this is already a pain, but imagine something more complicated: it goes terrible.
So, what are the best practices for things like that?