summaryrefslogtreecommitdiffhomepage
path: root/compat/timer.hpp
diff options
context:
space:
mode:
authorStanislaw Halik <sthalik@misaki.pl>2016-12-31 07:08:47 +0100
committerStanislaw Halik <sthalik@misaki.pl>2016-12-31 07:52:58 +0100
commite8d59272d85bcac4a89ff36a190aee09dd7dfac9 (patch)
tree3a20fd19cf2599c4def484af659e01052384fbc0 /compat/timer.hpp
parent67145ae776064fe57b7a25573909190e4a6d6ac8 (diff)
compat/timer: prevent races in initializing timer resolution
Also, - don't lose high bits with cast from long long to long on _WIN32. - reduce #define pollution
Diffstat (limited to 'compat/timer.hpp')
-rw-r--r--compat/timer.hpp109
1 files changed, 61 insertions, 48 deletions
diff --git a/compat/timer.hpp b/compat/timer.hpp
index b01e5f38..ab1ec6b3 100644
--- a/compat/timer.hpp
+++ b/compat/timer.hpp
@@ -11,49 +11,11 @@
#if defined (_WIN32)
# include <windows.h>
-# ifndef CLOCK_MONOTONIC
-# define CLOCK_MONOTONIC -1
-# endif
-static inline void opentrack_clock_gettime(int, struct timespec* ts)
-{
- static LARGE_INTEGER freq;
-
- if (!freq.QuadPart)
- (void) QueryPerformanceFrequency(&freq);
-
- LARGE_INTEGER d;
-
- (void) QueryPerformanceCounter(&d);
-
- using ll = long long;
- using ld = long double;
- const long long part = ll(d.QuadPart / ld(freq.QuadPart) * 1000000000.L);
- using t_s = decltype(ts->tv_sec);
- using t_ns = decltype(ts->tv_nsec);
-
- ts->tv_sec = t_s(part / 1000000000LL);
- ts->tv_nsec = t_ns(part % 1000000000LL);
-}
-# define clock_gettime opentrack_clock_gettime
-#else
-# if defined(__MACH__)
-# define CLOCK_MONOTONIC 0
-# include <inttypes.h>
-# include <mach/mach_time.h>
-static inline void clock_gettime(int, struct timespec* ts)
-{
- static mach_timebase_info_data_t sTimebaseInfo;
- uint64_t state, nsec;
- if ( sTimebaseInfo.denom == 0 ) {
- (void) mach_timebase_info(&sTimebaseInfo);
- }
- state = mach_absolute_time();
- nsec = state * sTimebaseInfo.numer / sTimebaseInfo.denom;
- ts->tv_sec = nsec / 1000000000L;
- ts->tv_nsec = nsec % 1000000000L;
-}
-# endif
+#elif defined(__MACH__)
+# include <inttypes.h>
+# include <mach/mach_time.h>
#endif
+
class Timer
{
private:
@@ -64,27 +26,78 @@ private:
}
long conv_usecs(const struct timespec& cur) const
{
- return long(cur.tv_sec - state.tv_sec) * 1000000L + long(cur.tv_nsec - state.tv_nsec) / 1000l;
+ return (cur.tv_sec - state.tv_sec) * 1000000LL + (cur.tv_nsec - state.tv_nsec) / 1000;
+ }
+#ifdef _WIN32
+ static LARGE_INTEGER otr_get_clock_frequency()
+ {
+ LARGE_INTEGER freq = {};
+ (void) QueryPerformanceFrequency(&freq);
+ return freq;
}
+ static void otr_clock_gettime(struct timespec* ts)
+ {
+ static LARGE_INTEGER freq = otr_get_clock_frequency();
+
+ LARGE_INTEGER d;
+
+ (void) QueryPerformanceCounter(&d);
+
+ using ll = long long;
+ using ld = long double;
+ const long long part = ll(d.QuadPart / ld(freq.QuadPart) * 1000000000.L);
+ using t_s = decltype(ts->tv_sec);
+ using t_ns = decltype(ts->tv_nsec);
+
+ ts->tv_sec = t_s(part / 1000000000LL);
+ ts->tv_nsec = t_ns(part % 1000000000LL);
+ }
+#elif defined(__MACH__)
+ static mach_timebase_info_data_t otr_get_mach_frequency()
+ {
+ mach_timebase_info_data_t timebase_info;
+ (void) mach_timebase_info(&timebase_info);
+ return timebase_info;
+ }
+ static void otr_clock_gettime(struct timespec* ts)
+ {
+ static mach_timebase_info_data_t timebase_info = otr_get_mach_frequency();
+ uint64_t state, nsec;
+ state = mach_absolute_time();
+ nsec = state * timebase_info.numer / timebase_info.denom;
+ ts->tv_sec = nsec / 1000000000L;
+ ts->tv_nsec = nsec % 1000000000L;
+ }
+#endif
+
public:
Timer()
{
start();
}
+ static inline void wrap_gettime(struct timespec* state)
+ {
+#if defined(_WIN32) || defined(__MACH__)
+ otr_clock_gettime(state);
+#else
+ (void) clock_gettime(CLOCK_MONOTONIC, state);
+#endif
+ }
+
void start()
{
- clock_gettime(CLOCK_MONOTONIC, &state);
+ wrap_gettime(&state);
}
long long elapsed_nsecs() const
{
- struct timespec cur;
- clock_gettime(CLOCK_MONOTONIC, &cur);
+ struct timespec cur = {};
+ wrap_gettime(&cur);
return conv_nsecs(cur);
}
long elapsed_usecs() const
{
- struct timespec cur;
- clock_gettime(CLOCK_MONOTONIC, &cur);
+ struct timespec cur = {};
+ wrap_gettime(&cur);
return long(conv_usecs(cur));
}
long elapsed_ms() const