]> git.mxchange.org Git - flightgear.git/commitdiff
Updated hybrid of original busy-wait frame rate throttling loop combined with
authorcurt <curt>
Wed, 9 Mar 2005 21:56:00 +0000 (21:56 +0000)
committercurt <curt>
Wed, 9 Mar 2005 21:56:00 +0000 (21:56 +0000)
a safe undersleep() to conserve cpu.  Essentially we undersleep our target by
just a bit (to avoid the chance of oversleeping.)  Then we finish off the
remaining time slice with a busy-wait loop.

src/Main/main.cxx

index db569b84ee1d8ac2234e0fa73797a4c6fe407ce7..f1bb3174668eb31bbf6992dc7a71d2a5b2d487b1 100644 (file)
 #include <simgear/timing/sg_time.hxx>
 #include <simgear/math/sg_random.h>
 
-// Class refferences
+// Class references
 #include <simgear/ephemeris/ephemeris.hxx>
 #include <simgear/scene/model/modellib.hxx>
 #include <simgear/scene/material/matlib.hxx>
 #include <simgear/scene/model/animation.hxx>
 #include <simgear/scene/sky/sky.hxx>
 #include <Time/light.hxx>
-
-
-
 #include <Include/general.hxx>
 #include <Cockpit/cockpit.hxx>
 #include <Cockpit/hud.hxx>
@@ -233,19 +230,57 @@ static void fgMainLoop( void ) {
 
     double throttle_hz = fgGetDouble("/sim/frame-rate-throttle-hz", 0.0);
     if ( throttle_hz > 0.0 && scenery_loaded ) {
-        static double remainder = 0.0;
-
-        // simple frame rate throttle
-        double dt = 1000000.0 / throttle_hz + remainder;
-        int wait = dt / 1000;
-        remainder = dt - ( wait * 1000.0 );
-
+        // optionally throttle the frame rate (to get consistant frame
+        // rates or reduce cpu usage.
+
+        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 desireable.  Because of the way sleep()
+        // is implimented 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 to 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;
+        }
         current_time_stamp.stamp();
-        int t_ms = (int) ( ( current_time_stamp - last_time_stamp ) / 1000 ) ; /* Convert to ms */
-        if ( t_ms < wait ) {
-            ulMilliSecondSleep ( wait - t_ms ) ;
+        /* Convert to ms */
+        double elapsed_us = current_time_stamp - last_time_stamp;
+        if ( elapsed_us < frame_us ) {
+            double requested_us = frame_us - elapsed_us;
+            ulMilliSecondSleep ( (int)(requested_us / 1000.0) ) ;
         }
+#endif
+
+        // busy wait timing loop.
+        // 
+        // This yields the most accurate timing.  If the previous
+        // ulMilliSecondSleep() call is ommitted this will peg the cpu
+        // (which is just fine if FG is the only app you care about.)
         current_time_stamp.stamp();
+        while ( current_time_stamp - last_time_stamp < frame_us ) {
+            current_time_stamp.stamp();
+        }
     } else {
         // run as fast as the app will go
         current_time_stamp.stamp();