Hey all,
I have a state machine design that needs to support playback. We have states that perform actions and sometimes need to generate random numbers. In case the program shuts down while in the middle of the FSM's execution, the program needs to playback the whole FSM using the same random numbers as before.
For a basic example, let's say I had three states: A, B, and C. The FSM will call a state's Execute() function. At the end of the function, the state will post an event, and the FSM will determine which state to go to next. In state A, it will call rand(). If the number is even, it will post an event to go to state B, otherwise state C should be the next state.
void StateA::Execute(IEventQueue& rQueue)
{
int num = rand();
if( num % 2 == 0 )
{
rQueue.PostEvent("GoToStateB");
}
else
{
rQueue.PostEvent("GoToStateC");
}
}
If the random number is 69, then it should go to state C. While in state C, it's possible that the program might quit. When the program starts up again, it should playback the state machine. Obviously, for this to work correctly, it can't generate a completely new random number, it needs to use 69 again for accurate playback.
I have a file stream interface that I can use for saving data to a file, but the code is a little ugly:
void StateA::Execute(IEventQueue& rQueue, IFileStream& rStream)
{
int num = 0;
// fails if there's no more data to read
bool bSuccess = rStream.ReadInt(num);
if (!bSucess)
{
num = rand();
rStream.WriteInt(num);
}
// same code as before
}
My only problem with this solution is that I don't care for having to check the stream for data first and then conditionally write to the same stream.
I thought about hiding it like this:
void StateA::Execute(IEventQueue& rQueue, IStream& rStream)
{
int num = 0;
num = rand();
rStream & num;
// same code as before
}
Inside IStream, operator& (probably not the best use of overloading) would actually try to read an int from the stream. If that stream was empty, it would then write it instead. Like before, the behavior would be: read first until the end of stream, and then start appending.
So I guess my question is: is there a common idiom for this type of playback that I might be overlooking? Does anyone have alternate suggestions? I feel like I'm starting to over-complicate the design a bit.
Thanks!