qb  2.0.0.0
C++17 Actor Framework
qb Issue Watch Star Fork Follow @isndev
Loading...
Searching...
No Matches
timestamp.h
Go to the documentation of this file.
1
24
25#ifndef FEATURES_TIMESTAMP_H
26#define FEATURES_TIMESTAMP_H
27
28#include <chrono>
29#include <cstdint>
30#include <ratio>
31#include <string>
32#include <string_view>
33#include <type_traits>
34#include <utility>
35#include <iomanip>
36#include <array>
37#include <optional>
38#include <functional>
39#include <thread>
40
41#if defined(__APPLE__)
42#include <mach/mach.h>
43#include <mach/mach_time.h>
44#include <sys/time.h>
45#elif defined(_WIN32) || defined(_WIN64)
46#ifndef WIN32_LEAN_AND_MEAN
47#define WIN32_LEAN_AND_MEAN
48#endif
49#ifndef NOMINMAX
50#define NOMINMAX
51#endif
52#include <windows.h>
53#endif
54
55#include <qb/io.h>
56
57// Forward declarations
58namespace qb {
59class Duration;
60class TimePoint;
61
62// Specialized time points
63class UtcTimePoint;
64class LocalTimePoint;
66class TscTimePoint; // TSC = Time Stamp Counter (formerly RDTS)
67}
68
69namespace qb {
70
76
85class Duration {
86public:
88 using rep = int64_t;
89
91 using chrono_duration = std::chrono::duration<rep, std::nano>;
92
94 static constexpr Duration zero() noexcept { return Duration(0); }
95
97 constexpr Duration() noexcept = default;
98
103 constexpr explicit Duration(rep nanoseconds) noexcept
104 : _duration(nanoseconds) {}
105
112 template <typename Rep, typename Period>
113 constexpr explicit Duration(const std::chrono::duration<Rep, Period>& duration) noexcept
114 : _duration(std::chrono::duration_cast<chrono_duration>(duration).count()) {}
115
116 // Standard special member functions
117 constexpr Duration(const Duration&) noexcept = default;
118 constexpr Duration(Duration&&) noexcept = default;
119 constexpr Duration& operator=(const Duration&) noexcept = default;
120 constexpr Duration& operator=(Duration&&) noexcept = default;
121 ~Duration() noexcept = default;
122
127 [[nodiscard]] constexpr chrono_duration to_chrono() const noexcept {
128 return chrono_duration(_duration);
129 }
130
136 template <typename TargetDuration>
137 [[nodiscard]] constexpr TargetDuration to() const noexcept {
138 return std::chrono::duration_cast<TargetDuration>(to_chrono());
139 }
140
146 [[nodiscard]] static constexpr Duration from_days(rep days) noexcept {
147 return Duration(days * 86400 * 1000000000LL);
148 }
149
155 [[nodiscard]] static constexpr Duration from_hours(rep hours) noexcept {
156 return Duration(hours * 3600 * 1000000000LL);
157 }
158
164 [[nodiscard]] static constexpr Duration from_minutes(rep minutes) noexcept {
165 return Duration(minutes * 60 * 1000000000LL);
166 }
167
173 [[nodiscard]] static constexpr Duration from_seconds(rep seconds) noexcept {
174 return Duration(seconds * 1000000000LL);
175 }
176
182 [[nodiscard]] static constexpr Duration from_milliseconds(rep ms) noexcept {
183 return Duration(ms * 1000000LL);
184 }
185
191 [[nodiscard]] static constexpr Duration from_microseconds(rep us) noexcept {
192 return Duration(us * 1000LL);
193 }
194
200 [[nodiscard]] static constexpr Duration from_nanoseconds(rep ns) noexcept {
201 return Duration(ns);
202 }
203
204 // Value accessors
205
210 [[nodiscard]] constexpr rep days() const noexcept {
211 return _duration / (86400 * 1000000000LL);
212 }
213
218 [[nodiscard]] constexpr double days_float() const noexcept {
219 return static_cast<double>(_duration) / (86400.0 * 1000000000.0);
220 }
221
226 [[nodiscard]] constexpr rep hours() const noexcept {
227 return _duration / (3600 * 1000000000LL);
228 }
229
234 [[nodiscard]] constexpr double hours_float() const noexcept {
235 return static_cast<double>(_duration) / (3600.0 * 1000000000.0);
236 }
237
242 [[nodiscard]] constexpr rep minutes() const noexcept {
243 return _duration / (60 * 1000000000LL);
244 }
245
250 [[nodiscard]] constexpr double minutes_float() const noexcept {
251 return static_cast<double>(_duration) / (60.0 * 1000000000.0);
252 }
253
258 [[nodiscard]] constexpr rep seconds() const noexcept {
259 return _duration / 1000000000LL;
260 }
261
266 [[nodiscard]] constexpr double seconds_float() const noexcept {
267 return static_cast<double>(_duration) / 1000000000.0;
268 }
269
274 [[nodiscard]] constexpr rep milliseconds() const noexcept {
275 return _duration / 1000000LL;
276 }
277
282 [[nodiscard]] constexpr double milliseconds_float() const noexcept {
283 return static_cast<double>(_duration) / 1000000.0;
284 }
285
290 [[nodiscard]] constexpr rep microseconds() const noexcept {
291 return _duration / 1000LL;
292 }
293
298 [[nodiscard]] constexpr double microseconds_float() const noexcept {
299 return static_cast<double>(_duration) / 1000.0;
300 }
301
306 [[nodiscard]] constexpr rep nanoseconds() const noexcept {
307 return _duration;
308 }
309
314 [[nodiscard]] constexpr double nanoseconds_float() const noexcept {
315 return static_cast<double>(_duration);
316 }
317
322 [[nodiscard]] constexpr rep count() const noexcept {
323 return _duration;
324 }
325
326 // Unary operators
327 constexpr Duration operator+() const noexcept { return *this; }
328 constexpr Duration operator-() const noexcept { return Duration(-_duration); }
329
330 // Compound assignment operators
331 constexpr Duration& operator+=(const Duration& other) noexcept {
332 _duration += other._duration;
333 return *this;
334 }
335
336 constexpr Duration& operator-=(const Duration& other) noexcept {
337 _duration -= other._duration;
338 return *this;
339 }
340
341 constexpr Duration& operator*=(rep multiplier) noexcept {
342 _duration *= multiplier;
343 return *this;
344 }
345
346 constexpr Duration& operator/=(rep divisor) noexcept {
347 _duration /= divisor;
348 return *this;
349 }
350
351 constexpr Duration& operator%=(const Duration& other) noexcept {
352 _duration %= other._duration;
353 return *this;
354 }
355
356 // Comparison operators
357 constexpr bool operator==(const Duration& rhs) const noexcept {
358 return count() == rhs.count();
359 }
360
361 constexpr bool operator!=(const Duration& rhs) const noexcept {
362 return count() != rhs.count();
363 }
364
365 constexpr bool operator<(const Duration& rhs) const noexcept {
366 return count() < rhs.count();
367 }
368
369 constexpr bool operator<=(const Duration& rhs) const noexcept {
370 return count() <= rhs.count();
371 }
372
373 constexpr bool operator>(const Duration& rhs) const noexcept {
374 return count() > rhs.count();
375 }
376
377 constexpr bool operator>=(const Duration& rhs) const noexcept {
378 return count() >= rhs.count();
379 }
380
381private:
382 rep _duration{0};
383};
384
385// Binary arithmetic operators for Duration
393constexpr Duration operator+(const Duration& lhs, const Duration& rhs) noexcept {
394 return Duration(lhs.count() + rhs.count());
395}
396
404constexpr Duration operator-(const Duration& lhs, const Duration& rhs) noexcept {
405 return Duration(lhs.count() - rhs.count());
406}
407
415constexpr Duration operator*(const Duration& lhs, Duration::rep rhs) noexcept {
416 return Duration(lhs.count() * rhs);
417}
418
426constexpr Duration operator*(Duration::rep lhs, const Duration& rhs) noexcept {
427 return Duration(lhs * rhs.count());
428}
429
437constexpr Duration operator/(const Duration& lhs, Duration::rep rhs) noexcept {
438 return Duration(lhs.count() / rhs);
439}
440
448constexpr Duration::rep operator/(const Duration& lhs, const Duration& rhs) noexcept {
449 return lhs.count() / rhs.count();
450}
451
459constexpr Duration operator%(const Duration& lhs, Duration::rep rhs) noexcept {
460 return Duration(lhs.count() % rhs);
461}
462
470constexpr Duration operator%(const Duration& lhs, const Duration& rhs) noexcept {
471 return Duration(lhs.count() % rhs.count());
472}
473
474// Literal operators for convenient duration creation
475namespace literals {
482 constexpr Duration operator""_d(unsigned long long days) noexcept {
483 return Duration::from_days(days);
484 }
485
492 constexpr Duration operator""_h(unsigned long long hours) noexcept {
493 return Duration::from_hours(hours);
494 }
495
502 constexpr Duration operator""_min(unsigned long long minutes) noexcept {
503 return Duration::from_minutes(minutes);
504 }
505
512 constexpr Duration operator""_s(unsigned long long seconds) noexcept {
513 return Duration::from_seconds(seconds);
514 }
515
522 constexpr Duration operator""_ms(unsigned long long milliseconds) noexcept {
523 return Duration::from_milliseconds(milliseconds);
524 }
525
532 constexpr Duration operator""_us(unsigned long long microseconds) noexcept {
533 return Duration::from_microseconds(microseconds);
534 }
535
542 constexpr Duration operator""_ns(unsigned long long nanoseconds) noexcept {
543 return Duration::from_nanoseconds(nanoseconds);
544 }
545}
546
556public:
558 using rep = uint64_t;
559
561 using chrono_time_point = std::chrono::time_point<std::chrono::system_clock,
562 std::chrono::duration<rep, std::nano>>;
563
565 static constexpr TimePoint epoch() noexcept { return TimePoint(0); }
566
570 constexpr TimePoint() noexcept = default;
571
576 constexpr explicit TimePoint(rep nanoseconds) noexcept
578
585 template <typename Clock, typename ChronoDuration>
586 explicit TimePoint(const std::chrono::time_point<Clock, ChronoDuration>& time_point) noexcept
587 : _time_since_epoch(std::chrono::duration_cast<std::chrono::nanoseconds>(
588 time_point.time_since_epoch()).count()) {}
589
590 // Standard special member functions
591 constexpr TimePoint(const TimePoint&) noexcept = default;
592 constexpr TimePoint(TimePoint&&) noexcept = default;
593 constexpr TimePoint& operator=(const TimePoint&) noexcept = default;
594 constexpr TimePoint& operator=(TimePoint&&) noexcept = default;
595 ~TimePoint() noexcept = default;
596
601 static TimePoint now() noexcept {
602 // Use the combination of system clock (for absolute time) and
603 // steady clock (for monotonic time between calls)
604 static const auto system_start = std::chrono::system_clock::now();
605 static const auto steady_start = std::chrono::steady_clock::now();
606
607 auto steady_now = std::chrono::steady_clock::now();
608 auto delta = steady_now - steady_start;
609 auto result = system_start + delta;
610
611 return TimePoint(result);
612 }
613
618 [[nodiscard]] chrono_time_point to_chrono() const noexcept {
619 return std::chrono::time_point<std::chrono::system_clock>() +
620 std::chrono::nanoseconds(_time_since_epoch);
621 }
622
629 template <typename Clock, typename ChronoDuration = typename Clock::duration>
630 [[nodiscard]] std::chrono::time_point<Clock, ChronoDuration>
631 to() const noexcept {
632 using target_tp = std::chrono::time_point<Clock, ChronoDuration>;
633 return std::chrono::time_point_cast<ChronoDuration>(
634 target_tp(std::chrono::duration_cast<ChronoDuration>(
635 std::chrono::nanoseconds(_time_since_epoch))));
636 }
637
643 [[nodiscard]] static constexpr TimePoint from_days(int64_t days) noexcept {
644 return TimePoint(days * 86400ULL * 1000000000ULL);
645 }
646
652 [[nodiscard]] static constexpr TimePoint from_hours(int64_t hours) noexcept {
653 return TimePoint(hours * 3600ULL * 1000000000ULL);
654 }
655
661 [[nodiscard]] static constexpr TimePoint from_minutes(int64_t minutes) noexcept {
662 return TimePoint(minutes * 60ULL * 1000000000ULL);
663 }
664
670 [[nodiscard]] static constexpr TimePoint from_seconds(int64_t seconds) noexcept {
671 return TimePoint(seconds * 1000000000ULL);
672 }
673
679 [[nodiscard]] static constexpr TimePoint from_milliseconds(int64_t ms) noexcept {
680 return TimePoint(ms * 1000000ULL);
681 }
682
688 [[nodiscard]] static constexpr TimePoint from_microseconds(int64_t us) noexcept {
689 return TimePoint(us * 1000ULL);
690 }
691
697 [[nodiscard]] static constexpr TimePoint from_nanoseconds(int64_t ns) noexcept {
698 return TimePoint(ns);
699 }
700
706 [[nodiscard]] static std::optional<TimePoint> from_iso8601(std::string_view iso8601) noexcept {
707 try {
708 std::tm tm = {};
709 std::string str_iso8601(iso8601);
710 std::istringstream iss(str_iso8601);
711 iss >> std::get_time(&tm, "%Y-%m-%dT%H:%M:%SZ");
712 if (iss.fail()) {
713 return std::nullopt;
714 }
715 const auto time_since_epoch = std::mktime(&tm);
716 if (time_since_epoch == -1) {
717 return std::nullopt;
718 }
719 return TimePoint(static_cast<rep>(time_since_epoch) * 1000000000ULL);
720 } catch (...) {
721 return std::nullopt;
722 }
723 }
724
731 [[nodiscard]] static std::optional<TimePoint> parse(
732 std::string_view time_string, std::string_view format) noexcept {
733 try {
734 std::tm tm = {};
735 std::string str_time_string(time_string);
736 std::istringstream iss(str_time_string);
737 iss >> std::get_time(&tm, format.data());
738 if (iss.fail()) {
739 return std::nullopt;
740 }
741 const auto time_since_epoch = std::mktime(&tm);
742 if (time_since_epoch == -1) {
743 return std::nullopt;
744 }
745 return TimePoint(static_cast<rep>(time_since_epoch) * 1000000000ULL);
746 } catch (...) {
747 return std::nullopt;
748 }
749 }
750
751 // Value accessors
752
757 [[nodiscard]] constexpr rep days() const noexcept {
758 return _time_since_epoch / (86400ULL * 1000000000ULL);
759 }
760
765 [[nodiscard]] constexpr double days_float() const noexcept {
766 return static_cast<double>(_time_since_epoch) / (86400.0 * 1000000000.0);
767 }
768
773 [[nodiscard]] constexpr rep hours() const noexcept {
774 return _time_since_epoch / (3600ULL * 1000000000ULL);
775 }
776
781 [[nodiscard]] constexpr double hours_float() const noexcept {
782 return static_cast<double>(_time_since_epoch) / (3600.0 * 1000000000.0);
783 }
784
789 [[nodiscard]] constexpr rep minutes() const noexcept {
790 return _time_since_epoch / (60ULL * 1000000000ULL);
791 }
792
797 [[nodiscard]] constexpr double minutes_float() const noexcept {
798 return static_cast<double>(_time_since_epoch) / (60.0 * 1000000000.0);
799 }
800
805 [[nodiscard]] constexpr rep seconds() const noexcept {
806 return _time_since_epoch / 1000000000ULL;
807 }
808
813 [[nodiscard]] constexpr double seconds_float() const noexcept {
814 return static_cast<double>(_time_since_epoch) / 1000000000.0;
815 }
816
821 [[nodiscard]] constexpr rep milliseconds() const noexcept {
822 return _time_since_epoch / 1000000ULL;
823 }
824
829 [[nodiscard]] constexpr double milliseconds_float() const noexcept {
830 return static_cast<double>(_time_since_epoch) / 1000000.0;
831 }
832
837 [[nodiscard]] constexpr rep microseconds() const noexcept {
838 return _time_since_epoch / 1000ULL;
839 }
840
845 [[nodiscard]] constexpr double microseconds_float() const noexcept {
846 return static_cast<double>(_time_since_epoch) / 1000.0;
847 }
848
853 [[nodiscard]] constexpr rep nanoseconds() const noexcept {
854 return _time_since_epoch;
855 }
856
861 [[nodiscard]] constexpr double nanoseconds_float() const noexcept {
862 return static_cast<double>(_time_since_epoch);
863 }
864
869 [[nodiscard]] Duration time_since_epoch() const noexcept {
870 return Duration(static_cast<Duration::rep>(_time_since_epoch));
871 }
872
877 [[nodiscard]] constexpr rep count() const noexcept {
878 return _time_since_epoch;
879 }
880
886 [[nodiscard]] std::string format(std::string_view format) const {
887 const auto time_t_value = static_cast<std::time_t>(seconds());
888 std::tm tm = {};
889
890#if defined(_MSC_VER)
891 gmtime_s(&tm, &time_t_value);
892#else
893 tm = *std::gmtime(&time_t_value);
894#endif
895
896 std::array<char, 128> buffer{};
897 const auto result = std::strftime(buffer.data(), buffer.size(), format.data(), &tm);
898
899 if (result == 0) {
900 return {};
901 }
902
903 return std::string(buffer.data(), result);
904 }
905
910 [[nodiscard]] std::string to_iso8601() const {
911 return format("%Y-%m-%dT%H:%M:%SZ");
912 }
913
918 static uint64_t read_tsc() noexcept {
919#if defined(_MSC_VER)
920 return __rdtsc();
921#elif defined(__i386__)
922 uint64_t x;
923 __asm__ volatile(".byte 0x0f, 0x31" : "=A"(x));
924 return x;
925#elif defined(__x86_64__)
926 unsigned hi, lo;
927 __asm__ __volatile__("rdtsc" : "=a"(lo), "=d"(hi));
928 return ((uint64_t)lo) | (((uint64_t)hi) << 32ULL);
929#else
930 // Fallback to high-resolution clock on platforms without rdtsc
931 const auto now = std::chrono::high_resolution_clock::now();
932 return std::chrono::duration_cast<std::chrono::nanoseconds>(
933 now.time_since_epoch()).count();
934#endif
935 }
936
942 TimePoint& operator+=(const Duration& duration) noexcept {
943 _time_since_epoch += static_cast<rep>(duration.count());
944 return *this;
945 }
946
952 TimePoint& operator-=(const Duration& duration) noexcept {
953 _time_since_epoch -= static_cast<rep>(duration.count());
954 return *this;
955 }
956
961 static uint64_t nano() noexcept {
962 return now().count();
963 }
964
965protected:
967};
968
969// Binary arithmetic operators for TimePoint and Duration
977inline TimePoint operator+(const TimePoint& lhs, const Duration& rhs) noexcept {
978 TimePoint result(lhs);
979 result += rhs;
980 return result;
981}
982
990inline TimePoint operator+(const Duration& lhs, const TimePoint& rhs) noexcept {
991 return rhs + lhs;
992}
993
1001inline TimePoint operator-(const TimePoint& lhs, const Duration& rhs) noexcept {
1002 TimePoint result(lhs);
1003 result -= rhs;
1004 return result;
1005}
1006
1014inline Duration operator-(const TimePoint& lhs, const TimePoint& rhs) noexcept {
1015 return Duration(static_cast<Duration::rep>(lhs.count() - rhs.count()));
1016}
1017
1018// Comparison operators for TimePoint
1026constexpr bool operator==(const TimePoint& lhs, const TimePoint& rhs) noexcept {
1027 return lhs.count() == rhs.count();
1028}
1029
1037constexpr bool operator!=(const TimePoint& lhs, const TimePoint& rhs) noexcept {
1038 return lhs.count() != rhs.count();
1039}
1040
1048constexpr bool operator<(const TimePoint& lhs, const TimePoint& rhs) noexcept {
1049 return lhs.count() < rhs.count();
1050}
1051
1059constexpr bool operator<=(const TimePoint& lhs, const TimePoint& rhs) noexcept {
1060 return lhs.count() <= rhs.count();
1061}
1062
1070constexpr bool operator>(const TimePoint& lhs, const TimePoint& rhs) noexcept {
1071 return lhs.count() > rhs.count();
1072}
1073
1081constexpr bool operator>=(const TimePoint& lhs, const TimePoint& rhs) noexcept {
1082 return lhs.count() >= rhs.count();
1083}
1084
1085// Backward compatibility typedefs
1093
1101
1108class UtcTimePoint : public TimePoint {
1109public:
1111
1116
1121 static UtcTimePoint now() noexcept {
1122 auto tp = TimePoint::now();
1123 UtcTimePoint result;
1124 // Convert timepoint to epoch value and construct UtcTimePoint with it
1125 result = UtcTimePoint(tp.count());
1126 return result;
1127 }
1128};
1129
1137public:
1139
1144
1149 static LocalTimePoint now() noexcept {
1150 auto tp = TimePoint::now();
1151 LocalTimePoint result;
1152 // Convert timepoint to epoch value and construct LocalTimePoint with it
1153 result = LocalTimePoint(tp.count());
1154 return result;
1155 }
1156
1162 [[nodiscard]] std::string format_local(std::string_view format) const {
1163 const auto time_t_value = static_cast<std::time_t>(seconds());
1164 std::tm tm = {};
1165
1166#if defined(_MSC_VER)
1167 localtime_s(&tm, &time_t_value);
1168#else
1169 tm = *std::localtime(&time_t_value);
1170#endif
1171
1172 std::array<char, 128> buffer{};
1173 const auto result = std::strftime(buffer.data(), buffer.size(), format.data(), &tm);
1174
1175 if (result == 0) {
1176 return {};
1177 }
1178
1179 return std::string(buffer.data(), result);
1180 }
1181};
1182
1191public:
1193
1198
1203 static HighResTimePoint now() noexcept {
1204 auto tp = TimePoint::now();
1205 HighResTimePoint result;
1206 // Convert timepoint to epoch value and construct HighResTimePoint with it
1207 result = HighResTimePoint(tp.count());
1208 return result;
1209 }
1210};
1211
1220class TscTimePoint : public TimePoint {
1221public:
1223
1228
1233 static TscTimePoint now() noexcept {
1234 static const auto system_time_at_init = TimePoint::now();
1235 static const auto tsc_at_init = TimePoint::read_tsc();
1236 static const auto tsc_frequency = calibrate_tsc_frequency();
1237
1238 const auto tsc_elapsed = TimePoint::read_tsc() - tsc_at_init;
1239 const auto seconds_elapsed = static_cast<double>(tsc_elapsed) / tsc_frequency;
1240 const auto nanoseconds_elapsed = static_cast<uint64_t>(seconds_elapsed * 1e9);
1241
1242 return TscTimePoint(system_time_at_init.count() + nanoseconds_elapsed);
1243 }
1244
1245private:
1250 static double calibrate_tsc_frequency() noexcept {
1251 const auto start_time = TimePoint::now();
1252 const auto start_tsc = TimePoint::read_tsc();
1253
1254 // Sleep for a short time to get a measurement
1255 std::this_thread::sleep_for(std::chrono::milliseconds(10));
1256
1257 const auto end_time = TimePoint::now();
1258 const auto end_tsc = TimePoint::read_tsc();
1259
1260 const auto time_diff_ns = end_time.count() - start_time.count();
1261 const auto tsc_diff = end_tsc - start_tsc;
1262
1263 return static_cast<double>(tsc_diff) * 1e9 / static_cast<double>(time_diff_ns);
1264 }
1265};
1266
1274
1282
1290
1298
1307public:
1308 using TimerCallback = std::function<void(Duration)>;
1309
1314 explicit ScopedTimer(TimerCallback callback)
1315 : _start_time(HighResTimePoint::now())
1316 , _callback(std::move(callback))
1317 , _active(true) {}
1318
1323 stop();
1324 }
1325
1331 if (!_active) {
1332 return _elapsed;
1333 }
1334
1335 _active = false;
1336 _elapsed = HighResTimePoint::now() - _start_time;
1337
1338 if (_callback) {
1339 _callback(_elapsed);
1340 }
1341
1342 return _elapsed;
1343 }
1344
1348 void restart() {
1349 _start_time = HighResTimePoint::now();
1350 _active = true;
1351 }
1352
1358 if (!_active) {
1359 return _elapsed;
1360 }
1361
1362 return HighResTimePoint::now() - _start_time;
1363 }
1364
1365 // Deleted copy/move operations to prevent double-stopping
1366 ScopedTimer(const ScopedTimer&) = delete;
1367 ScopedTimer& operator=(const ScopedTimer&) = delete;
1368 ScopedTimer(ScopedTimer&&) = delete;
1369 ScopedTimer& operator=(ScopedTimer&&) = delete;
1370
1371private:
1372 HighResTimePoint _start_time;
1373 TimerCallback _callback;
1374 Duration _elapsed{0};
1375 bool _active;
1376};
1377
1386public:
1391 explicit LogTimer(std::string reason)
1392 : _reason(std::move(reason))
1393 , _timer([this](Duration duration) {
1394 qb::io::cout() << _reason << ": " << duration.microseconds() << "us" << std::endl;
1395 }) {}
1396
1402 return _timer.elapsed();
1403 }
1404
1405private:
1406 std::string _reason;
1407 ScopedTimer _timer;
1408};
1409
1410} // namespace qb
1411
1412// Stream operators
1420inline std::ostream& operator<<(std::ostream& os, const qb::TimePoint& tp) {
1421 return os << tp.to_iso8601();
1422}
1423
1431inline std::ostream& operator<<(std::ostream& os, const qb::Duration& d) {
1432 auto seconds = d.seconds();
1433 auto nanoseconds = d.nanoseconds() % 1000000000LL;
1434
1435 if (nanoseconds == 0) {
1436 return os << seconds << "s";
1437 } else if (nanoseconds % 1000000LL == 0) {
1438 return os << seconds << "s " << (nanoseconds / 1000000LL) << "ms";
1439 } else if (nanoseconds % 1000LL == 0) {
1440 return os << seconds << "s " << (nanoseconds / 1000LL) << "us";
1441 } else {
1442 return os << seconds << "s " << nanoseconds << "ns";
1443 }
1444}
1445
1446// Hash support for unordered containers
1447namespace std {
1457 template<>
1458 struct hash<qb::Duration> {
1464 size_t operator()(const qb::Duration& duration) const noexcept {
1465 return std::hash<int64_t>{}(duration.count());
1466 }
1467 };
1468
1478 template<>
1479 struct hash<qb::TimePoint> {
1485 size_t operator()(const qb::TimePoint& time_point) const noexcept {
1486 return std::hash<uint64_t>{}(time_point.count());
1487 }
1488 };
1489}
1490
1491// std::formatter support (C++20)
1492#if __cplusplus >= 202002L
1493namespace std {
1494 template<>
1495 struct formatter<qb::TimePoint> {
1496 constexpr auto parse(format_parse_context& ctx) {
1497 return ctx.begin();
1498 }
1499
1500 auto format(const qb::TimePoint& tp, format_context& ctx) const {
1501 return format_to(ctx.out(), "{}", tp.to_iso8601());
1502 }
1503 };
1504
1505 template<>
1506 struct formatter<qb::Duration> {
1507 constexpr auto parse(format_parse_context& ctx) {
1508 return ctx.begin();
1509 }
1510
1511 auto format(const qb::Duration& d, format_context& ctx) const {
1512 auto seconds = d.seconds();
1513 auto nanoseconds = d.nanoseconds() % 1000000000LL;
1514
1515 if (nanoseconds == 0) {
1516 return format_to(ctx.out(), "{}s", seconds);
1517 } else if (nanoseconds % 1000000LL == 0) {
1518 return format_to(ctx.out(), "{}s {}ms", seconds, nanoseconds / 1000000LL);
1519 } else if (nanoseconds % 1000LL == 0) {
1520 return format_to(ctx.out(), "{}s {}us", seconds, nanoseconds / 1000LL);
1521 } else {
1522 return format_to(ctx.out(), "{}s {}ns", seconds, nanoseconds);
1523 }
1524 }
1525 };
1526}
1527#endif
1528
1529#endif // FEATURES_TIMESTAMP_H
Represents a duration with nanosecond precision.
Definition timestamp.h:85
constexpr double minutes_float() const noexcept
Gets the duration in minutes with fractional precision.
Definition timestamp.h:250
constexpr rep minutes() const noexcept
Gets the duration in minutes.
Definition timestamp.h:242
constexpr rep seconds() const noexcept
Gets the duration in seconds.
Definition timestamp.h:258
constexpr double nanoseconds_float() const noexcept
Gets the duration in nanoseconds with double precision.
Definition timestamp.h:314
constexpr rep days() const noexcept
Gets the duration in days.
Definition timestamp.h:210
static constexpr Duration from_nanoseconds(rep ns) noexcept
Factory method to create a Duration from nanoseconds.
Definition timestamp.h:200
constexpr double hours_float() const noexcept
Gets the duration in hours with fractional precision.
Definition timestamp.h:234
constexpr TargetDuration to() const noexcept
Converts to any std::chrono::duration.
Definition timestamp.h:137
static constexpr Duration from_microseconds(rep us) noexcept
Factory method to create a Duration from microseconds.
Definition timestamp.h:191
constexpr double days_float() const noexcept
Gets the duration in days with fractional precision.
Definition timestamp.h:218
constexpr double seconds_float() const noexcept
Gets the duration in seconds with fractional precision.
Definition timestamp.h:266
static constexpr Duration from_hours(rep hours) noexcept
Factory method to create a Duration from hours.
Definition timestamp.h:155
static constexpr Duration from_days(rep days) noexcept
Factory method to create a Duration from days.
Definition timestamp.h:146
int64_t rep
Type used for nanosecond representation.
Definition timestamp.h:88
constexpr rep milliseconds() const noexcept
Gets the duration in milliseconds.
Definition timestamp.h:274
constexpr Duration() noexcept=default
Default constructor, initializes to zero.
constexpr double milliseconds_float() const noexcept
Gets the duration in milliseconds with fractional precision.
Definition timestamp.h:282
static constexpr Duration zero() noexcept
Represents zero duration.
Definition timestamp.h:94
static constexpr Duration from_milliseconds(rep ms) noexcept
Factory method to create a Duration from milliseconds.
Definition timestamp.h:182
static constexpr Duration from_seconds(rep seconds) noexcept
Factory method to create a Duration from seconds.
Definition timestamp.h:173
constexpr rep nanoseconds() const noexcept
Gets the duration in nanoseconds.
Definition timestamp.h:306
constexpr rep count() const noexcept
Gets the total duration in nanoseconds.
Definition timestamp.h:322
std::chrono::duration< rep, std::nano > chrono_duration
Underlying chrono duration type (nanoseconds)
Definition timestamp.h:91
constexpr Duration(const std::chrono::duration< Rep, Period > &duration) noexcept
Constructs a duration from std::chrono::duration.
Definition timestamp.h:113
constexpr rep microseconds() const noexcept
Gets the duration in microseconds.
Definition timestamp.h:290
static constexpr Duration from_minutes(rep minutes) noexcept
Factory method to create a Duration from minutes.
Definition timestamp.h:164
constexpr double microseconds_float() const noexcept
Gets the duration in microseconds with fractional precision.
Definition timestamp.h:298
constexpr rep hours() const noexcept
Gets the duration in hours.
Definition timestamp.h:226
constexpr chrono_duration to_chrono() const noexcept
Converts to std::chrono::duration.
Definition timestamp.h:127
Represents a high-resolution time point.
Definition timestamp.h:1190
static HighResTimePoint now() noexcept
Gets current high-resolution time.
Definition timestamp.h:1203
constexpr TimePoint() noexcept=default
Default constructor, initializes to epoch.
HighResTimePoint()
Default constructor, initializes to current high-resolution time.
Definition timestamp.h:1197
Represents a local time point with nanosecond precision.
Definition timestamp.h:1136
constexpr TimePoint() noexcept=default
Default constructor, initializes to epoch.
LocalTimePoint()
Default constructor, initializes to current local time.
Definition timestamp.h:1143
static LocalTimePoint now() noexcept
Gets current local time.
Definition timestamp.h:1149
std::string format_local(std::string_view format) const
Formats the time point as a local time string.
Definition timestamp.h:1162
LogTimer(std::string reason)
Constructs a timer with a descriptive reason.
Definition timestamp.h:1391
Duration elapsed() const
Gets elapsed time without stopping timer.
Definition timestamp.h:1401
Utility for measuring code block execution time.
Definition timestamp.h:1306
Duration elapsed() const
Gets elapsed time without stopping timer.
Definition timestamp.h:1357
Duration stop()
Stops the timer and invokes callback if active.
Definition timestamp.h:1330
ScopedTimer(TimerCallback callback)
Constructs a timer with a callback.
Definition timestamp.h:1314
~ScopedTimer()
Destructor that invokes callback with elapsed time.
Definition timestamp.h:1322
void restart()
Restarts the timer.
Definition timestamp.h:1348
Represents a point in time with nanosecond precision.
Definition timestamp.h:555
constexpr double minutes_float() const noexcept
Gets the time in minutes since epoch with fractional precision.
Definition timestamp.h:797
TimePoint(const std::chrono::time_point< Clock, ChronoDuration > &time_point) noexcept
Constructs a time point from std::chrono::time_point.
Definition timestamp.h:586
constexpr double hours_float() const noexcept
Gets the time in hours since epoch with fractional precision.
Definition timestamp.h:781
std::string format(std::string_view format) const
Formats the time point as a string.
Definition timestamp.h:886
constexpr double microseconds_float() const noexcept
Gets the time in microseconds since epoch with fractional precision.
Definition timestamp.h:845
constexpr rep nanoseconds() const noexcept
Gets the time in nanoseconds since epoch.
Definition timestamp.h:853
constexpr rep minutes() const noexcept
Gets the time in minutes since epoch.
Definition timestamp.h:789
constexpr double days_float() const noexcept
Gets the time in days since epoch with fractional precision.
Definition timestamp.h:765
rep _time_since_epoch
Time in nanoseconds since epoch.
Definition timestamp.h:966
static std::optional< TimePoint > from_iso8601(std::string_view iso8601) noexcept
Creates a TimePoint from ISO8601 string.
Definition timestamp.h:706
Duration time_since_epoch() const noexcept
Gets the duration since epoch.
Definition timestamp.h:869
constexpr rep seconds() const noexcept
Gets the time in seconds since epoch.
Definition timestamp.h:805
static constexpr TimePoint from_milliseconds(int64_t ms) noexcept
Factory method to create a TimePoint from milliseconds since epoch.
Definition timestamp.h:679
constexpr TimePoint() noexcept=default
Default constructor, initializes to epoch.
constexpr rep hours() const noexcept
Gets the time in hours since epoch.
Definition timestamp.h:773
static TimePoint now() noexcept
Gets current system time.
Definition timestamp.h:601
chrono_time_point to_chrono() const noexcept
Converts to std::chrono::time_point.
Definition timestamp.h:618
TimePoint & operator-=(const Duration &duration) noexcept
Subtracts a duration from this time point.
Definition timestamp.h:952
TimePoint & operator+=(const Duration &duration) noexcept
Adds a duration to this time point.
Definition timestamp.h:942
static constexpr TimePoint from_days(int64_t days) noexcept
Factory method to create a TimePoint from days since epoch.
Definition timestamp.h:643
static constexpr TimePoint from_minutes(int64_t minutes) noexcept
Factory method to create a TimePoint from minutes since epoch.
Definition timestamp.h:661
constexpr rep days() const noexcept
Gets the time in days since epoch.
Definition timestamp.h:757
static constexpr TimePoint from_nanoseconds(int64_t ns) noexcept
Factory method to create a TimePoint from nanoseconds since epoch.
Definition timestamp.h:697
static constexpr TimePoint from_seconds(int64_t seconds) noexcept
Factory method to create a TimePoint from seconds since epoch.
Definition timestamp.h:670
constexpr double nanoseconds_float() const noexcept
Gets the time in nanoseconds since epoch with double precision.
Definition timestamp.h:861
constexpr rep count() const noexcept
Gets the total time in nanoseconds since epoch.
Definition timestamp.h:877
uint64_t rep
Type used for nanosecond representation.
Definition timestamp.h:558
std::string to_iso8601() const
Converts to ISO8601 string.
Definition timestamp.h:910
static constexpr TimePoint epoch() noexcept
Represents the epoch (1970-01-01 00:00:00 UTC)
Definition timestamp.h:565
static uint64_t nano() noexcept
Gets the current time in nanoseconds since epoch.
Definition timestamp.h:961
constexpr double milliseconds_float() const noexcept
Gets the time in milliseconds since epoch with fractional precision.
Definition timestamp.h:829
constexpr rep milliseconds() const noexcept
Gets the time in milliseconds since epoch.
Definition timestamp.h:821
std::chrono::time_point< Clock, ChronoDuration > to() const noexcept
Converts to any std::chrono::time_point.
Definition timestamp.h:631
static constexpr TimePoint from_microseconds(int64_t us) noexcept
Factory method to create a TimePoint from microseconds since epoch.
Definition timestamp.h:688
static uint64_t read_tsc() noexcept
Reads CPU timestamp counter.
Definition timestamp.h:918
std::chrono::time_point< std::chrono::system_clock, std::chrono::duration< rep, std::nano > > chrono_time_point
Underlying std::chrono time point type.
Definition timestamp.h:561
static constexpr TimePoint from_hours(int64_t hours) noexcept
Factory method to create a TimePoint from hours since epoch.
Definition timestamp.h:652
static std::optional< TimePoint > parse(std::string_view time_string, std::string_view format) noexcept
Factory method to parse a string into a TimePoint.
Definition timestamp.h:731
constexpr rep microseconds() const noexcept
Gets the time in microseconds since epoch.
Definition timestamp.h:837
constexpr double seconds_float() const noexcept
Gets the time in seconds since epoch with fractional precision.
Definition timestamp.h:813
Represents a time point based on CPU's timestamp counter.
Definition timestamp.h:1220
TscTimePoint()
Default constructor, initializes to current TSC time.
Definition timestamp.h:1227
static TscTimePoint now() noexcept
Gets current TSC time calibrated to system time.
Definition timestamp.h:1233
constexpr TimePoint() noexcept=default
Default constructor, initializes to epoch.
Represents a UTC time point with nanosecond precision.
Definition timestamp.h:1108
static UtcTimePoint now() noexcept
Gets current UTC time.
Definition timestamp.h:1121
constexpr TimePoint() noexcept=default
Default constructor, initializes to epoch.
UtcTimePoint()
Default constructor, initializes to current UTC time.
Definition timestamp.h:1115
Thread-safe console output class.
Definition io.h:100
constexpr Duration operator*(const Duration &lhs, Duration::rep rhs) noexcept
Multiplies a duration by a scalar value.
Definition timestamp.h:415
constexpr bool operator<(const TimePoint &lhs, const TimePoint &rhs) noexcept
Less than comparison for time points.
Definition timestamp.h:1048
constexpr bool operator<=(const TimePoint &lhs, const TimePoint &rhs) noexcept
Less than or equal comparison for time points.
Definition timestamp.h:1059
TscTimePoint RdtsTimestamp
Backward compatibility alias for TscTimePoint.
Definition timestamp.h:1297
constexpr Duration operator-(const Duration &lhs, const Duration &rhs) noexcept
Subtracts second duration from first.
Definition timestamp.h:404
constexpr bool operator>=(const TimePoint &lhs, const TimePoint &rhs) noexcept
Greater than or equal comparison for time points.
Definition timestamp.h:1081
TimePoint Timestamp
Backward compatibility alias for TimePoint.
Definition timestamp.h:1100
UtcTimePoint UtcTimestamp
Backward compatibility alias for UtcTimePoint.
Definition timestamp.h:1273
constexpr bool operator>(const TimePoint &lhs, const TimePoint &rhs) noexcept
Greater than comparison for time points.
Definition timestamp.h:1070
HighResTimePoint NanoTimestamp
Backward compatibility alias for HighResTimePoint.
Definition timestamp.h:1289
constexpr Duration operator/(const Duration &lhs, Duration::rep rhs) noexcept
Divides a duration by a scalar value.
Definition timestamp.h:437
Duration Timespan
Backward compatibility alias for Duration.
Definition timestamp.h:1092
LocalTimePoint LocalTimestamp
Backward compatibility alias for LocalTimePoint.
Definition timestamp.h:1281
std::ostream & operator<<(std::ostream &os, const qb::TimePoint &tp)
Stream insertion operator for TimePoint.
Definition timestamp.h:1420
constexpr Duration operator%(const Duration &lhs, Duration::rep rhs) noexcept
Calculates the remainder of dividing a duration by a scalar.
Definition timestamp.h:459
Core I/O and logging utilities for the qb framework.
string< std::max(_Size1, _Size2)> operator+(const string< _Size1 > &lhs, const string< _Size2 > &rhs) noexcept
Concatenation operator.
Definition string.h:1078
size_t operator()(const qb::Duration &duration) const noexcept
Hash function operator for Duration.
Definition timestamp.h:1464
size_t operator()(const qb::TimePoint &time_point) const noexcept
Hash function operator for TimePoint.
Definition timestamp.h:1485