3#ifndef TIME_SHIELD_HEADER_CORE_TIME_UTILS_HPP_INCLUDED
4#define TIME_SHIELD_HEADER_CORE_TIME_UTILS_HPP_INCLUDED
21#if TIME_SHIELD_PLATFORM_WINDOWS
22# ifndef WIN32_LEAN_AND_MEAN
23# define WIN32_LEAN_AND_MEAN
29#elif TIME_SHIELD_PLATFORM_UNIX
31# include <sys/resource.h>
32# include <sys/times.h>
35# error "Unsupported platform for get_cpu_time()"
46# if defined(CLOCK_REALTIME)
47 clock_gettime(CLOCK_REALTIME, &
ts);
49 timespec_get(&
ts, TIME_UTC);
65# if TIME_SHIELD_PLATFORM_WINDOWS
66 static std::once_flag init_flag;
67 static int64_t s_perf_freq = 0;
68 static int64_t s_anchor_perf = 0;
69 static int64_t s_anchor_realtime_us = 0;
71 std::call_once(init_flag, []() {
72 LARGE_INTEGER freq = {};
73 LARGE_INTEGER counter = {};
74 ::QueryPerformanceFrequency(&freq);
75 ::QueryPerformanceCounter(&counter);
77 s_perf_freq =
static_cast<int64_t
>(freq.QuadPart);
78 s_anchor_perf =
static_cast<int64_t
>(counter.QuadPart);
81 ::GetSystemTimeAsFileTime(&ft);
84 uli.LowPart = ft.dwLowDateTime;
85 uli.HighPart = ft.dwHighDateTime;
88 const int64_t k_epoch_diff_100ns = 116444736000000000LL;
90 const int64_t filetime_100ns =
static_cast<int64_t
>(uli.QuadPart);
92 s_anchor_realtime_us = (filetime_100ns - k_epoch_diff_100ns) / 10;
95 LARGE_INTEGER
now = {};
96 ::QueryPerformanceCounter(&
now);
98 const int64_t now_ticks =
static_cast<int64_t
>(
now.QuadPart);
99 const int64_t delta_ticks = now_ticks - s_anchor_perf;
102 const int64_t q = delta_ticks / s_perf_freq;
103 const int64_t r = delta_ticks % s_perf_freq;
105 const int64_t delta_us =
106 q * 1000000LL + (r * 1000000LL) / s_perf_freq;
108 return s_anchor_realtime_us + delta_us;
110 static std::once_flag init_flag;
111 static int64_t s_anchor_realtime_us = 0;
112 static int64_t s_anchor_mono_ns = 0;
114 std::call_once(init_flag, []() {
115 struct timespec realtime_ts{};
116 struct timespec mono_ts{};
118# if defined(CLOCK_MONOTONIC_RAW)
119 clock_gettime(CLOCK_MONOTONIC_RAW, &mono_ts);
121 clock_gettime(CLOCK_MONOTONIC, &mono_ts);
123 clock_gettime(CLOCK_REALTIME, &realtime_ts);
125 s_anchor_realtime_us =
static_cast<int64_t
>(realtime_ts.tv_sec) * 1000000LL
126 + realtime_ts.tv_nsec / 1000;
127 s_anchor_mono_ns =
static_cast<int64_t
>(mono_ts.tv_sec) * 1000000000LL
131 struct timespec mono_now_ts{};
132# if defined(CLOCK_MONOTONIC_RAW)
133 clock_gettime(CLOCK_MONOTONIC_RAW, &mono_now_ts);
135 clock_gettime(CLOCK_MONOTONIC, &mono_now_ts);
138 const int64_t mono_now_ns =
static_cast<int64_t
>(mono_now_ts.tv_sec) * 1000000000LL
139 + mono_now_ts.tv_nsec;
140 const int64_t delta_ns = mono_now_ns - s_anchor_mono_ns;
141 return s_anchor_realtime_us + delta_ns / 1000;
153 const auto ticks = std::chrono::steady_clock::now().time_since_epoch();
154 return static_cast<ts_t>(std::chrono::duration_cast<std::chrono::seconds>(ticks).count());
165 const auto ticks = std::chrono::steady_clock::now().time_since_epoch();
166 return static_cast<ts_ms_t>(std::chrono::duration_cast<std::chrono::milliseconds>(ticks).count());
177 const auto ticks = std::chrono::steady_clock::now().time_since_epoch();
178 return static_cast<ts_us_t>(std::chrono::duration_cast<std::chrono::microseconds>(ticks).count());
185 template<
class T =
int>
188 return static_cast<T
>(
ts.tv_nsec);
195 template<
class T =
int>
205 template<
class T =
int>
288# if TIME_SHIELD_PLATFORM_WINDOWS
289 FILETIME create_time{}, exit_time{}, kernel_time{}, user_time{};
290 if (GetProcessTimes(GetCurrentProcess(), &create_time, &exit_time, &kernel_time, &user_time)) {
292 li.LowPart = user_time.dwLowDateTime;
293 li.HighPart = user_time.dwHighDateTime;
294 return static_cast<double>(li.QuadPart) / 10000000.0;
296# elif TIME_SHIELD_PLATFORM_UNIX
298# if defined(_POSIX_TIMERS) && (_POSIX_TIMERS > 0)
299 clockid_t
id = (clockid_t)-1;
300# if defined(_POSIX_CPUTIME) && (_POSIX_CPUTIME > 0)
301 if (clock_getcpuclockid(0, &
id) != 0) {
302# if defined(CLOCK_PROCESS_CPUTIME_ID)
303 id = CLOCK_PROCESS_CPUTIME_ID;
304# elif defined(CLOCK_VIRTUAL)
308# elif defined(CLOCK_PROCESS_CPUTIME_ID)
309 id = CLOCK_PROCESS_CPUTIME_ID;
310# elif defined(CLOCK_VIRTUAL)
313 if (
id != (clockid_t)-1) {
315 if (clock_gettime(
id, &
ts) == 0) {
316 return static_cast<double>(
ts.tv_sec) +
static_cast<double>(
ts.tv_nsec) / 1e9;
321# if defined(RUSAGE_SELF)
322 struct rusage usage{};
323 if (getrusage(RUSAGE_SELF, &usage) == 0) {
324 return static_cast<double>(usage.ru_utime.tv_sec) +
static_cast<double>(usage.ru_utime.tv_usec) / 1e6;
328# if defined(_SC_CLK_TCK)
330 if (times(&t) != (clock_t)-1) {
331 return static_cast<double>(t.tms_utime) /
static_cast<double>(sysconf(_SC_CLK_TCK));
335# if defined(CLOCKS_PER_SEC)
336 clock_t cl = clock();
337 if (cl != (clock_t)-1) {
338 return static_cast<double>(cl) /
static_cast<double>(CLOCKS_PER_SEC);
342# warning "get_cpu_time() may not work correctly: unsupported platform"
344 return std::numeric_limits<double>::quiet_NaN();
Configuration macros for the library.
Header file with time-related constants.
constexpr int64_t NS_PER_US
Nanoseconds per microsecond.
constexpr int64_t NS_PER_MS
Nanoseconds per millisecond.
constexpr int64_t MS_PER_SEC
Milliseconds per second.
constexpr int64_t NS_PER_SEC
Nanoseconds per second.
constexpr int64_t US_PER_SEC
Microseconds per second.
TIME_SHIELD_CONSTEXPR ts_t ts(year_t year, int month, int day)
Alias for to_timestamp.
int64_t ts_t
Unix timestamp in seconds since 1970‑01‑01T00:00:00Z.
int64_t ts_ms_t
Unix timestamp in milliseconds since epoch.
double fts_t
Floating-point timestamp (fractional seconds since epoch).
int64_t ts_us_t
Unix timestamp in microseconds since epoch.
ts_us_t timestamp_us() noexcept
Get the current UTC timestamp in microseconds.
ts_us_t monotonic_us() noexcept
Return monotonic microseconds from a process-local reference.
ts_ms_t now() noexcept
Get the current UTC timestamp in milliseconds.
ts_t monotonic_sec() noexcept
Return monotonic seconds from a process-local reference.
T ns_of_sec() noexcept
Get the nanosecond part of the current second.
int64_t now_realtime_us()
Get current real time in microseconds using a platform-specific method.
ts_t ts() noexcept
Get the current UTC timestamp in seconds.
ts_t timestamp() noexcept
Get the current UTC timestamp in seconds.
fts_t ftimestamp() noexcept
Get the current UTC timestamp in floating-point seconds.
double get_cpu_time() noexcept
Get the CPU time used by the current process.
struct timespec get_timespec_impl() noexcept
Get the current timespec.
ts_us_t ts_us() noexcept
Get the current UTC timestamp in microseconds.
T ms_of_sec() noexcept
Get the millisecond part of the current second.
ts_ms_t monotonic_ms() noexcept
Return monotonic milliseconds from a process-local reference.
ts_ms_t ts_ms() noexcept
Get the current UTC timestamp in milliseconds.
T us_of_sec() noexcept
Get the microsecond part of the current second.
ts_ms_t timestamp_ms() noexcept
Get the current UTC timestamp in milliseconds.
fts_t fts() noexcept
Get the current UTC timestamp in floating-point seconds.
Main namespace for the Time Shield library.
Type definitions for time-related units and formats.