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.
This commit is contained in:
Joel Schumacher
2020-05-21 15:56:57 +02:00
parent 8d627c88ae
commit 0a5db1ba6d
2 changed files with 66 additions and 47 deletions
+66 -41
View File
@@ -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;
#elif defined(LOVE_MACOSX) || defined(LOVE_IOS)
return (double) mach_absolute_time() * timerPeriod;
#elif defined(LOVE_WINDOWS)
LARGE_INTEGER microTime;
QueryPerformanceCounter(&microTime);
return (double) microTime.QuadPart * timerPeriod;
#endif
return getTimeOfDay();
}
double Timer::getTime()
{
static const double start = getTimeAbsolute();
return getTimeAbsolute() - start;
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)
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)
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 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