Here is a sketch for a new inner loop, it separates the modes, but it also publishes the actual runstate so it can be queried, this should also fix the synchronous stepping to be blocking in the step() function as well. See this as a sketch, some of the variable types are not defined i.e. wether to be std::atomic<> or BufferedValue,
while (m_mode != stop && updateValid) {
switch m_mode:
{
// idle do nothing, just sleep
case idle:
boost::this_thread::sleep_for(500.0);
break;
// this is the same code as we have now
case normal:
if (m_period > frameTime)
{
sleepTime = m_period - frameTime;
boost::this_thread::sleep_until(Clock::now() + sleepTime);
}
start = Clock::now();
// Technically we can return false here if a thread wants to stop
// but currently this is not communicated to the other threads
// when one thread fails all operations that require a barrier
// will hang
// We are also still updating with a fixed frame rate for all threads
updateValid = doUpdate(m_period.count());
frameTime = Clock::now() - start;
break;
case synchronous:
// step() in the runtime will now have to do two barrier calls but this
// means it can actually block until all threads are back at the first
// barrier, ie. done with their update
waitForBarrier(true);
updateValid = doUpdate(m_period.count());
// Signify to the other threads if we will be running again or not
updateValid = waitForBarrier(updateValid);
break;
default:
continue;
}
// m_actualMode is used for querying the thread state, it could be used to
// busy wait for all threads to be in the same state
m_actualMode = m_mode;
}
m_actualMode = m_mode;