diff options
author | Stanislaw Halik <sthalik@misaki.pl> | 2017-03-21 06:27:28 +0100 |
---|---|---|
committer | Stanislaw Halik <sthalik@misaki.pl> | 2017-03-21 06:27:28 +0100 |
commit | fd0305aeecfad05f855b7d0e09a1eb9a70f4b2e5 (patch) | |
tree | 9bc750b5ce7a7c18536133d14fbc28b85e12e4f1 /compat/timer.cpp | |
parent | 0a9ec483f78de78b92f52d8f3a1b6dc1dceb03fd (diff) |
compat/timer: move from header. simplify
It was getting inlined in each compilation unit.
Diffstat (limited to 'compat/timer.cpp')
-rw-r--r-- | compat/timer.cpp | 119 |
1 files changed, 119 insertions, 0 deletions
diff --git a/compat/timer.cpp b/compat/timer.cpp new file mode 100644 index 00000000..9ab0f721 --- /dev/null +++ b/compat/timer.cpp @@ -0,0 +1,119 @@ +/* Copyright (c) 2014-2015, Stanislaw Halik <sthalik@misaki.pl> + + * Permission to use, copy, modify, and/or distribute this + * software for any purpose with or without fee is hereby granted, + * provided that the above copyright notice and this permission + * notice appear in all copies. + */ + +#pragma once + +#include "timer.hpp" + +Timer::Timer() +{ + start(); +} + +void Timer::start() +{ + wrap_gettime(&state); +} + +// common + +void Timer::wrap_gettime(timespec* state) +{ +#if defined(_WIN32) || defined(__MACH__) + otr_clock_gettime(state); +#else + (void) clock_gettime(CLOCK_MONOTONIC, state); +#endif +} + +// nanoseconds + +long long Timer::elapsed_nsecs() const +{ + struct timespec cur = {}; + wrap_gettime(&cur); + return conv_nsecs(cur); +} + +long long Timer::conv_nsecs(const timespec& cur) const +{ + // this can and will overflow + return (cur.tv_sec - state.tv_sec) * 1000000000LL + (cur.tv_nsec - state.tv_nsec); +} + +// microseconds + +double Timer::elapsed_usecs() const +{ + struct timespec cur = {}; + wrap_gettime(&cur); + const long long nsecs = conv_nsecs(cur); + return nsecs * 1e-3; +} + +// milliseconds + +double Timer::elapsed_ms() const +{ + return elapsed_usecs() / 1000.; +} + +double Timer::elapsed_seconds() const +{ + return double(elapsed_nsecs() * 1e-9L); +} + +// -- +// platform-specific code starts here +// -- + +#if defined _WIN32 +LARGE_INTEGER Timer::otr_get_clock_frequency() +{ + LARGE_INTEGER freq = {}; + (void) QueryPerformanceFrequency(&freq); + return freq; +} + +void Timer::otr_clock_gettime(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__ +mach_timebase_info_data_t Timer::otr_get_mach_frequency() +{ + mach_timebase_info_data_t timebase_info; + (void) mach_timebase_info(&timebase_info); + return timebase_info; +} + +double Timer::otr_clock_gettime(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 |