summaryrefslogtreecommitdiff
path: root/libs/libmdbx/src/test/chrono.cc
diff options
context:
space:
mode:
authorGeorge Hazan <ghazan@miranda.im>2018-07-11 12:29:02 +0300
committerGeorge Hazan <ghazan@miranda.im>2018-07-11 12:29:10 +0300
commit92a5c27c4ea88f2f7c4810c789f7b5aebe06d03c (patch)
treee24f375b06c781077d22028a5d86f2d56585dc6c /libs/libmdbx/src/test/chrono.cc
parent09693d256f7a0ec0c24dce56f9aca87d3a01856d (diff)
libmdbx extracted to separate dll
Diffstat (limited to 'libs/libmdbx/src/test/chrono.cc')
-rw-r--r--libs/libmdbx/src/test/chrono.cc129
1 files changed, 129 insertions, 0 deletions
diff --git a/libs/libmdbx/src/test/chrono.cc b/libs/libmdbx/src/test/chrono.cc
new file mode 100644
index 0000000000..f734668628
--- /dev/null
+++ b/libs/libmdbx/src/test/chrono.cc
@@ -0,0 +1,129 @@
+/*
+ * Copyright 2017-2018 Leonid Yuriev <leo@yuriev.ru>
+ * and other libmdbx authors: please see AUTHORS file.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted only as authorized by the OpenLDAP
+ * Public License.
+ *
+ * A copy of this license is available in the file LICENSE in the
+ * top-level directory of the distribution or, alternatively, at
+ * <http://www.OpenLDAP.org/license.html>.
+ */
+
+#include "test.h"
+
+namespace chrono {
+
+#define NSEC_PER_SEC 1000000000u
+uint32_t ns2fractional(uint32_t ns) {
+ assert(ns < NSEC_PER_SEC);
+ /* LY: здесь и далее используется "длинное деление", которое
+ * для ясности кода оставлено как есть (без ручной оптимизации). Так как
+ * GCC, Clang и даже MSVC сами давно умеют конвертировать деление на
+ * константу в быструю reciprocal-форму. */
+ return ((uint64_t)ns << 32) / NSEC_PER_SEC;
+}
+
+uint32_t fractional2ns(uint32_t fractional) {
+ return (fractional * (uint64_t)NSEC_PER_SEC) >> 32;
+}
+
+#define USEC_PER_SEC 1000000u
+uint32_t us2fractional(uint32_t us) {
+ assert(us < USEC_PER_SEC);
+ return ((uint64_t)us << 32) / USEC_PER_SEC;
+}
+
+uint32_t fractional2us(uint32_t fractional) {
+ return (fractional * (uint64_t)USEC_PER_SEC) >> 32;
+}
+
+#define MSEC_PER_SEC 1000u
+uint32_t ms2fractional(uint32_t ms) {
+ assert(ms < MSEC_PER_SEC);
+ return ((uint64_t)ms << 32) / MSEC_PER_SEC;
+}
+
+uint32_t fractional2ms(uint32_t fractional) {
+ return (fractional * (uint64_t)MSEC_PER_SEC) >> 32;
+}
+
+time from_ns(uint64_t ns) {
+ time result;
+ result.fixedpoint = ((ns / NSEC_PER_SEC) << 32) |
+ ns2fractional((uint32_t)(ns % NSEC_PER_SEC));
+ return result;
+}
+
+time from_us(uint64_t us) {
+ time result;
+ result.fixedpoint = ((us / USEC_PER_SEC) << 32) |
+ us2fractional((uint32_t)(us % USEC_PER_SEC));
+ return result;
+}
+
+time from_ms(uint64_t ms) {
+ time result;
+ result.fixedpoint = ((ms / MSEC_PER_SEC) << 32) |
+ ms2fractional((uint32_t)(ms % MSEC_PER_SEC));
+ return result;
+}
+
+time now_realtime() {
+#if defined(_WIN32) || defined(_WIN64) || defined(_WINDOWS)
+ static void(WINAPI * query_time)(LPFILETIME);
+ if (!query_time) {
+ query_time = (void(WINAPI *)(LPFILETIME))GetProcAddress(
+ GetModuleHandle(TEXT("kernel32.dll")),
+ "GetSystemTimePreciseAsFileTime");
+ if (!query_time)
+ query_time = GetSystemTimeAsFileTime;
+ }
+
+ FILETIME filetime;
+ query_time(&filetime);
+ uint64_t ns100 =
+ (uint64_t)filetime.dwHighDateTime << 32 | filetime.dwLowDateTime;
+ return from_ns((ns100 - UINT64_C(116444736000000000)) * 100u);
+#else
+ struct timespec ts;
+ if (unlikely(clock_gettime(CLOCK_REALTIME, &ts)))
+ failure_perror("clock_gettime(CLOCK_REALTIME", errno);
+
+ return from_timespec(ts);
+#endif
+}
+
+time now_motonic() {
+#if defined(_WIN32) || defined(_WIN64) || defined(_WINDOWS)
+ static uint64_t reciprocal;
+ static LARGE_INTEGER Frequency;
+ if (reciprocal == 0) {
+ if (!QueryPerformanceFrequency(&Frequency))
+ failure_perror("QueryPerformanceFrequency()", GetLastError());
+ reciprocal = (((UINT64_C(1) << 48) + Frequency.QuadPart / 2 + 1) /
+ Frequency.QuadPart);
+ assert(reciprocal);
+ }
+
+ LARGE_INTEGER Counter;
+ if (!QueryPerformanceCounter(&Counter))
+ failure_perror("QueryPerformanceCounter()", GetLastError());
+
+ time result;
+ result.fixedpoint = (Counter.QuadPart / Frequency.QuadPart) << 32;
+ uint64_t mod = Counter.QuadPart % Frequency.QuadPart;
+ result.fixedpoint += (mod * reciprocal) >> 16;
+ return result;
+#else
+ struct timespec ts;
+ if (unlikely(clock_gettime(CLOCK_MONOTONIC, &ts)))
+ failure_perror("clock_gettime(CLOCK_MONOTONIC)", errno);
+
+ return from_timespec(ts);
+#endif
+}
+
+} /* namespace chrono */