Time Shield Library
C++ library for working with time
Loading...
Searching...
No Matches
time_utils.hpp
Go to the documentation of this file.
1// SPDX-License-Identifier: MIT
2#pragma once
3#ifndef _TIME_SHIELD_TIME_UTILS_HPP_INCLUDED
4#define _TIME_SHIELD_TIME_UTILS_HPP_INCLUDED
5
10
11#include "config.hpp"
12#include "types.hpp"
13#include "constants.hpp"
14
15#include <limits> // For std::numeric_limits
16#include <ctime> // For clock_t and timespec (POSIX)
17#include <time.h> // For clock(), times(), etc.
18#include <mutex> // For std::once_flag
19
20#if TIME_SHIELD_PLATFORM_WINDOWS
21# ifndef WIN32_LEAN_AND_MEAN
22# define WIN32_LEAN_AND_MEAN
23# endif
24# include <Windows.h>
25#elif TIME_SHIELD_PLATFORM_UNIX
26# include <unistd.h>
27# include <sys/resource.h>
28# include <sys/times.h>
29# include <time.h>
30#else
31# error "Unsupported platform for get_cpu_time()"
32#endif
33
34namespace time_shield {
35
39 inline struct timespec get_timespec_impl() noexcept {
40 // https://en.cppreference.com/w/c/chrono/timespec_get
41 struct timespec ts;
42# if defined(CLOCK_REALTIME)
43 clock_gettime(CLOCK_REALTIME, &ts); // Версия для POSIX
44# else
45 timespec_get(&ts, TIME_UTC);
46# endif
47 return ts;
48 }
49
59 inline int64_t now_realtime_us() {
60# if TIME_SHIELD_PLATFORM_WINDOWS
61 static std::once_flag init_flag;
62 static int64_t s_perf_freq = 0;
63 static int64_t s_anchor_perf = 0;
64 static int64_t s_anchor_realtime_us = 0;
65
66 std::call_once(init_flag, [] {
67 LARGE_INTEGER freq, counter;
68 QueryPerformanceFrequency(&freq);
69 QueryPerformanceCounter(&counter);
70
71 s_perf_freq = freq.QuadPart;
72 s_anchor_perf = counter.QuadPart;
73
74 FILETIME ft;
75 GetSystemTimeAsFileTime(&ft);
76 ULARGE_INTEGER uli;
77 uli.LowPart = ft.dwLowDateTime;
78 uli.HighPart = ft.dwHighDateTime;
79 // Convert from 100ns since 1601 to microseconds since 1970
80 s_anchor_realtime_us = (uli.QuadPart - 116444736000000000ULL) / 10;
81 });
82
83 LARGE_INTEGER now;
84 QueryPerformanceCounter(&now);
85
86 int64_t delta_ticks = now.QuadPart - s_anchor_perf;
87 int64_t delta_us = (delta_ticks * 1000000) / s_perf_freq;
88
89 return s_anchor_realtime_us + delta_us;
90# else
91 // Stub implementation for non-Windows platforms.
92 return 0;
93# endif
94 }
95
100 template<class T = int>
101 inline T ns_of_sec() noexcept {
102 const struct timespec ts = get_timespec_impl();
103 return static_cast<T>(ts.tv_nsec);
104 }
105
110 template<class T = int>
111 T us_of_sec() noexcept {
112 const struct timespec ts = get_timespec_impl();
113 return ts.tv_nsec / NS_PER_US;
114 }
115
120 template<class T = int>
121 T ms_of_sec() noexcept {
122 const struct timespec ts = get_timespec_impl();
123 return ts.tv_nsec / NS_PER_MS;
124 }
125
128 inline ts_t ts() noexcept {
129 const struct timespec ts = get_timespec_impl();
130 return ts.tv_sec;
131 }
132
136 inline ts_t timestamp() noexcept {
137 const struct timespec ts = get_timespec_impl();
138 return ts.tv_sec;
139 }
140
144 inline fts_t fts() noexcept {
145 const struct timespec ts = get_timespec_impl();
146 return ts.tv_sec + static_cast<fts_t>(ts.tv_nsec) / static_cast<fts_t>(NS_PER_SEC);
147 }
148
152 inline fts_t ftimestamp() noexcept {
153 const struct timespec ts = get_timespec_impl();
154 return ts.tv_sec + static_cast<fts_t>(ts.tv_nsec) / static_cast<fts_t>(NS_PER_SEC);
155 }
156
160 inline ts_ms_t ts_ms() noexcept {
161 const struct timespec ts = get_timespec_impl();
162 return MS_PER_SEC * ts.tv_sec + ts.tv_nsec / NS_PER_MS;
163 }
164
168 inline ts_ms_t timestamp_ms() noexcept {
169 const struct timespec ts = get_timespec_impl();
170 return MS_PER_SEC * ts.tv_sec + ts.tv_nsec / NS_PER_MS;
171 }
172
176 inline ts_ms_t now() noexcept {
177 const struct timespec ts = get_timespec_impl();
178 return MS_PER_SEC * ts.tv_sec + ts.tv_nsec / NS_PER_MS;
179 }
180
184 inline ts_us_t ts_us() noexcept {
185 const struct timespec ts = get_timespec_impl();
186 return US_PER_SEC * ts.tv_sec + ts.tv_nsec / NS_PER_US;
187 }
188
192 inline ts_us_t timestamp_us() noexcept {
193 const struct timespec ts = get_timespec_impl();
194 return US_PER_SEC * ts.tv_sec + ts.tv_nsec / NS_PER_US;
195 }
196
202 inline double get_cpu_time() noexcept {
203# if TIME_SHIELD_PLATFORM_WINDOWS
204 FILETIME create_time{}, exit_time{}, kernel_time{}, user_time{};
205 if (GetProcessTimes(GetCurrentProcess(), &create_time, &exit_time, &kernel_time, &user_time)) {
206 ULARGE_INTEGER li{};
207 li.LowPart = user_time.dwLowDateTime;
208 li.HighPart = user_time.dwHighDateTime;
209 return static_cast<double>(li.QuadPart) / 10000000.0;
210 }
211# elif TIME_SHIELD_PLATFORM_UNIX
212 // AIX, BSD, Cygwin, HP-UX, Linux, OSX, and Solaris
213# if defined(_POSIX_TIMERS) && (_POSIX_TIMERS > 0)
214 clockid_t id = (clockid_t)-1;
215# if defined(_POSIX_CPUTIME) && (_POSIX_CPUTIME > 0)
216 if (clock_getcpuclockid(0, &id) != 0) {
217# if defined(CLOCK_PROCESS_CPUTIME_ID)
218 id = CLOCK_PROCESS_CPUTIME_ID;
219# elif defined(CLOCK_VIRTUAL)
220 id = CLOCK_VIRTUAL;
221# endif
222 }
223# elif defined(CLOCK_PROCESS_CPUTIME_ID)
224 id = CLOCK_PROCESS_CPUTIME_ID;
225# elif defined(CLOCK_VIRTUAL)
226 id = CLOCK_VIRTUAL;
227# endif
228 if (id != (clockid_t)-1) {
229 struct timespec ts;
230 if (clock_gettime(id, &ts) == 0) {
231 return static_cast<double>(ts.tv_sec) + static_cast<double>(ts.tv_nsec) / 1e9;
232 }
233 }
234# endif
235
236# if defined(RUSAGE_SELF)
237 struct rusage usage{};
238 if (getrusage(RUSAGE_SELF, &usage) == 0) {
239 return static_cast<double>(usage.ru_utime.tv_sec) + static_cast<double>(usage.ru_utime.tv_usec) / 1e6;
240 }
241# endif
242
243# if defined(_SC_CLK_TCK)
244 struct tms t{};
245 if (times(&t) != (clock_t)-1) {
246 return static_cast<double>(t.tms_utime) / static_cast<double>(sysconf(_SC_CLK_TCK));
247 }
248# endif
249
250# if defined(CLOCKS_PER_SEC)
251 clock_t cl = clock();
252 if (cl != (clock_t)-1) {
253 return static_cast<double>(cl) / static_cast<double>(CLOCKS_PER_SEC);
254 }
255# endif
256# else
257# warning "get_cpu_time() may not work correctly: unsupported platform"
258# endif
259 return std::numeric_limits<double>::quiet_NaN();
260 }
261
262}; // namespace time_shield
263
264#endif // _TIME_SHIELD_TIME_UTILS_HPP_INCLUDED
Configuration macros for the library.
Header file with time-related constants.
constexpr int64_t NS_PER_US
Nanoseconds per microsecond.
Definition constants.hpp:71
constexpr int64_t NS_PER_MS
Nanoseconds per millisecond.
Definition constants.hpp:72
constexpr int64_t MS_PER_SEC
Milliseconds per second.
Definition constants.hpp:77
constexpr int64_t NS_PER_SEC
Nanoseconds per second.
Definition constants.hpp:73
constexpr int64_t US_PER_SEC
Microseconds per second.
Definition constants.hpp:76
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.
Definition types.hpp:46
int64_t ts_ms_t
Unix timestamp in milliseconds since epoch.
Definition types.hpp:47
double fts_t
Floating-point timestamp (fractional seconds since epoch).
Definition types.hpp:49
int64_t ts_us_t
Unix timestamp in microseconds since epoch.
Definition types.hpp:48
ts_us_t timestamp_us() noexcept
Get the current UTC timestamp in microseconds.
ts_ms_t now() noexcept
Get the current UTC timestamp in milliseconds.
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 hybrid 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 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.