|
@@ -21,6 +21,8 @@
|
|
|
#include "config_express.h"
|
|
#include "config_express.h"
|
|
|
#include "numeric_types.h"
|
|
#include "numeric_types.h"
|
|
|
|
|
|
|
|
|
|
+#include "math.h" // for fabs()
|
|
|
|
|
+
|
|
|
TrueClock *TrueClock::_global_ptr = NULL;
|
|
TrueClock *TrueClock::_global_ptr = NULL;
|
|
|
|
|
|
|
|
#if defined(WIN32_VC)
|
|
#if defined(WIN32_VC)
|
|
@@ -41,6 +43,7 @@ static BOOL _has_high_res;
|
|
|
static PN_int64 _frequency;
|
|
static PN_int64 _frequency;
|
|
|
static PN_int64 _init_count;
|
|
static PN_int64 _init_count;
|
|
|
static long _init_sec;
|
|
static long _init_sec;
|
|
|
|
|
+static bool _paranoid_clock;
|
|
|
|
|
|
|
|
void get_true_time_of_day(ulong &sec, ulong &usec) {
|
|
void get_true_time_of_day(ulong &sec, ulong &usec) {
|
|
|
struct timeb tb;
|
|
struct timeb tb;
|
|
@@ -55,7 +58,30 @@ get_real_time() const {
|
|
|
LARGE_INTEGER count;
|
|
LARGE_INTEGER count;
|
|
|
QueryPerformanceCounter(&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 {
|
|
} else {
|
|
|
// No high-resolution clock; return the best information we have.
|
|
// No high-resolution clock; return the best information we have.
|
|
@@ -72,6 +98,8 @@ TrueClock() {
|
|
|
_has_high_res = QueryPerformanceFrequency((LARGE_INTEGER *)&_frequency);
|
|
_has_high_res = QueryPerformanceFrequency((LARGE_INTEGER *)&_frequency);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ _paranoid_clock = get_paranoid_clock();
|
|
|
|
|
+
|
|
|
if (_has_high_res) {
|
|
if (_has_high_res) {
|
|
|
LARGE_INTEGER count;
|
|
LARGE_INTEGER count;
|
|
|
QueryPerformanceCounter(&count);
|
|
QueryPerformanceCounter(&count);
|
|
@@ -93,6 +121,25 @@ TrueClock() {
|
|
|
ftime(&tb);
|
|
ftime(&tb);
|
|
|
_init_sec = tb.time;
|
|
_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
|
|
|
|
|
+
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|