I have a program that uses an external API which uses its own state. The program stores the initial state at the beginning. Afterwards, dozens of functions are invoked using a dispatcher depending on the input. Each of them alters the current state using the API. One of the functions should be able to reset the current state to the initial. Although, that would require access to the variable/constant set at the beginning, which is out of scope in the function.
One solution would be a global, which is considered evil. Another solution could be a function with a static variable to store the initial state at its first call. Calling it again would return the static state. Although, this is not really an improvement.
Is there any clean, maintainable solution to this problem?
Edit: OK, let's say I'll use a const global after all. To illustrate it, I'll use the following code:
extern int get_state();
extern void set_state(int);
const int initial_state = get_state();
int main()
{
while(1) {
// call dispatcher, eventually
break;
}
set_state(initial_state);
return 0;
}
The problem is that the initializer of initial_state must be constant, which get_state() apparently isn't. Is there any way to work around this?
Globals aren't evil (especially if constant).
Any other solution would likely be ugly and would have a better chance of introducing bugs.
You can make use of Singleton design pattern. With this you can share the common state in a cleaner and controlled manner.
Here is the Code for your reference.
In State.h
State *getState(void);
In State.c
static State *g_state;
State* getState(void)
{
if(g_state == NULL) // not initialized
{
// Allocate Memory and initialize it
}
else
{
// operate on it if necessary. Can have mutex, semaphore based on your Use Case.
return g_state;
}
}
Here even though common state is a Global Variable, it is not accessible outside getState() function, hence no evil of using Global variable!!
Shash
Related
I've coded a stateflow handler and to reduce the risk of using the state flow enums outside the stateflow handler, I've defined the stateflow enums inside the function bloc.
My code looks like:
static void RequestHandler(bool isThisRequestANewRequest)
{
typedef enum
{
STATE_NEW_REQUEST,
STATE_1,
STATE_2,
STATE_ERROR,
} States;
static States state = STATE_ERROR;
if(isThisRequestANewRequest == true)
{
state = STATE_NEW_REQUEST;
}
switch(state)
{
case STATE_NEW_REQUEST:
//init request flags
state = STATE_1;
//lint -fallthrough
case STATE_1:
//do something
break;
case STATE_2:
//do something else
break;
case STATE_ERROR:
default:
//do something in case of error
break;
}
}
Is this can be considered as a good practice? Is there any risk? Is there any cons? (maintenance, reading, ...)
One collegue of mine told me that this was not, but I'm waiting for fact based answers, not just raw opinions.
Note: My question applies to both monothreaded and multithreaded tasks.
Generally, reducing scope as much as possible is good practice. If you want some sort of canonical reference to that, the closest I can come up with is MISRA-C:2012, rule 8.9 which recommends that objects that are only used by a single function should be declared at block scope. I don't see why the same wouldn't apply to types.
It is however bad practice to rely on fall-through in switch statements, since that blocks static analysers (like Lint in this case) from finding real bugs caused by missing break. It also makes the code harder to read and maintain - I would personally consider fall-through switches much worse practice than code repetition.
If you are to execute multiple states per function call, consider using simple if statements:
if(state == STATE_NEW_REQUEST)
{
...
state = STATE_1;
}
if(state == STATE_1)
{
...
}
Otherwise, if you are only executing one state per function call, you can use a switch. In general, the need to "execute several states per state" is a hint that the broader program design could be improved.
Going by the requirements of pure method(a method which has no side effects on outside world), I have found most of the times static methods meeting this requirement. We can't access instance variables in static method, so it greatly reduces chances of side effects. Then mostly we use static methods to do some computations based on input values and just return new value...inputs are rarely mutated.
So can it be said that static methods are good enough replacement of pure methods.
No. Just being static does not make a function pure.
In purely functional programming the outcome of the function should depend only on their arguments, regardless of global state. Static functions can easily access and modify global state.
Any useful pure function must return a value. Static functions can and often are declared to be void, which makes no sense for a pure function.
Pure functions should produce the same result for the same input each time. Any static function using a static counter could break that rule.
In Java , for example, streams objects are functional in nature. Their functions, such as filter() , are not static, but maintain the immutability of the stream data by producing a new stream instead of modifying the original stream object.
That being said, its easier for static functions to have no side effects, since they have 1 less thing to worry about modifying - their own instance state. Instance functions need to refrain from modifying both their own instance state, and global static state.
So I have seen that many suggestions on implementing a state machine in C involve a state struct or the like, but I was wondering why we can't just use a while(1) for very simple state machines. For example,
int currentstate = state1;
void state1function(){
dosomething();
if(user chooses to go to state 2){
currentstate = state2;
}
}
int main{
while(1){
if(currentstate == state1){
state1function();
}
else if (currenstate == state2){
state2function();
}
Basically keeping track of the state in a global variable, and in the while loop calling a function depending on the state. This seems simple to me and i don't really see why it wouldn't work.
Can anyone please tell me why something like this would not work/would not be recommended?
Thanks
Sooner or later, using this approach, you will find that it would be convenient to have:
An explicit transition table.
OnEntry(), OnExit(), Do(), OnEvent() functions for each state.
Actions performed on a transition.
Guards. (explicit conditions for transitions to be triggered)
Nested state machines.
Concurrent state machines. Meaning: Multiple FSM running next to each other.
Communicating concurrent, nested state machines.
Somewhere along this ladder of sophistication, you will most likely abandon the brute force style, you started with, which might have looked like the code you gave in your question.
The while(1) construct is quite unrelated to state machines. It is used whenever a single thread of execution (main() or OS threads) are long-running, as they typically are on embedded systems or server-applications. If the application is written in form of a state machine or in other forms, does not really matter.
Depending on the problem you're trying to solve, a global or a static is a straightforward solution. Using a struct comes in handy when you need to manage more than one state machine at a time, and/or when you need to change state from more than one thread or process.
The while loop without wait will consume lot of CPU. I think an event mechanism using mutex or seamphores will be useful.
C is not asynchronous (by default). An infinite loop will just cause your program to "freeze" until the results are done.
I have a problem with here:
void DrawState(){
char statevar[1000] = {0};
//bla bla bla
something = showmenu(); // or showscreen() or showinput()
if(something){
// change state
state = new_state;
}else{
// return to previous state
state = return_state;
}
// draw new state here.
DrawState();
}
I need this function to run when state changes. But when I do write like this recursively, it consumes too much memory and eventually it crashes the system. When I don't do this, I don't have any idea how to call itself from outside.
Does someone have any idea?
Edit: This is a library that runs over a manager software, like a plugin. Background jobs need to work too with this implementation. Maybe I should run this on some event.
It sounds like what you want doesn't involve recursion, per se, but rather simply a callback.
When you need to run some code whenever something in your code changes, you want to implement the Observer pattern. A simple C implementation might use a function pointer to hold the function that will be run when the data monitored is updated.
For example, you could separate your update function:
void DrawState() {
// ...
}
And then, you could maintain a pointer to it
int (*updateDraw)() = DrawState
And then do...
if (updated) {
// when updated
updateDraw()
}
What is the best way to write a state machine in C?
I usually write a big switch-case statement in a for(;;), with callbacks to re-enter the state machine when an external operation is finished.
Do you know a more efficient way?
I like the Quantum Leaps approach.
The current state is a pointer to a function that takes an event object as argument. When an event happens, just call the state function with that event; The function can then do its work and transition to another state by just setting the state to another function.
E.g.:
// State type and variable, notice that it's a function pointer.
typedef void (*State)(int);
State state;
// A couple of state functions.
void state_xyz(int event) { /*...*/ }
void state_init(int event) {
if (event == E_GO_TO_xyz) {
// State transition done simply by changing the state to another function.
state = state_xyz;
}
}
// main contains the event loop here:
int main() {
int e;
// Initial state.
state = state_init;
// Receive event, dispatch it, repeat... No 'switch'!
while ((e = wait_for_event()) != E_END) {
state(e);
}
return 0;
}
The QL frameworks provides helpers for extra things like entry/exit/init actions, hierarchical state machines, etc. I highly recommend the book for a deeper explanation and good implementation of this.
The best way is largely subjective, but a common way is to use a "table-based" approach where you map state codes (enums or some other integral type) to function pointers. The function returns your next state and other associated data and you loop through this until the terminal state is reached. This might in fact be what you are describing as your approach above.
That's pretty much the standard approach. If you're interested in studying a well considered library and comparing specifics, take a look at Ragel:
Ragel compiles executable finite state machines from regular languages. Ragel targets C, C++, Objective-C, D, Java and Ruby. Ragel state machines can not only recognize byte sequences as regular expression machines do, but can also execute code at arbitrary points in the recognition of a regular language. Code embedding is done using inline operators that do not disrupt the regular language syntax.
Switch statements are a good way to get started, but they tend to get unwieldy when the FSM gets larger.
A couple related (or duplicate) SO questions with great information and ideas:
state machines tutorials
C state-machine design
I used this pattern. Is there a typical state machine implementation pattern? (check best answer).
But i also add some features
1. Information about previous state.
2. Parameter passing
3. Adding external events like global timeout and "resseting SM"
I found state machines little less cryptic and maintainable.
Anyway, I still think state machines are most difficult and annoying programming task.(I got so far)
An alternative approach is a 2D array that describes for each state/event combination the actions to execute and the next state to go to. This can get trickier to manage when you need to transition to different states depending on 'circumstances', but it can be made to work well. You have an event recognizer function which returns the next event; you have the table where each entry in the table identifies the function to call on receiving the event and the next state to go to - unless the called function overrides that state.
Actually generating such code is fiddlier - it depends on how the FSM is described in the first place. Spotting duplicate actions is often important. Often, you can rely on 'sparse matrix' techniques that do not record error handling explicitly: if the entry logically exists in the sparse matrix, you act on that event/state information, but if the entry does not exist you fall back onto appropriate error reporting and resynchronization code.
A 2D array of pointers to structures can be passed into a generic FSM function; the fact that you write a triple-pointer is enough to make you cautious about what is going on. (I wrote one of those back in March 1986 - I don't have the source for that on disk any more, though I do still have a printout of the document that described it.)
Have a look here: http://code.google.com/p/fwprofile/
It's an open source version (GNU GPLv3) of the state machine implemented
in C. The concept and implementation is well-suited for use in
mission-critical applications. There are deployments in industrial
applications.
I use function pointers and a 2d look-up table where I use the state for one parameter and the event as the other.
I use excel (or any spreadsheet tool) to map a function to every state/event combination.
When an event occurs, I que it up, so then I have something that looks like this
int main(void)
{
StateList currentState = start_up;
EventList currentEvent;
uint8_t stateArray[STATE_COUNT][EVENT_COUNT];
InitializeStateArray(stateArray);
InitializeEventQue();
while(1)
{
currentEvent = GetPriorityEvent();
currentState = (StateList)(*(stateArray[currentState][currentEvent]))();
}
return 1; //should never get here
}
This method essentially forces the developer to consider all possible events in each state, and in my experience makes debugging a little easier.
You can use minimalist uml-state-machine framework implemented in c. It supports both finite and hierarchical state machine. The framework is very minimalist. 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;
If framework is configured to support hierarchical state machine. It contains additional three members to represent the hierarchical relation between the states.
typedef struct hierarchical_state_t state_t;
//! Hierarchical state structure
typedef struct hierarchical_state_t
{
state_handler Handler; //!< State handler function
state_handler Entry; //!< Entry action for state
state_handler Exit; //!< Exit action for state.
const state_t* const Parent; //!< Parent state of the current state.
const state_t* const Node; //!< Child states of the current state.
uint32_t Level; //!< Hierarchy level from the top state.
}hierarchical_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 pState_Machine, const state_t* pTarget_State);
state_machine_result_t traverse_state(state_machine_t* const pState_Machine, const state_t* pTarget_State);
For more details refer to GitHub project.
check this out "https://github.com/knor12/NKFSMCompiler" it helps generate C Language code for a state machine defined in an scxml or csv file. an example is provided.