Browse Source

Subtract start time before double conversion

To preserve precision the subtraction of the start time happens with
integer values now and the platform specific implementations have been
split completely.
Joel Schumacher 5 years ago
parent
commit
0a5db1ba6d
2 changed files with 64 additions and 45 deletions
  1. 64 39
      src/modules/timer/Timer.cpp
  2. 0 6
      src/modules/timer/Timer.h

+ 64 - 39
src/modules/timer/Timer.cpp

@@ -35,15 +35,6 @@
 #include <sys/time.h>
 #endif
 
-#if defined(LOVE_LINUX)
-static inline double getTimeOfDay()
-{
-	timeval t;
-	gettimeofday(&t, NULL);
-	return (double) t.tv_sec + (double) t.tv_usec / 1000000.0;
-}
-#endif
-
 namespace love
 {
 namespace timer
@@ -109,58 +100,92 @@ double Timer::getAverageDelta() const
 	return averageDelta;
 }
 
-double Timer::getTimerPeriod()
+#if defined(LOVE_LINUX)
+
+static inline timespec getTimeOfDay()
 {
-#if defined(LOVE_MACOSX) || defined(LOVE_IOS)
-	mach_timebase_info_data_t info;
-	mach_timebase_info(&info);
-	return (double) info.numer / (double) info.denom / 1000000000.0;
-#elif defined(LOVE_WINDOWS)
-	LARGE_INTEGER temp;
-	if (QueryPerformanceFrequency(&temp) != 0 && temp.QuadPart != 0)
-		return 1.0 / (double) temp.QuadPart;
-#endif
-	return 0;
+	timeval t;
+	gettimeofday(&t, NULL);
+	return timespec { t.tv_sec, t.tv_usec * 1000 };
 }
 
-double Timer::getTimeAbsolute()
+static timespec getTimeAbsolute()
 {
-	// The timer period (reciprocal of the frequency.)
-	static const double timerPeriod = getTimerPeriod();
-
-#if defined(LOVE_LINUX)
-	(void) timerPeriod; // Unused on linux
-
-	double mt;
 	// Check for POSIX timers and monotonic clocks. If not supported, use the gettimeofday fallback.
 #if _POSIX_TIMERS > 0 && defined(_POSIX_MONOTONIC_CLOCK) \
 && (defined(CLOCK_MONOTONIC_RAW) || defined(CLOCK_MONOTONIC))
-	timespec t;
+
 #ifdef CLOCK_MONOTONIC_RAW
 	clockid_t clk_id = CLOCK_MONOTONIC_RAW;
 #else
 	clockid_t clk_id = CLOCK_MONOTONIC;
 #endif
+
+	timespec t;
 	if (clock_gettime(clk_id, &t) == 0)
-		mt = (double) t.tv_sec + (double) t.tv_nsec / 1000000000.0;
+		return t;
 	else
+		return getTimeOfDay();
 #endif
-		mt = getTimeOfDay();
-	return mt;
+	return getTimeOfDay();
+}
+
+double Timer::getTime()
+{
+	static const timespec start = getTimeAbsolute();
+	const timespec now = getTimeAbsolute();
+	const timespec rel = timespec {
+		now.tv_sec - start.tv_sec,
+		now.tv_nsec - start.tv_nsec
+	};
+	return (double) rel.tv_sec + (double) rel.tv_nsec / 1.0e9;
+}
+
 #elif defined(LOVE_MACOSX) || defined(LOVE_IOS)
-	return (double) mach_absolute_time() * timerPeriod;
+
+static mach_timebase_info_data_t getTimebaseInfo()
+{
+	mach_timebase_info_data_t info;
+	mach_timebase_info(&info);
+	return info;
+}
+
+double Timer::getTime()
+{
+	static const mach_timebase_info_data_t info = getTimebaseInfo();
+	static const uint64_t start = mach_absolute_time();
+	const uint64_t rel = mach_absolute_time() - start;
+	return ((double) rel * 1.0e-9) * (double) info.number / (double) info.denom;
+}
+
 #elif defined(LOVE_WINDOWS)
-	LARGE_INTEGER microTime;
-	QueryPerformanceCounter(&microTime);
-	return (double) microTime.QuadPart * timerPeriod;
-#endif
+
+static LARGE_INTEGER getTimeAbsolute()
+{
+	LARGE_INTEGER t;
+	QueryPerformanceCounter(&t);
+	return t;
+}
+
+static LARGE_INTEGER getFrequency()
+{
+	LARGE_INTEGER freq;
+	// "On systems that run Windows XP or later, the function will always succeed and will thus never return zero."
+	QueryPerformanceFrequency(&freq);
+	return freq;
 }
 
 double Timer::getTime()
 {
-	static const double start = getTimeAbsolute();
-	return getTimeAbsolute() - start;
+	static const LARGE_INTEGER freq = getFrequency();
+	static const LARGE_INTEGER start = getTimeAbsolute();
+	const LARGE_INTEGER now = getTimeAbsolute();
+	LARGE_INTEGER rel;
+	rel.QuadPart = now.QuadPart - start.QuadPart;
+	return rel.QuadPart / freq.QuadPart;
 }
 
+#endif
+
 } // timer
 } // love

+ 0 - 6
src/modules/timer/Timer.h

@@ -101,12 +101,6 @@ private:
 	// The current timestep.
 	double dt;
 
-	// Returns the timer period on some platforms.
-	static double getTimerPeriod();
-
-	// Like getTime, but relative to an unspecified time.
-	static double getTimeAbsolute();
-
 }; // Timer
 
 } // timer