diff options
Diffstat (limited to 'compat')
-rw-r--r-- | compat/time.hpp | 25 | ||||
-rw-r--r-- | compat/timer.cpp | 32 | ||||
-rw-r--r-- | compat/timer.hpp | 18 |
3 files changed, 55 insertions, 20 deletions
diff --git a/compat/time.hpp b/compat/time.hpp new file mode 100644 index 00000000..fbe7469a --- /dev/null +++ b/compat/time.hpp @@ -0,0 +1,25 @@ +#pragma once + +#include <chrono> +#include <type_traits> + +namespace time_units { + +template<typename repr, typename ratio> +using duration = std::chrono::duration<repr, ratio>; + +template<typename t, typename u> +static inline constexpr auto time_cast(const u& in) +{ + return std::chrono::duration_cast<t>(in); +} + +using secs = duration<double, std::ratio<1, 1>>; +using secs_ = duration<long long, std::ratio<1, 1>>; +using ms = duration<double, std::milli>; +using ms_ = duration<long long, std::milli>; +using us = duration<double, std::micro>; +using us_ = duration<long long, std::micro>; +using ns = duration<long long, std::nano>; + +} // ns time_units diff --git a/compat/timer.cpp b/compat/timer.cpp index d5052ccb..3ecdf528 100644 --- a/compat/timer.cpp +++ b/compat/timer.cpp @@ -7,6 +7,7 @@ */ #include "timer.hpp" +#include <cmath> Timer::Timer() { @@ -15,17 +16,20 @@ Timer::Timer() void Timer::start() { - wrap_gettime(&state); + gettime(&state); } // common -void Timer::wrap_gettime(timespec* state) +void Timer::gettime(timespec* state) { #if defined(_WIN32) || defined(__MACH__) otr_clock_gettime(state); +#elif defined CLOCK_MONOTONIC + const int res = clock_gettime(CLOCK_MONOTONIC, state); + assert(res == 0 && "must support CLOCK_MONOTONIC"); #else - (void) clock_gettime(CLOCK_MONOTONIC, state); +# error "timer query method not known" #endif } @@ -33,14 +37,13 @@ void Timer::wrap_gettime(timespec* state) long long Timer::elapsed_nsecs() const { - struct timespec cur = {}; - wrap_gettime(&cur); + timespec cur{}; + 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); } @@ -48,8 +51,8 @@ long long Timer::conv_nsecs(const timespec& cur) const double Timer::elapsed_usecs() const { - struct timespec cur = {}; - wrap_gettime(&cur); + timespec cur{}; + gettime(&cur); const long long nsecs = conv_nsecs(cur); return nsecs * 1e-3; } @@ -73,27 +76,26 @@ double Timer::elapsed_seconds() const #if defined _WIN32 LARGE_INTEGER Timer::otr_get_clock_frequency() { - LARGE_INTEGER freq = {}; + LARGE_INTEGER freq{}; (void) QueryPerformanceFrequency(&freq); return freq; } void Timer::otr_clock_gettime(timespec* ts) { - static LARGE_INTEGER freq = otr_get_clock_frequency(); + static const 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); + const ll part = ll(std::roundl((d.QuadPart * 1000000000.L) / ll(freq.QuadPart))); 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); + ts->tv_sec = t_s(part / 1000000000); + ts->tv_nsec = t_ns(part % 1000000000); } #elif defined __MACH__ @@ -106,7 +108,7 @@ mach_timebase_info_data_t Timer::otr_get_mach_frequency() double Timer::otr_clock_gettime(timespec* ts) { - static mach_timebase_info_data_t timebase_info = otr_get_mach_frequency(); + static const 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; diff --git a/compat/timer.hpp b/compat/timer.hpp index e9efba79..58e1c7d6 100644 --- a/compat/timer.hpp +++ b/compat/timer.hpp @@ -20,7 +20,9 @@ #include <ctime> #include <tuple> -class OTR_COMPAT_EXPORT Timer +#include "time.hpp" + +class OTR_COMPAT_EXPORT Timer final { struct timespec state; long long conv_nsecs(const struct timespec& cur) const; @@ -31,16 +33,22 @@ class OTR_COMPAT_EXPORT Timer static mach_timebase_info_data_t otr_get_mach_frequency(); #endif - static void wrap_gettime(struct timespec* state); + static void gettime(struct timespec* state); + using ns = time_units::ns; public: Timer(); - void start(); + + template<typename t> + t elapsed() const + { + using namespace time_units; + return static_cast<const t&>(ns(elapsed_nsecs())); + } + long long elapsed_nsecs() const; double elapsed_usecs() const; double elapsed_ms() const; double elapsed_seconds() const; }; - - |