Reputation: 511
I have a software state machine that works using via an event driven function calls. Namely, I have a state machine handle to a struct that contains a function pointer representing the current state:
typedef struct pHandle_t pHandle_t;
typedef void(*pState_f)(pHandle_t *pHandle, pEvent_t pEvent);
struct pHandle_t
{
pState_f curState;
void *contextPtr; // Is this needed?
};
Each state is then represented by a function that takes a handle to itself and an event as input:
static void SM_Init(pHandle_t *pHandle, pEvent_t pEvent);
Within each function there is a switch/case on the pEvent that usually produces some action as well as changing the curState function pointer to change to the function representing the state. All of this code works very well while using global variables to determine when certain state changes are done. (This type of approach obviously would not work well with function instantiated variables to try and know when to stop).
However, in the interest of reducing global variables and functions, I would like to implement a more object oriented approach, so that my globals and instruction memory go away once the state machine has reached a complete state. I know there are several examples of how to make code appear object oriented in regular C, but there is one wrench in the gears here: External modules need to be able to send events to this state machine without having a pointer to the state machine handle. How can I do this without requiring the overall state machine object be declared as a global (which really defeats the original intent of trying to free all that space once I was done with it)?
I apologize in advance if some of this wording is confusing. I believe this is a very useful topic so I will reword as requested, but please comment before downvoting me... Also before anyone asks, the existing code base is all C and suggesting C++ falls on deaf ears, despite all my efforts.
Upvotes: 3
Views: 526
Reputation: 19494
This is probably a terrible idea, but as such, it may help to convince your peers to let you store one little, measly pointer where you need it.
If all you have to identify instances of state machine objects is the callback-function pointer, then to have multiple machines running, you'll need duplicates of all the functions so that different pointers can be functionally-identical, but compare differently when cast to char *
.
So for two machines, you'll need roughly double the code size. Three machines: triple. Etc.
<shudder>
Upvotes: 3