Skip to content

Instantly share code, notes, and snippets.

@Bak-Jin-Hyeong
Last active June 8, 2019 07:59
Show Gist options
  • Save Bak-Jin-Hyeong/ce28835d08fec517ec9402fe38ec1282 to your computer and use it in GitHub Desktop.
Save Bak-Jin-Hyeong/ce28835d08fec517ec9402fe38ec1282 to your computer and use it in GitHub Desktop.
#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} };
}
#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