Last active
June 8, 2019 07:59
-
-
Save Bak-Jin-Hyeong/ce28835d08fec517ec9402fe38ec1282 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "CoarseClock.h" | |
#if defined(_WIN32) || defined(_WIN64) | |
#if defined(_M_IX86) || defined(_M_AMD64) | |
#include <Windows.h> | |
[[nodiscard]] CoarseSteadyClock::time_point CoarseSteadyClock::now() noexcept | |
{ | |
// https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/ntddk/ns-ntddk-kuser_shared_data | |
#ifdef _WIN64 | |
const auto x = *reinterpret_cast<volatile int64_t*>(0x7FFE0008); | |
return time_point{ duration{ x } }; | |
#else | |
struct KSYSTEM_TIME | |
{ | |
ULONG LowPart; | |
LONG High1Time; | |
LONG High2Time; | |
}; | |
LARGE_INTEGER li; | |
for (;;) | |
{ | |
const auto p = | |
reinterpret_cast<volatile struct KSYSTEM_TIME*>(0x7FFE0008); | |
const auto high1 = p->High1Time; | |
const auto low = p->LowPart; | |
const auto high2 = p->High2Time; | |
if (high1 == high2) | |
{ | |
li.LowPart = low; | |
li.HighPart = high1; | |
break; | |
} | |
else | |
{ | |
YieldProcessor(); | |
} | |
} | |
return time_point{ duration{ li.QuadPart } }; | |
#endif | |
} | |
[[nodiscard]] CoarseSystemClock::time_point CoarseSystemClock::now() noexcept | |
{ | |
constexpr int64_t windows_epoch_to_unix_epoch = 0x19DB1DED53E8000ll; | |
FILETIME ft{}; | |
::GetSystemTimeAsFileTime(&ft); | |
const auto x = | |
(static_cast<int64_t>(ft.dwHighDateTime) << 32) + | |
static_cast<int64_t>(ft.dwLowDateTime) - | |
windows_epoch_to_unix_epoch; | |
return time_point{ duration{ x } }; | |
} | |
#else // #if defined(_M_IX86) || defined(_M_AMD64) | |
#error Unsupported architecture | |
#endif // #if defined(_M_IX86) || defined(_M_AMD64) | |
#else // #if defined(_WIN32) || defined(_WIN64) | |
[[nodiscard]] CoarseSteadyClock::time_point CoarseSteadyClock::now() noexcept | |
{ | |
// TODO: Fallback to CLOCK_MONOTONIC | |
// on systems that do not support CLOCK_MONOTONIC_COARSE | |
timespec t{}; | |
clock_gettime(CLOCK_MONOTONIC_COARSE, &t); | |
return time_point | |
{ | |
duration | |
{ | |
std::chrono::seconds(t.tv_sec) + | |
std::chrono::nanoseconds(t.tv_nsec) | |
} | |
}; | |
} | |
[[nodiscard]] CoarseSystemClock::time_point CoarseSystemClock::now() noexcept | |
{ | |
// TODO: Fallback to CLOCK_REALTIME | |
// on systems that do not support CLOCK_REALTIME_COARSE | |
timespec t{}; | |
clock_gettime(CLOCK_REALTIME_COARSE, &t); | |
return time_point | |
{ | |
duration | |
{ | |
std::chrono::seconds(t.tv_sec) + | |
std::chrono::nanoseconds(t.tv_nsec) | |
} | |
}; | |
} | |
#endif // #if defined(_WIN32) || defined(_WIN64) | |
[[nodiscard]] | |
time_t CoarseSystemClock::to_time_t(const time_point& t) noexcept | |
{ | |
return static_cast<time_t>( | |
t.time_since_epoch().count() / ticks_per_time_t); | |
} | |
[[nodiscard]] CoarseSystemClock::time_point | |
CoarseSystemClock::from_time_t(time_t t) noexcept | |
{ | |
return time_point{ duration{t * ticks_per_time_t} }; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef COARSECLOCK__H__ | |
#define COARSECLOCK__H__ | |
#include <ctime> | |
#include <chrono> | |
#include <ratio> | |
class CoarseSystemClock | |
{ | |
public: | |
#if defined(_WIN32) || defined(_WIN64) | |
static constexpr int64_t ticks_per_time_t = 10000000LL; | |
#else | |
static constexpr int64_t ticks_per_time_t = 1000000000LL; | |
#endif | |
public: | |
static constexpr bool is_steady = false; | |
using rep = long long; | |
using period = std::ratio<1, ticks_per_time_t>; | |
using duration = std::chrono::duration<rep, period>; | |
using time_point = std::chrono::time_point<CoarseSystemClock>; | |
[[nodiscard]] static time_point now() noexcept; | |
[[nodiscard]] static time_t to_time_t(const time_point& tp) noexcept; | |
[[nodiscard]] static time_point from_time_t(time_t t) noexcept; | |
}; | |
class CoarseSteadyClock | |
{ | |
public: | |
#if defined(_WIN32) || defined(_WIN64) | |
static constexpr int64_t ticks_per_time_t = 10000000LL; | |
#else | |
static constexpr int64_t ticks_per_time_t = 1000000000LL; | |
#endif | |
public: | |
static constexpr bool is_steady = true; | |
using rep = long long; | |
using period = std::ratio<1, ticks_per_time_t>; | |
using duration = std::chrono::duration<rep, period>; | |
using time_point = std::chrono::time_point<CoarseSteadyClock>; | |
[[nodiscard]] static time_point now() noexcept; | |
}; | |
#endif // #ifndef COARSECLOCK__H__ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment