diff options
| author | Stanislaw Halik <sthalik@misaki.pl> | 2017-05-12 15:40:49 +0200 | 
|---|---|---|
| committer | Stanislaw Halik <sthalik@misaki.pl> | 2017-05-12 15:40:49 +0200 | 
| commit | d160fbec0c70095b725d612458ae9ee3aa8ed526 (patch) | |
| tree | 84add8f7929b33adfe33cdbe2b8588f0813812a9 | |
| parent | ad496a028cee3e119177a3a7d9e9f4f0edb3f96c (diff) | |
compat/timer: add std::chrono support
| -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;  }; - - | 
