aboutsummaryrefslogtreecommitdiff
path: root/third_party/include/hayai/hayai_clock.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/include/hayai/hayai_clock.hpp')
-rwxr-xr-xthird_party/include/hayai/hayai_clock.hpp367
1 files changed, 367 insertions, 0 deletions
diff --git a/third_party/include/hayai/hayai_clock.hpp b/third_party/include/hayai/hayai_clock.hpp
new file mode 100755
index 0000000..c6d4e41
--- /dev/null
+++ b/third_party/include/hayai/hayai_clock.hpp
@@ -0,0 +1,367 @@
+//
+// System-specific implementation of the clock functions.
+//
+// Copyright (C) 2011 Nick Bruun <nick@bruun.co>
+// Copyright (C) 2013 Vlad Lazarenko <vlad@lazarenko.me>
+// Copyright (C) 2014 Nicolas Pauss <nicolas.pauss@gmail.com>
+//
+// Implementation notes:
+//
+// On Windows, QueryPerformanceCounter() is used. It gets
+// real-time clock with up to nanosecond precision.
+//
+// On Apple (OS X, iOS), mach_absolute_time() is used. It gets
+// CPU/bus dependent real-time clock with up to nanosecond precision.
+//
+// On Unix, gethrtime() is used with HP-UX and Solaris. Otherwise,
+// clock_gettime() is used to access monotonic real-time clock
+// with up to nanosecond precision. On kernels 2.6.28 and newer, the ticks
+// are also raw and are not subject to NTP and/or adjtime(3) adjustments.
+//
+// Other POSIX compliant platforms resort to using gettimeofday(). It is
+// subject to clock adjustments, does not allow for higher than microsecond
+// resolution and is also declared obsolete by POSIX.1-2008.
+//
+// Note on C++11:
+//
+// Starting with C++11, we could use std::chrono. However, the details of
+// what clock is really being used is implementation-specific. For example,
+// Visual Studio 2012 defines "high_resolution_clock" as system clock with
+// ~1 millisecond precision that is not acceptable for performance
+// measurements. Therefore, we are much better off having full control of what
+// mechanism we use to obtain the system clock.
+//
+// Note on durations: it is assumed that end times passed to the clock methods
+// are all after the start time. Wrap-around of clocks is not tested, as
+// nanosecond precision of unsigned 64-bit integers would require an uptime of
+// almost 585 years for this to happen. Let's call ourselves safe on that one.
+//
+#ifndef __HAYAI_CLOCK
+#define __HAYAI_CLOCK
+
+#include "hayai_compatibility.hpp"
+
+
+// POSIX
+#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
+#include <unistd.h>
+#endif
+
+// Win32
+#if defined(_WIN32)
+#ifndef NOMINMAX
+#define NOMINMAX
+#endif
+#include <windows.h>
+
+// Apple
+#elif defined(__APPLE__) && defined(__MACH__)
+#include <mach/mach_time.h>
+
+// Unix
+#elif defined(__unix__) || defined(__unix) || defined(unix)
+
+// gethrtime
+# if (defined(__hpux) || defined(hpux)) || ((defined(__sun__) || defined(__sun) || defined(sun)) && (defined(__SVR4) || defined(__svr4__)))
+# include <sys/time.h>
+
+// clock_gettime
+# elif defined(_POSIX_TIMERS) && (_POSIX_TIMERS > 0)
+# include <time.h>
+
+// gettimeofday
+# else
+# include <sys/time.h>
+
+# endif
+#else
+#error "Unable to define high resolution timer for an unknown OS."
+#endif
+
+#include <stdexcept>
+#include <stdint.h>
+
+
+namespace hayai
+{
+// Win32
+#if defined(_WIN32)
+ class Clock
+ {
+ public:
+ /// Time point.
+
+ /// Opaque representation of a point in time.
+ typedef LARGE_INTEGER TimePoint;
+
+
+ /// Get the current time as a time point.
+
+ /// @returns the current time point.
+ static TimePoint Now()
+ {
+ TimePoint result;
+ QueryPerformanceCounter(&result);
+ return result;
+ }
+
+
+ /// Get the duration between two time points.
+
+ /// @param startTime Start time point.
+ /// @param endTime End time point.
+ /// @returns the number of nanoseconds elapsed between the two time
+ /// points.
+ static uint64_t Duration(const TimePoint& startTime,
+ const TimePoint& endTime)
+ {
+ const static double performanceFrequencyNs =
+ PerformanceFrequencyNs();
+
+ return static_cast<uint64_t>(
+ (endTime.QuadPart - startTime.QuadPart)
+ * performanceFrequencyNs
+ );
+ }
+
+
+ /// Clock implementation description.
+
+ /// @returns a description of the clock implementation used.
+ static const char* Description()
+ {
+ return "QueryPerformanceCounter";
+ }
+ private:
+ static double PerformanceFrequencyNs()
+ {
+ TimePoint result;
+ QueryPerformanceFrequency(&result);
+ return 1e9 / static_cast<double>(result.QuadPart);
+ }
+ };
+
+// Mach kernel.
+#elif defined(__APPLE__) && defined(__MACH__)
+ class Clock
+ {
+ public:
+ /// Time point.
+
+ /// Opaque representation of a point in time.
+ typedef uint64_t TimePoint;
+
+
+ /// Get the current time as a time point.
+
+ /// @returns the current time point.
+ static TimePoint Now() __hayai_noexcept
+ {
+ return mach_absolute_time();
+ }
+
+
+ /// Get the duration between two time points.
+
+ /// @param startTime Start time point.
+ /// @param endTime End time point.
+ /// @returns the number of nanoseconds elapsed between the two time
+ /// points.
+ static uint64_t Duration(const TimePoint& startTime,
+ const TimePoint& endTime) __hayai_noexcept
+ {
+ mach_timebase_info_data_t time_info;
+ mach_timebase_info(&time_info);
+
+ return (endTime - startTime) * time_info.numer / time_info.denom;
+ }
+
+
+ /// Clock implementation description.
+
+ /// @returns a description of the clock implementation used.
+ static const char* Description()
+ {
+ return "mach_absolute_time";
+ }
+ };
+
+// Unix
+#elif defined(__unix__) || defined(__unix) || defined(unix)
+
+// gethrtime
+# if (defined(__hpux) || defined(hpux)) || ((defined(__sun__) || defined(__sun) || defined(sun)) && (defined(__SVR4) || defined(__svr4__)))
+ class Clock
+ {
+ public:
+ /// Time point.
+
+ /// Opaque representation of a point in time.
+ typedef hrtime_t TimePoint;
+
+
+ /// Get the current time as a time point.
+
+ /// @returns the current time point.
+ static TimePoint Now() __hayai_noexcept
+ {
+ return gethrtime();
+ }
+
+
+ /// Get the duration between two time points.
+
+ /// @param startTime Start time point.
+ /// @param endTime End time point.
+ /// @returns the number of nanoseconds elapsed between the two time
+ /// points.
+ static uint64_t Duration(const TimePoint& startTime,
+ const TimePoint& endTime) __hayai_noexcept
+ {
+ return static_cast<uint64_t>(endTime - startTime);
+ }
+
+
+ /// Clock implementation description.
+
+ /// @returns a description of the clock implementation used.
+ static const char* Description()
+ {
+ return "gethrtime";
+ }
+ };
+
+
+// clock_gettime
+# elif defined(_POSIX_TIMERS) && (_POSIX_TIMERS > 0)
+ class Clock
+ {
+ public:
+ /// Time point.
+
+ /// Opaque representation of a point in time.
+ typedef struct timespec TimePoint;
+
+
+ /// Get the current time as a time point.
+
+ /// @returns the current time point.
+ static TimePoint Now() __hayai_noexcept
+ {
+ TimePoint result;
+# if defined(CLOCK_MONOTONIC_RAW)
+ clock_gettime(CLOCK_MONOTONIC_RAW, &result);
+# elif defined(CLOCK_MONOTONIC)
+ clock_gettime(CLOCK_MONOTONIC, &result);
+# elif defined(CLOCK_REALTIME)
+ clock_gettime(CLOCK_REALTIME, &result);
+# else
+ clock_gettime((clocId_t)-1, &result);
+# endif
+ return result;
+ }
+
+
+ /// Get the duration between two time points.
+
+ /// @param startTime Start time point.
+ /// @param endTime End time point.
+ /// @returns the number of nanoseconds elapsed between the two time
+ /// points.
+ static uint64_t Duration(const TimePoint& startTime,
+ const TimePoint& endTime) __hayai_noexcept
+ {
+ TimePoint timeDiff;
+
+ timeDiff.tv_sec = endTime.tv_sec - startTime.tv_sec;
+ if (endTime.tv_nsec < startTime.tv_nsec)
+ {
+ timeDiff.tv_nsec = endTime.tv_nsec + 1000000000LL -
+ startTime.tv_nsec;
+ timeDiff.tv_sec--;
+ }
+ else
+ timeDiff.tv_nsec = endTime.tv_nsec - startTime.tv_nsec;
+
+ return static_cast<uint64_t>(timeDiff.tv_sec * 1000000000LL +
+ timeDiff.tv_nsec);
+ }
+
+
+ /// Clock implementation description.
+
+ /// @returns a description of the clock implementation used.
+ static const char* Description()
+ {
+# if defined(CLOCK_MONOTONIC_RAW)
+ return "clock_gettime(CLOCK_MONOTONIC_RAW)";
+# elif defined(CLOCK_MONOTONIC)
+ return "clock_gettime(CLOCK_MONOTONIC)";
+# elif defined(CLOCK_REALTIME)
+ return "clock_gettime(CLOCK_REALTIME)";
+# else
+ return "clock_gettime(-1)";
+# endif
+ }
+ };
+
+// gettimeofday
+# else
+ class Clock
+ {
+ public:
+ /// Time point.
+
+ /// Opaque representation of a point in time.
+ typedef struct timeval TimePoint;
+
+
+ /// Get the current time as a time point.
+
+ /// @returns the current time point.
+ static TimePoint Now() __hayai_noexcept
+ {
+ TimePoint result;
+ gettimeofday(&result, NULL);
+ return result;
+ }
+
+
+ /// Get the duration between two time points.
+
+ /// @param startTime Start time point.
+ /// @param endTime End time point.
+ /// @returns the number of nanoseconds elapsed between the two time
+ /// points.
+ static uint64_t Duration(const TimePoint& startTime,
+ const TimePoint& endTime) __hayai_noexcept
+ {
+ TimePoint timeDiff;
+
+ timeDiff.tv_sec = endTime.tv_sec - startTime.tv_sec;
+ if (endTime.tv_usec < startTime.tv_usec)
+ {
+ timeDiff.tv_usec = endTime.tv_usec + 1000000L -
+ startTime.tv_usec;
+ timeDiff.tv_sec--;
+ }
+ else
+ timeDiff.tv_usec = endTime.tv_usec - startTime.tv_usec;
+
+ return static_cast<uint64_t>(timeDiff.tv_sec * 1000000000LL +
+ timeDiff.tv_usec * 1000);
+ }
+
+
+ /// Clock implementation description.
+
+ /// @returns a description of the clock implementation used.
+ static const char* Description()
+ {
+ return "gettimeofday";
+ }
+ };
+# endif
+#endif
+}
+#endif