BasicThread Inner Loop

6 views
Skip to first unread message

Harald Scheirich

unread,
Nov 26, 2014, 8:01:01 AM11/26/14
to openSurgSim
There are a few small issues with the basic thread inner loop, we recently fixed some problems when shutting down threads, but technically the loop is not quite thread safe when changing states, also we cannot correctly the actual state the thread is in (we might want it to idle but it has not completed its last update). Additionally the synchronous mode is only synchronous in starting the update of all thread, again we don't know when the threads have finished their update calls. 

Knowing when update has finished, or knowing when the states have been actually reached (idle for example) helps us performing other operations, when shutting down the simulation we set all the threads to idle to prevent interactions. Right now we can't know when the threads are actually idling. This caused us to have to use a wait to make sure that all threads had actually entered idle, which cause a lot of the unit tests to slow down.

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, 

// m_mode used for setting the run state
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;

What do you think ?

Thanks, Harry

--
Harald Scheirich
Principal Software Engineer
Simquest Solutions Inc. 
Reply all
Reply to author
Forward
0 new messages