Bladeren bron

paranoid clock checking

David Rose 24 jaren geleden
bovenliggende
commit
0c2864e5ee

+ 0 - 41
panda/src/express/clockObject.I

@@ -113,47 +113,6 @@ reset() {
   set_frame_count(0);
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: ClockObject::set_real_time
-//       Access: Published
-//  Description: Resets the clock to the indicated time.  This
-//               changes only the real time of the clock as reported
-//               by get_real_time(), but does not immediately change
-//               the time reported by get_frame_time()--that will
-//               change after the next call to tick().  Also see
-//               reset(), set_frame_time(), and set_frame_count().
-////////////////////////////////////////////////////////////////////
-INLINE void ClockObject::
-set_real_time(double time) {
-  _start_time = _true_clock->get_real_time() - time;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: ClockObject::set_frame_time
-//       Access: Published
-//  Description: Changes the time as reported for the current frame to
-//               the indicated time.  Normally, the way to adjust the
-//               frame time is via tick(); this function is provided
-//               only for occasional special adjustments.
-////////////////////////////////////////////////////////////////////
-INLINE void ClockObject::
-set_frame_time(double time) {
-  _actual_frame_time = time;
-  _reported_frame_time = time;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: ClockObject::set_frame_count
-//       Access: Published
-//  Description: Resets the number of frames counted to the indicated
-//               number.  Also see reset(), set_real_time(), and
-//               set_frame_time().
-////////////////////////////////////////////////////////////////////
-INLINE void ClockObject::
-set_frame_count(int frame_count) {
-  _frame_count = frame_count;
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: ClockObject::get_frame_count
 //       Access: Published

+ 59 - 0
panda/src/express/clockObject.cxx

@@ -18,6 +18,7 @@
 
 
 #include "clockObject.h"
+#include "config_express.h"
 
 ClockObject *ClockObject::_global_clock = (ClockObject *)NULL;
 
@@ -39,6 +40,64 @@ ClockObject() {
   _max_dt = -1.0;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: ClockObject::set_real_time
+//       Access: Published
+//  Description: Resets the clock to the indicated time.  This
+//               changes only the real time of the clock as reported
+//               by get_real_time(), but does not immediately change
+//               the time reported by get_frame_time()--that will
+//               change after the next call to tick().  Also see
+//               reset(), set_frame_time(), and set_frame_count().
+////////////////////////////////////////////////////////////////////
+void ClockObject::
+set_real_time(double time) {
+#ifndef NDEBUG
+  if (this == _global_clock) {
+    express_cat.warning()
+      << "Adjusting global clock's real time by " << time - get_real_time()
+      << " seconds.\n";
+  }
+#endif  // NDEBUG
+  _start_time = _true_clock->get_real_time() - time;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ClockObject::set_frame_time
+//       Access: Published
+//  Description: Changes the time as reported for the current frame to
+//               the indicated time.  Normally, the way to adjust the
+//               frame time is via tick(); this function is provided
+//               only for occasional special adjustments.
+////////////////////////////////////////////////////////////////////
+void ClockObject::
+set_frame_time(double time) {
+  if (this == _global_clock) {
+    express_cat.warning()
+      << "Adjusting global clock's frame time by " << time - get_frame_time()
+      << " seconds.\n";
+  }
+  _actual_frame_time = time;
+  _reported_frame_time = time;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ClockObject::set_frame_count
+//       Access: Published
+//  Description: Resets the number of frames counted to the indicated
+//               number.  Also see reset(), set_real_time(), and
+//               set_frame_time().
+////////////////////////////////////////////////////////////////////
+void ClockObject::
+set_frame_count(int frame_count) {
+  if (this == _global_clock) {
+    express_cat.warning()
+      << "Adjusting global clock's frame count by " 
+      << frame_count - get_frame_count() << " frames.\n";
+  }
+  _frame_count = frame_count;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: ClockObject::tick
 //       Access: Published

+ 3 - 3
panda/src/express/clockObject.h

@@ -81,9 +81,9 @@ PUBLISHED:
   INLINE double get_real_time() const;
 
   INLINE void reset();
-  INLINE void set_real_time(double time);
-  INLINE void set_frame_time(double time);
-  INLINE void set_frame_count(int frame_count);
+  void set_real_time(double time);
+  void set_frame_time(double time);
+  void set_frame_count(int frame_count);
 
   INLINE int get_frame_count() const;
   INLINE double get_frame_rate() const;

+ 8 - 8
panda/src/express/config_express.cxx

@@ -88,15 +88,15 @@ get_never_destruct() {
 // it is available.
 bool
 get_use_high_res_clock() {
-  static bool got_use_high_res_clock = false;
-  static bool use_high_res_clock;
-
-  if (!got_use_high_res_clock) {
-    use_high_res_clock = config_express.GetBool("use-high-res-clock", true);
-    got_use_high_res_clock = true;
-  }
+  return config_express.GetBool("use-high-res-clock", true);
+}
 
-  return use_high_res_clock;
+// Set this to true to double-check the results of the high-resolution
+// clock against the system clock.  This has no effect if NDEBUG is
+// defined.
+bool
+get_paranoid_clock() {
+  return config_express.GetBool("paranoid-clock", false);
 }
 
 const int patchfile_window_size =

+ 1 - 0
panda/src/express/config_express.h

@@ -36,6 +36,7 @@ NotifyCategoryDecl(express, EXPCL_PANDAEXPRESS, EXPTP_PANDAEXPRESS);
 bool EXPCL_PANDAEXPRESS get_leak_memory();
 bool EXPCL_PANDAEXPRESS get_never_destruct();
 bool EXPCL_PANDAEXPRESS get_use_high_res_clock();
+bool EXPCL_PANDAEXPRESS get_paranoid_clock();
 
 extern const int patchfile_window_size;
 extern const int patchfile_increment_size;

+ 48 - 1
panda/src/express/trueClock.cxx

@@ -21,6 +21,8 @@
 #include "config_express.h"
 #include "numeric_types.h"
 
+#include "math.h"  // for fabs()
+
 TrueClock *TrueClock::_global_ptr = NULL;
 
 #if defined(WIN32_VC)
@@ -41,6 +43,7 @@ static BOOL _has_high_res;
 static PN_int64 _frequency;
 static PN_int64 _init_count;
 static long _init_sec;
+static bool _paranoid_clock;
 
 void get_true_time_of_day(ulong &sec, ulong &usec) {
   struct timeb tb;
@@ -55,7 +58,30 @@ get_real_time() const {
     LARGE_INTEGER count;
     QueryPerformanceCounter(&count);
 
-    return (double)(count.QuadPart - _init_count) / (double)_frequency;
+    double time = (double)(count.QuadPart - _init_count) / (double)_frequency;
+
+#ifndef NDEBUG
+    if (_paranoid_clock) {
+      // Now double-check the high-resolution clock against the system
+      // clock.
+      struct timeb tb;
+      ftime(&tb);
+      double sys_time = (double)(tb.time - _init_sec) + (double)tb.millitm / 1000.0;
+      if (fabs(time - sys_time) > 0.5) {
+        // Too much variance!
+        express_cat.error()
+          << "Clock error!  High resolution clock reads " << time 
+          << " while system clock reads " << sys_time << ".\n";
+        _init_count = 
+          (PN_int64)(count.QuadPart - sys_time * (double)_frequency);
+        time = (double)(count.QuadPart - _init_count) / (double)_frequency;
+        express_cat.error()
+          << "High resolution clock reset to " << time << ".\n";
+      }
+    }
+#endif  // NDEBUG
+
+    return time;
 
   } else {
     // No high-resolution clock; return the best information we have.
@@ -72,6 +98,8 @@ TrueClock() {
     _has_high_res = QueryPerformanceFrequency((LARGE_INTEGER *)&_frequency);
   }
 
+  _paranoid_clock = get_paranoid_clock();
+
   if (_has_high_res) {
     LARGE_INTEGER count;
     QueryPerformanceCounter(&count);
@@ -93,6 +121,25 @@ TrueClock() {
     ftime(&tb);
     _init_sec = tb.time;
   }
+#ifndef NDEBUG
+  else if (_paranoid_clock) {
+    express_cat.warning()
+      << "Not trusting the high resolution clock." << endl;
+
+    struct timeb tb;
+    ftime(&tb);
+    _init_sec = tb.time;
+
+    // Also set the QueryPerformance counter to exactly match the sys
+    // time, before we get started.
+    double sys_time = (double)(tb.time - _init_sec) + (double)tb.millitm / 1000.0;
+    LARGE_INTEGER count;
+    QueryPerformanceCounter(&count);
+    _init_count = 
+      (PN_int64)(count.QuadPart - sys_time * (double)_frequency);
+  }
+#endif
+
 }