Time Shield Library
C++ library for working with time
Loading...
Searching...
No Matches
time_utils.hpp
Go to the documentation of this file.
1#pragma once
2#ifndef _TIME_SHIELD_TIME_UTILS_HPP_INCLUDED
3#define _TIME_SHIELD_TIME_UTILS_HPP_INCLUDED
4
9
10#include "config.hpp"
11#include "types.hpp"
12#include "constants.hpp"
13
14#include <limits> // For std::numeric_limits
15#include <ctime> // For clock_t and timespec (POSIX)
16#include <time.h> // For clock(), times(), etc.
17#include <mutex> // For std::once_flag
18
19#if defined(_WIN32)
20 #include <Windows.h>
21#elif defined(__unix__) || defined(__APPLE__)
22 #include <unistd.h>
23 #include <sys/resource.h>
24 #include <sys/times.h>
25 #include <time.h>
26#else
27 #error "Unsupported platform for get_cpu_time()"
28#endif
29
30namespace time_shield {
31
35 inline const struct timespec get_timespec_impl() noexcept {
36 // https://en.cppreference.com/w/c/chrono/timespec_get
37 struct timespec ts;
38# if defined(CLOCK_REALTIME)
39 clock_gettime(CLOCK_REALTIME, &ts); // Версия для POSIX
40# else
41 timespec_get(&ts, TIME_UTC);
42# endif
43 return ts;
44 }
45
55 inline int64_t now_realtime_us() {
56# if defined(_WIN32)
57 static std::once_flag init_flag;
58 static int64_t s_perf_freq = 0;
59 static int64_t s_anchor_perf = 0;
60 static int64_t s_anchor_realtime_us = 0;
61
62 std::call_once(init_flag, [] {
63 LARGE_INTEGER freq, counter;
64 QueryPerformanceFrequency(&freq);
65 QueryPerformanceCounter(&counter);
66
67 s_perf_freq = freq.QuadPart;
68 s_anchor_perf = counter.QuadPart;
69
70 FILETIME ft;
71 GetSystemTimeAsFileTime(&ft);
72 ULARGE_INTEGER uli;
73 uli.LowPart = ft.dwLowDateTime;
74 uli.HighPart = ft.dwHighDateTime;
75 // Convert from 100ns since 1601 to microseconds since 1970
76 s_anchor_realtime_us = (uli.QuadPart - 116444736000000000ULL) / 10;
77 });
78
79 LARGE_INTEGER now;
80 QueryPerformanceCounter(&now);
81
82 int64_t delta_ticks = now.QuadPart - s_anchor_perf;
83 int64_t delta_us = (delta_ticks * 1000000) / s_perf_freq;
84
85 return s_anchor_realtime_us + delta_us;
86# else
87# error "now_realtime_us() is only supported on Windows."
88# endif
89 }
90
95 template<class T = int>
96 inline const T ns_of_sec() noexcept {
97 const struct timespec ts = get_timespec_impl();
98 return static_cast<T>(ts.tv_nsec);
99 }
100
105 template<class T = int>
106 const T us_of_sec() noexcept {
107 const struct timespec ts = get_timespec_impl();
108 return ts.tv_nsec / NS_PER_US;
109 }
110
115 template<class T = int>
116 const T ms_of_sec() noexcept {
117 const struct timespec ts = get_timespec_impl();
118 return ts.tv_nsec / NS_PER_MS;
119 }
120
123 inline const ts_t ts() noexcept {
124 const struct timespec ts = get_timespec_impl();
125 return ts.tv_sec;
126 }
127
131 inline const ts_t timestamp() noexcept {
132 const struct timespec ts = get_timespec_impl();
133 return ts.tv_sec;
134 }
135
139 inline const fts_t fts() noexcept {
140 const struct timespec ts = get_timespec_impl();
141 return ts.tv_sec + static_cast<fts_t>(ts.tv_nsec) / static_cast<fts_t>(NS_PER_SEC);
142 }
143
147 inline const fts_t ftimestamp() noexcept {
148 const struct timespec ts = get_timespec_impl();
149 return ts.tv_sec + static_cast<fts_t>(ts.tv_nsec) / static_cast<fts_t>(NS_PER_SEC);
150 }
151
155 inline const ts_ms_t ts_ms() noexcept {
156 const struct timespec ts = get_timespec_impl();
157 return MS_PER_SEC * ts.tv_sec + ts.tv_nsec / NS_PER_MS;
158 }
159
163 inline const ts_ms_t timestamp_ms() noexcept {
164 const struct timespec ts = get_timespec_impl();
165 return MS_PER_SEC * ts.tv_sec + ts.tv_nsec / NS_PER_MS;
166 }
167
171 inline const ts_ms_t now() noexcept {
172 const struct timespec ts = get_timespec_impl();
173 return MS_PER_SEC * ts.tv_sec + ts.tv_nsec / NS_PER_MS;
174 }
175
179 inline const ts_us_t ts_us() noexcept {
180 const struct timespec ts = get_timespec_impl();
181 return US_PER_SEC * ts.tv_sec + ts.tv_nsec / NS_PER_US;
182 }
183
187 inline const ts_us_t timestamp_us() noexcept {
188 const struct timespec ts = get_timespec_impl();
189 return US_PER_SEC * ts.tv_sec + ts.tv_nsec / NS_PER_US;
190 }
191
197 inline double get_cpu_time() noexcept {
198# if defined(_WIN32)
199 FILETIME create_time{}, exit_time{}, kernel_time{}, user_time{};
200 if (GetProcessTimes(GetCurrentProcess(), &create_time, &exit_time, &kernel_time, &user_time)) {
201 ULARGE_INTEGER li{};
202 li.LowPart = user_time.dwLowDateTime;
203 li.HighPart = user_time.dwHighDateTime;
204 return static_cast<double>(li.QuadPart) / 10000000.0;
205 }
206# elif defined(__unix__) || defined(__unix) || defined(unix) || (defined(__APPLE__) && defined(__MACH__))
207 // AIX, BSD, Cygwin, HP-UX, Linux, OSX, and Solaris
208# if defined(_POSIX_TIMERS) && (_POSIX_TIMERS > 0)
209 clockid_t id = (clockid_t)-1;
210# if defined(_POSIX_CPUTIME) && (_POSIX_CPUTIME > 0)
211 if (clock_getcpuclockid(0, &id) != 0) {
212# if defined(CLOCK_PROCESS_CPUTIME_ID)
213 id = CLOCK_PROCESS_CPUTIME_ID;
214# elif defined(CLOCK_VIRTUAL)
215 id = CLOCK_VIRTUAL;
216# endif
217 }
218# elif defined(CLOCK_PROCESS_CPUTIME_ID)
219 id = CLOCK_PROCESS_CPUTIME_ID;
220# elif defined(CLOCK_VIRTUAL)
221 id = CLOCK_VIRTUAL;
222# endif
223 if (id != (clockid_t)-1) {
224 struct timespec ts;
225 if (clock_gettime(id, &ts) == 0) {
226 return static_cast<double>(ts.tv_sec) + static_cast<double>(ts.tv_nsec) / 1e9;
227 }
228 }
229# endif
230
231# if defined(RUSAGE_SELF)
232 struct rusage usage{};
233 if (getrusage(RUSAGE_SELF, &usage) == 0) {
234 return static_cast<double>(usage.ru_utime.tv_sec) + static_cast<double>(usage.ru_utime.tv_usec) / 1e6;
235 }
236# endif
237
238# if defined(_SC_CLK_TCK)
239 struct tms t{};
240 if (times(&t) != (clock_t)-1) {
241 return static_cast<double>(t.tms_utime) / static_cast<double>(sysconf(_SC_CLK_TCK));
242 }
243# endif
244
245# if defined(CLOCKS_PER_SEC)
246 clock_t cl = clock();
247 if (cl != (clock_t)-1) {
248 return static_cast<double>(cl) / static_cast<double>(CLOCKS_PER_SEC);
249 }
250# endif
251# else
252# warning "get_cpu_time() may not work correctly: unsupported platform"
253# endif
254 return std::numeric_limits<double>::quiet_NaN();
255 }
256
257}; // namespace time_shield
258
259#endif // _TIME_SHIELD_TIME_UTILS_HPP_INCLUDED
Header file with preprocessor definitions for C++ standards and constexpr usage.
Header file with time-related constants.
constexpr int64_t NS_PER_US
Nanoseconds per microsecond.
Definition constants.hpp:33
constexpr int64_t NS_PER_MS
Nanoseconds per millisecond.
Definition constants.hpp:34
constexpr int64_t MS_PER_SEC
Milliseconds per second.
Definition constants.hpp:39
constexpr int64_t NS_PER_SEC
Nanoseconds per second.
Definition constants.hpp:35
constexpr int64_t US_PER_SEC
Microseconds per second.
Definition constants.hpp:38
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:45
int64_t ts_ms_t
Unix timestamp in milliseconds since epoch.
Definition types.hpp:46
double fts_t
Floating-point timestamp (fractional seconds since epoch).
Definition types.hpp:48
int64_t ts_us_t
Unix timestamp in microseconds since epoch.
Definition types.hpp:47
const ts_us_t timestamp_us() noexcept
Get the current UTC timestamp in microseconds.
const ts_ms_t now() noexcept
Get the current UTC timestamp in milliseconds.
int64_t now_realtime_us()
Get current real time in microseconds using a hybrid method.
const ts_t ts() noexcept
Get the current UTC timestamp in seconds.
const T us_of_sec() noexcept
Get the microsecond part of the current second.
const ts_t timestamp() noexcept
Get the current UTC timestamp in seconds.
const 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.
const T ns_of_sec() noexcept
Get the nanosecond part of the current second.
const ts_us_t ts_us() noexcept
Get the current UTC timestamp in microseconds.
const ts_ms_t ts_ms() noexcept
Get the current UTC timestamp in milliseconds.
const struct timespec get_timespec_impl() noexcept
Get the current timespec.
const ts_ms_t timestamp_ms() noexcept
Get the current UTC timestamp in milliseconds.
const fts_t fts() noexcept
Get the current UTC timestamp in floating-point seconds.
const T ms_of_sec() noexcept
Get the millisecond part of the current second.
Main namespace for the Time Shield library.
Type definitions for time-related units and formats.