aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/time_provider
diff options
context:
space:
mode:
authorivanmorozov <ivanmorozov@yandex-team.com>2022-11-29 15:52:07 +0300
committerivanmorozov <ivanmorozov@yandex-team.com>2022-11-29 15:52:07 +0300
commit8ff1738e8665e5c3a1a328104806bcafbc1bd7ae (patch)
tree9657e2ea4d923a22e69e954fe11fb77e35bc3271 /library/cpp/time_provider
parentdb99cf88226de50e47bd3acdc0ecfe634ce1d828 (diff)
downloadydb-8ff1738e8665e5c3a1a328104806bcafbc1bd7ae.tar.gz
time providers in separated library for future refactoring
Diffstat (limited to 'library/cpp/time_provider')
-rw-r--r--library/cpp/time_provider/CMakeLists.txt2
-rw-r--r--library/cpp/time_provider/monotonic.cpp31
-rw-r--r--library/cpp/time_provider/monotonic.h111
-rw-r--r--library/cpp/time_provider/monotonic_provider.cpp32
-rw-r--r--library/cpp/time_provider/monotonic_provider.h21
-rw-r--r--library/cpp/time_provider/time_provider.cpp16
-rw-r--r--library/cpp/time_provider/time_provider.h5
7 files changed, 218 insertions, 0 deletions
diff --git a/library/cpp/time_provider/CMakeLists.txt b/library/cpp/time_provider/CMakeLists.txt
index aa7435c8827..eecbe5cf32c 100644
--- a/library/cpp/time_provider/CMakeLists.txt
+++ b/library/cpp/time_provider/CMakeLists.txt
@@ -13,5 +13,7 @@ target_link_libraries(library-cpp-time_provider PUBLIC
yutil
)
target_sources(library-cpp-time_provider PRIVATE
+ ${CMAKE_SOURCE_DIR}/library/cpp/time_provider/monotonic.cpp
${CMAKE_SOURCE_DIR}/library/cpp/time_provider/time_provider.cpp
+ ${CMAKE_SOURCE_DIR}/library/cpp/time_provider/monotonic_provider.cpp
)
diff --git a/library/cpp/time_provider/monotonic.cpp b/library/cpp/time_provider/monotonic.cpp
new file mode 100644
index 00000000000..99126080e2a
--- /dev/null
+++ b/library/cpp/time_provider/monotonic.cpp
@@ -0,0 +1,31 @@
+#include "monotonic.h"
+
+#include <chrono>
+
+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;
+}
+
+} // namespace TMonotonic
+
+template<>
+void Out<NMonotonic::TMonotonic>(
+ IOutputStream& o,
+ NMonotonic::TMonotonic t)
+{
+ o << t - NMonotonic::TMonotonic::Zero();
+}
diff --git a/library/cpp/time_provider/monotonic.h b/library/cpp/time_provider/monotonic.h
new file mode 100644
index 00000000000..e36902d884b
--- /dev/null
+++ b/library/cpp/time_provider/monotonic.h
@@ -0,0 +1,111 @@
+#pragma once
+
+#include <util/datetime/base.h>
+namespace NMonotonic {
+/**
+ * Returns current monotonic time in microseconds
+ */
+ui64 GetMonotonicMicroSeconds();
+
+/**
+ * Similar to TInstant, but measuring monotonic time
+ */
+class TMonotonic: public TTimeBase<TMonotonic> {
+ using TBase = TTimeBase<TMonotonic>;
+
+private:
+ constexpr explicit TMonotonic(TValue value) noexcept
+ : TBase(value) {
+ }
+
+public:
+ constexpr TMonotonic() noexcept {
+ }
+
+ static constexpr TMonotonic FromValue(TValue value) noexcept {
+ return TMonotonic(value);
+ }
+
+ static inline TMonotonic Now() {
+ return TMonotonic::MicroSeconds(GetMonotonicMicroSeconds());
+ }
+
+ using TBase::Days;
+ using TBase::Hours;
+ using TBase::MicroSeconds;
+ using TBase::MilliSeconds;
+ using TBase::Minutes;
+ using TBase::Seconds;
+
+ static constexpr TMonotonic Max() noexcept {
+ return TMonotonic(::Max<ui64>());
+ }
+
+ static constexpr TMonotonic Zero() noexcept {
+ return TMonotonic();
+ }
+
+ static constexpr TMonotonic MicroSeconds(ui64 us) noexcept {
+ return TMonotonic(TInstant::MicroSeconds(us).GetValue());
+ }
+
+ static constexpr TMonotonic MilliSeconds(ui64 ms) noexcept {
+ return TMonotonic(TInstant::MilliSeconds(ms).GetValue());
+ }
+
+ static constexpr TMonotonic Seconds(ui64 s) noexcept {
+ return TMonotonic(TInstant::Seconds(s).GetValue());
+ }
+
+ static constexpr TMonotonic Minutes(ui64 m) noexcept {
+ return TMonotonic(TInstant::Minutes(m).GetValue());
+ }
+
+ static constexpr TMonotonic Hours(ui64 h) noexcept {
+ return TMonotonic(TInstant::Hours(h).GetValue());
+ }
+
+ static constexpr TMonotonic Days(ui64 d) noexcept {
+ return TMonotonic(TInstant::Days(d).GetValue());
+ }
+
+ template<class T>
+ inline TMonotonic& operator+=(const T& t) noexcept {
+ return (*this = (*this + t));
+ }
+
+ template<class T>
+ inline TMonotonic& operator-=(const T& t) noexcept {
+ return (*this = (*this - t));
+ }
+};
+} // namespace NMonotonic
+
+Y_DECLARE_PODTYPE(NMonotonic::TMonotonic);
+
+template<>
+struct THash<NMonotonic::TMonotonic> {
+ size_t operator()(const NMonotonic::TMonotonic& key) const {
+ return THash<NMonotonic::TMonotonic::TValue>()(key.GetValue());
+ }
+};
+
+namespace NMonotonic {
+
+constexpr TDuration operator-(const TMonotonic& l, const TMonotonic& r) {
+ return TInstant::FromValue(l.GetValue()) - TInstant::FromValue(r.GetValue());
+}
+
+constexpr TMonotonic operator+(const TMonotonic& l, const TDuration& r) {
+ TInstant result = TInstant::FromValue(l.GetValue()) + r;
+ return TMonotonic::FromValue(result.GetValue());
+}
+
+constexpr TMonotonic operator-(const TMonotonic& l, const TDuration& r) {
+ TInstant result = TInstant::FromValue(l.GetValue()) - r;
+ return TMonotonic::FromValue(result.GetValue());
+}
+
+} // namespace NMonotonic
+
+using TMonotonic = NMonotonic::TMonotonic;
diff --git a/library/cpp/time_provider/monotonic_provider.cpp b/library/cpp/time_provider/monotonic_provider.cpp
new file mode 100644
index 00000000000..22937bd8731
--- /dev/null
+++ b/library/cpp/time_provider/monotonic_provider.cpp
@@ -0,0 +1,32 @@
+#include "monotonic_provider.h"
+
+namespace {
+TIntrusivePtr<IMonotonicTimeProvider> GlobalMonotonicTimeProvider;
+}
+
+void TMonotonicOperator::RegisterProvider(TIntrusivePtr<IMonotonicTimeProvider> provider) {
+ GlobalMonotonicTimeProvider = provider;
+}
+
+NMonotonic::TMonotonic TMonotonicOperator::Now() {
+ if (GlobalMonotonicTimeProvider) {
+ return GlobalMonotonicTimeProvider->Now();
+ } else {
+ return TMonotonic::Now();
+ }
+}
+
+namespace NMonotonic {
+
+class TDefaultMonotonicTimeProvider: public IMonotonicTimeProvider {
+public:
+ TMonotonic Now() override {
+ return TMonotonic::Now();
+ }
+};
+
+TIntrusivePtr<IMonotonicTimeProvider> CreateDefaultMonotonicTimeProvider() {
+ return TIntrusivePtr<IMonotonicTimeProvider>(new TDefaultMonotonicTimeProvider);
+}
+
+}
diff --git a/library/cpp/time_provider/monotonic_provider.h b/library/cpp/time_provider/monotonic_provider.h
new file mode 100644
index 00000000000..966e2e496ba
--- /dev/null
+++ b/library/cpp/time_provider/monotonic_provider.h
@@ -0,0 +1,21 @@
+#pragma once
+
+#include <util/datetime/base.h>
+#include "monotonic.h"
+
+class IMonotonicTimeProvider: public TThrRefBase {
+public:
+ virtual TMonotonic Now() = 0;
+};
+
+class TMonotonicOperator {
+public:
+ static void RegisterProvider(TIntrusivePtr<IMonotonicTimeProvider> provider);
+ static TMonotonic Now();
+};
+
+namespace NMonotonic {
+
+TIntrusivePtr<IMonotonicTimeProvider> CreateDefaultMonotonicTimeProvider();
+
+}
diff --git a/library/cpp/time_provider/time_provider.cpp b/library/cpp/time_provider/time_provider.cpp
index 6c1ba8e07c9..687681f1ff2 100644
--- a/library/cpp/time_provider/time_provider.cpp
+++ b/library/cpp/time_provider/time_provider.cpp
@@ -28,3 +28,19 @@ TIntrusivePtr<ITimeProvider> CreateDefaultTimeProvider() {
TIntrusivePtr<ITimeProvider> CreateDeterministicTimeProvider(ui64 seed) {
return TIntrusivePtr<ITimeProvider>(new TDeterministicTimeProvider(seed));
}
+
+namespace {
+TIntrusivePtr<ITimeProvider> GlobalTimeProvider;
+}
+
+void TInstantOperator::RegisterProvider(TIntrusivePtr<ITimeProvider> provider) {
+ GlobalTimeProvider = provider;
+}
+
+TInstant TInstantOperator::Now() {
+ if (!GlobalTimeProvider) {
+ return TInstant::Now();
+ } else {
+ return GlobalTimeProvider->Now();
+ }
+}
diff --git a/library/cpp/time_provider/time_provider.h b/library/cpp/time_provider/time_provider.h
index 46e0a885dae..6744e027bdb 100644
--- a/library/cpp/time_provider/time_provider.h
+++ b/library/cpp/time_provider/time_provider.h
@@ -7,5 +7,10 @@ public:
virtual TInstant Now() = 0;
};
+class TInstantOperator {
+ static void RegisterProvider(TIntrusivePtr<ITimeProvider> provider);
+ static TInstant Now();
+};
+
TIntrusivePtr<ITimeProvider> CreateDefaultTimeProvider();
TIntrusivePtr<ITimeProvider> CreateDeterministicTimeProvider(ui64 seed);