aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/time_provider/monotonic.cpp
diff options
context:
space:
mode:
authorsnaury <snaury@ydb.tech>2023-05-17 00:09:28 +0300
committersnaury <snaury@ydb.tech>2023-05-17 00:09:28 +0300
commit56a6dcb981398ed4ff100c1cee255d0737c80ec3 (patch)
tree5944876280d020cf70fdabc149d704cdeb8694ea /library/cpp/time_provider/monotonic.cpp
parente95347322acfd16b2fd57c40f30718d6b3e42631 (diff)
downloadydb-56a6dcb981398ed4ff100c1cee255d0737c80ec3.tar.gz
Switch TMonotonic to CLOCK_BOOTTIME instead of a separate type
Diffstat (limited to 'library/cpp/time_provider/monotonic.cpp')
-rw-r--r--library/cpp/time_provider/monotonic.cpp88
1 files changed, 48 insertions, 40 deletions
diff --git a/library/cpp/time_provider/monotonic.cpp b/library/cpp/time_provider/monotonic.cpp
index ee0f29e498..f9fb6c5e19 100644
--- a/library/cpp/time_provider/monotonic.cpp
+++ b/library/cpp/time_provider/monotonic.cpp
@@ -2,9 +2,10 @@
#include <chrono>
#include <optional>
+#include <system_error>
#include <util/system/platform.h>
-#ifdef _linux
+#ifdef _linux_
#include <time.h>
#include <string.h>
#endif
@@ -12,23 +13,7 @@
namespace NMonotonic {
namespace {
- // Unfortunately time_since_epoch() is sometimes negative on wine
- // Remember initial time point at program start and use offsets from that
- std::chrono::steady_clock::time_point MonotonicOffset = std::chrono::steady_clock::now();
- }
-
- ui64 GetMonotonicMicroSeconds() {
- auto microseconds = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now() - MonotonicOffset).count();
- // Steady clock is supposed to never jump backwards, but it's better to be safe in case of buggy implementations
- if (Y_UNLIKELY(microseconds < 0)) {
- microseconds = 0;
- }
- // Add one so we never return zero
- return microseconds + 1;
- }
-
-#ifdef _linux_
- namespace {
+#if defined(_linux_) && defined(CLOCK_BOOTTIME)
std::optional<ui64> GetClockBootTimeMicroSeconds() {
struct timespec t;
std::optional<ui64> r;
@@ -37,25 +22,56 @@ namespace NMonotonic {
}
return r;
}
+#endif
- // We want time relative to process start
- std::optional<ui64> BootTimeOffset = GetClockBootTimeMicroSeconds();
- }
+ struct TMonotonicSupport {
+#if defined(_linux_) && defined(CLOCK_BOOTTIME)
+ // We remember initial offset to measure time relative to program
+ // start and so we never return a zero time.
+ std::optional<ui64> BootTimeOffset;
+#endif
+ // Unfortunately time_since_epoch() is sometimes negative on wine
+ // Remember initial time point at program start and use offsets from that
+ std::chrono::steady_clock::time_point SteadyClockOffset;
- ui64 GetBootTimeMicroSeconds() {
- if (Y_UNLIKELY(!BootTimeOffset)) {
- return GetMonotonicMicroSeconds();
- }
+ TMonotonicSupport() {
+#if defined(_linux_) && defined(CLOCK_BOOTTIME)
+ BootTimeOffset = GetClockBootTimeMicroSeconds();
+#endif
+ SteadyClockOffset = std::chrono::steady_clock::now();
+ }
- auto r = GetClockBootTimeMicroSeconds();
- Y_VERIFY(r, "Unexpected clock_gettime(CLOCK_BOOTTIME) failure: %s", strerror(errno));
- return *r - *BootTimeOffset + 1;
+ ui64 GetMicroSeconds() const {
+#if defined(_linux_) && defined(CLOCK_BOOTTIME)
+ if (Y_LIKELY(BootTimeOffset)) {
+ auto r = GetClockBootTimeMicroSeconds();
+ if (Y_UNLIKELY(!r)) {
+ throw std::system_error(
+ std::error_code(errno, std::system_category()),
+ "clock_gettime(CLOCK_BOOTTIME) failed");
+ }
+ // Note: we add 1 so we never return zero
+ return *r - *BootTimeOffset + 1;
+ }
+#endif
+ auto elapsed = std::chrono::steady_clock::now() - SteadyClockOffset;
+ auto microseconds = std::chrono::duration_cast<std::chrono::microseconds>(elapsed).count();
+ // Steady clock is supposed to never jump backwards, but it's
+ // better to be safe in case of buggy implementations
+ if (Y_UNLIKELY(microseconds < 0)) {
+ microseconds = 0;
+ }
+ // Note: we add 1 so we never return zero
+ return ui64(microseconds) + 1;
+ }
+ };
+
+ TMonotonicSupport MonotonicSupport;
}
-#else
- ui64 GetBootTimeMicroSeconds() {
- return GetMonotonicMicroSeconds();
+
+ ui64 GetMonotonicMicroSeconds() {
+ return MonotonicSupport.GetMicroSeconds();
}
-#endif
}
@@ -66,11 +82,3 @@ void Out<NMonotonic::TMonotonic>(
{
o << t - NMonotonic::TMonotonic::Zero();
}
-
-template <>
-void Out<NMonotonic::TBootTime>(
- IOutputStream& o,
- NMonotonic::TBootTime t)
-{
- o << t - NMonotonic::TBootTime::Zero();
-}