hayai_clock.hpp
Go to the documentation of this file.
00001 //
00002 // System-specific implementation of the clock functions.
00003 //
00004 // Copyright (C) 2011 Nick Bruun <nick@bruun.co>
00005 // Copyright (C) 2013 Vlad Lazarenko <vlad@lazarenko.me>
00006 // Copyright (C) 2014 Nicolas Pauss <nicolas.pauss@gmail.com>
00007 //
00008 // Implementation notes:
00009 //
00010 // On Windows, QueryPerformanceCounter() is used. It gets
00011 // real-time clock with up to nanosecond precision.
00012 //
00013 // On Apple (OS X, iOS), mach_absolute_time() is used. It gets
00014 // CPU/bus dependent real-time clock with up to nanosecond precision.
00015 //
00016 // On Unix, gethrtime() is used with HP-UX and Solaris. Otherwise,
00017 // clock_gettime() is used to access monotonic real-time clock
00018 // with up to nanosecond precision. On kernels 2.6.28 and newer, the ticks
00019 // are also raw and are not subject to NTP and/or adjtime(3) adjustments.
00020 //
00021 // Other POSIX compliant platforms resort to using gettimeofday(). It is
00022 // subject to clock adjustments, does not allow for higher than microsecond
00023 // resolution and is also declared obsolete by POSIX.1-2008.
00024 //
00025 // Note on C++11:
00026 //
00027 // Starting with C++11, we could use std::chrono. However, the details of
00028 // what clock is really being used is implementation-specific. For example,
00029 // Visual Studio 2012 defines "high_resolution_clock" as system clock with
00030 // ~1 millisecond precision that is not acceptable for performance
00031 // measurements. Therefore, we are much better off having full control of what
00032 // mechanism we use to obtain the system clock.
00033 //
00034 // Note on durations: it is assumed that end times passed to the clock methods
00035 // are all after the start time. Wrap-around of clocks is not tested, as
00036 // nanosecond precision of unsigned 64-bit integers would require an uptime of
00037 // almost 585 years for this to happen. Let's call ourselves safe on that one.
00038 //
00039 #ifndef __HAYAI_CLOCK
00040 #define __HAYAI_CLOCK
00041 
00042 #include "hayai/hayai_compatibility.hpp"
00043 
00044 
00045 // Win32
00046 #if defined(_WIN32)
00047 #ifndef NOMINMAX
00048 #define NOMINMAX
00049 #endif
00050 #include <windows.h>
00051 
00052 // Apple
00053 #elif defined(__APPLE__) && defined(__MACH__)
00054 #include <mach/mach_time.h>
00055 
00056 // Unix
00057 #elif defined(__unix__) || defined(__unix) || defined(unix)
00058 
00059 // gethrtime
00060 #   if (defined(__hpux) || defined(hpux)) || ((defined(__sun__) || defined(__sun) || defined(sun)) && (defined(__SVR4) || defined(__svr4__)))
00061 #   include <sys/time.h>
00062 
00063 // clock_gettime
00064 #   elif defined(_POSIX_TIMERS) && (_POSIX_TIMERS > 0)
00065 #   include <time.h>
00066 
00067 // gettimeofday
00068 #   else
00069 #   include <sys/time.h>
00070 
00071 #   endif
00072 #else
00073 #error "Unable to define high resolution timer for an unknown OS."
00074 #endif
00075 
00076 #include <stdexcept>
00077 #include <stdint.h>
00078 
00079 
00080 namespace hayai
00081 {
00082 // Win32
00083 #if defined(_WIN32)
00084     class Clock
00085     {
00086     public:
00088 
00090         typedef LARGE_INTEGER TimePoint;
00091 
00092 
00094 
00096         static TimePoint Now()
00097         {
00098             TimePoint result;
00099             QueryPerformanceCounter(&result);
00100             return result;
00101         }
00102 
00103 
00105 
00110         static uint64_t Duration(const TimePoint& startTime,
00111                                  const TimePoint& endTime)
00112         {
00113             const static double performanceFrequencyNs =
00114                 PerformanceFrequencyNs();
00115 
00116             return static_cast<uint64_t>(
00117                        (endTime.QuadPart - startTime.QuadPart)
00118                        * performanceFrequencyNs
00119                    );
00120         }
00121 
00122 
00124 
00126         static const char* Description()
00127         {
00128             return "QueryPerformanceCounter";
00129         }
00130     private:
00131         static double PerformanceFrequencyNs()
00132         {
00133             TimePoint result;
00134             QueryPerformanceFrequency(&result);
00135             return 1e9 / static_cast<double>(result.QuadPart);
00136         }
00137     };
00138 
00139 // Mach kernel.
00140 #elif defined(__APPLE__) && defined(__MACH__)
00141     class Clock
00142     {
00143     public:
00145 
00147         typedef uint64_t TimePoint;
00148 
00149 
00151 
00153         static TimePoint Now() __hayai_noexcept
00154         {
00155             return mach_absolute_time();
00156         }
00157 
00158 
00160 
00165         static uint64_t Duration(const TimePoint& startTime,
00166                                  const TimePoint& endTime) __hayai_noexcept
00167         {
00168             mach_timebase_info_data_t time_info;
00169             mach_timebase_info(&time_info);
00170 
00171             return (endTime - startTime) * time_info.numer / time_info.denom;
00172         }
00173 
00174 
00176 
00178         static const char* Description()
00179         {
00180             return "mach_absolute_time";
00181         }
00182     };
00183 
00184 // Unix
00185 #elif defined(__unix__) || defined(__unix) || defined(unix)
00186 
00187 // gethrtime
00188 #   if (defined(__hpux) || defined(hpux)) || ((defined(__sun__) || defined(__sun) || defined(sun)) && (defined(__SVR4) || defined(__svr4__)))
00189     class Clock
00190     {
00191     public:
00193 
00195         typedef hrtime_t TimePoint;
00196 
00197 
00199 
00201         static TimePoint Now() __hayai_noexcept
00202         {
00203             return gethrtime();
00204         }
00205 
00206 
00208 
00213         static uint64_t Duration(const TimePoint& startTime,
00214                                  const TimePoint& endTime) __hayai_noexcept
00215         {
00216             return static_cast<uint64_t>(endTime - startTime);
00217         }
00218 
00219 
00221 
00223         static const char* Description()
00224         {
00225             return "gethrtime";
00226         }
00227     };
00228 
00229 
00230 // clock_gettime
00231 #   elif defined(_POSIX_TIMERS) && (_POSIX_TIMERS > 0)
00232     class Clock
00233     {
00234     public:
00236 
00238         typedef struct timespec TimePoint;
00239 
00240 
00242 
00244         static TimePoint Now() __hayai_noexcept
00245         {
00246             TimePoint result;
00247 #       if   defined(CLOCK_MONOTONIC_RAW)
00248             clock_gettime(CLOCK_MONOTONIC_RAW, &result);
00249 #       elif defined(CLOCK_MONOTONIC)
00250             clock_gettime(CLOCK_MONOTONIC, &result);
00251 #       elif defined(CLOCK_REALTIME)
00252             clock_gettime(CLOCK_REALTIME, &result);
00253 #       else
00254             clock_gettime((clockid_t) - 1, &result);
00255 #       endif
00256             return result;
00257         }
00258 
00259 
00261 
00266         static uint64_t Duration(const TimePoint& startTime,
00267                                  const TimePoint& endTime) __hayai_noexcept
00268         {
00269             TimePoint timeDiff;
00270 
00271             timeDiff.tv_sec = endTime.tv_sec - startTime.tv_sec;
00272 
00273             if (endTime.tv_nsec < startTime.tv_nsec)
00274             {
00275                 timeDiff.tv_nsec = endTime.tv_nsec + 1000000000LL -
00276                 startTime.tv_nsec;
00277                 timeDiff.tv_sec--;
00278             }
00279             else
00280             { timeDiff.tv_nsec = endTime.tv_nsec - startTime.tv_nsec; }
00281 
00282             return static_cast<uint64_t>(timeDiff.tv_sec * 1000000000L +
00283             timeDiff.tv_nsec);
00284         }
00285 
00286 
00288 
00290         static const char* Description()
00291         {
00292 #       if   defined(CLOCK_MONOTONIC_RAW)
00293             return "clock_gettime(CLOCK_MONOTONIC_RAW)";
00294 #       elif defined(CLOCK_MONOTONIC)
00295             return "clock_gettime(CLOCK_MONOTONIC)";
00296 #       elif defined(CLOCK_REALTIME)
00297             return "clock_gettime(CLOCK_REALTIME)";
00298 #       else
00299             return "clock_gettime(-1)";
00300 #       endif
00301         }
00302     };
00303 
00304 // gettimeofday
00305 #   else
00306     class Clock
00307     {
00308     public:
00310 
00312         typedef struct timeval TimePoint;
00313 
00314 
00316 
00318         static TimePoint Now() __hayai_noexcept
00319         {
00320             TimePoint result;
00321             gettimeofday(&result, NULL);
00322             return result;
00323         }
00324 
00325 
00327 
00332         static uint64_t Duration(const TimePoint& startTime,
00333                                  const TimePoint& endTime) __hayai_noexcept
00334         {
00335             TimePoint timeDiff;
00336 
00337             timeDiff.tv_sec = endTime.tv_sec - startTime.tv_sec;
00338 
00339             if (endTime.tv_usec < startTime.tv_usec)
00340             {
00341                 timeDiff.tv_usec = endTime.tv_usec + 1000000L -
00342                 startTime.tv_usec;
00343                 timeDiff.tv_sec--;
00344             }
00345             else
00346             { timeDiff.tv_usec = endTime.tv_usec - startTime.tv_usec; }
00347 
00348             return static_cast<uint64_t>(timeDiff.tv_sec * 1000000000LL +
00349             timeDiff.tv_usec * 1000);
00350         }
00351 
00352 
00354 
00356         static const char* Description()
00357         {
00358             return "gettimeofday";
00359         }
00360     };
00361 #   endif
00362 #endif
00363 }
00364 #endif


hayai
Author(s): Nick Bruun
autogenerated on Thu Jun 6 2019 18:13:43