]> git.mxchange.org Git - flightgear.git/commitdiff
Make use of SGTimeStamp::sleepUntil for accurate sleeping.
authorMathias Froehlich <Mathias.Froehlich@web.de>
Fri, 28 Oct 2011 15:02:19 +0000 (17:02 +0200)
committerMathias Froehlich <Mathias.Froehlich@web.de>
Fri, 28 Oct 2011 15:43:47 +0000 (17:43 +0200)
For use with frame rate throtteling make use of
SGTimeStamp::sleepUntil. This function should cover the
system dependent parts of accurate sleeps and should
move the system dependent code out of the time manager.

src/Time/TimeManager.cxx

index 52b385e378fd3662f2da9cd3a3f069520e4bdd23..5c5fd01a0033b269b6cfe08ba4fd88dcf828067c 100644 (file)
 
 #include "TimeManager.hxx"
 
-#ifdef _WIN32
-#  define WIN32_LEAN_AND_MEAN
-#  include <windows.h> // for Sleep()
-#else
-#  include <unistd.h> // for usleep()
-#endif
-
 #include <simgear/timing/sg_time.hxx>
 #include <simgear/structure/event_mgr.hxx>
 #include <simgear/misc/sg_path.hxx>
@@ -284,69 +277,13 @@ void TimeManager::computeFrameRate()
 
 void TimeManager::throttleUpdateRate()
 {
-  double throttle_hz = fgGetDouble("/sim/frame-rate-throttle-hz", 0.0);
-  SGTimeStamp currentStamp;
-  
   // common case, no throttle requested
-  if (throttle_hz <= 0.0) {
+  double throttle_hz = fgGetDouble("/sim/frame-rate-throttle-hz", 0.0);
+  if (throttle_hz <= 0)
     return; // no-op
-  }
-  
-  double frame_us = 1000000.0 / throttle_hz;
-#define FG_SLEEP_BASED_TIMING 1
-#if defined(FG_SLEEP_BASED_TIMING)
-  // sleep based timing loop.
-  //
-  // Calling sleep, even usleep() on linux is less accurate than
-  // we like, but it does free up the cpu for other tasks during
-  // the sleep so it is desirable.  Because of the way sleep()
-  // is implemented in consumer operating systems like windows
-  // and linux, you almost always sleep a little longer than the
-  // requested amount.
-  //
-  // To combat the problem of sleeping too long, we calculate the
-  // desired wait time and shorten it by 2000us (2ms) to avoid
-  // [hopefully] over-sleep'ing.  The 2ms value was arrived at
-  // via experimentation.  We follow this up at the end with a
-  // simple busy-wait loop to get the final pause timing exactly
-  // right.
-  //
-  // Assuming we don't oversleep by more than 2000us, this
-  // should be a reasonable compromise between sleep based
-  // waiting, and busy waiting.
-
-  // sleep() will always overshoot by a bit so undersleep by
-  // 2000us in the hopes of never oversleeping.
-  frame_us -= 2000.0;
-  if ( frame_us < 0.0 ) {
-      frame_us = 0.0;
-  }
-  
-  currentStamp.stamp();
 
-  double elapsed_us = (currentStamp - _lastStamp).toUSecs();
-  if ( elapsed_us < frame_us ) {
-    double requested_us = frame_us - elapsed_us;
-#ifdef _WIN32
-    Sleep ((int)(requested_us / 1000.0)) ;
-#else
-    usleep(requested_us) ;
-#endif
-  }
-#endif
-
-  // busy wait timing loop.
-  //
-  // This yields the most accurate timing.  If the previous
-  // ulMilliSecondSleep() call is omitted this will peg the cpu
-  // (which is just fine if FG is the only app you care about.)
-  currentStamp.stamp();
-  SGTimeStamp next_time_stamp = _lastStamp;
-  next_time_stamp += SGTimeStamp::fromSec(1e-6*frame_us);
-  while ( currentStamp < next_time_stamp ) {
-      currentStamp.stamp();
-  }
+  // sleep for exactly 1/hz seconds relative to the past valid timestamp
+  SGTimeStamp::sleepUntil(_lastStamp + SGTimeStamp::fromSec(1/throttle_hz));
 }
 
 // periodic time updater wrapper