diff options
author | ivanmorozov <ivanmorozov@yandex-team.com> | 2022-11-29 15:52:07 +0300 |
---|---|---|
committer | ivanmorozov <ivanmorozov@yandex-team.com> | 2022-11-29 15:52:07 +0300 |
commit | 8ff1738e8665e5c3a1a328104806bcafbc1bd7ae (patch) | |
tree | 9657e2ea4d923a22e69e954fe11fb77e35bc3271 /library/cpp/time_provider | |
parent | db99cf88226de50e47bd3acdc0ecfe634ce1d828 (diff) | |
download | ydb-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.txt | 2 | ||||
-rw-r--r-- | library/cpp/time_provider/monotonic.cpp | 31 | ||||
-rw-r--r-- | library/cpp/time_provider/monotonic.h | 111 | ||||
-rw-r--r-- | library/cpp/time_provider/monotonic_provider.cpp | 32 | ||||
-rw-r--r-- | library/cpp/time_provider/monotonic_provider.h | 21 | ||||
-rw-r--r-- | library/cpp/time_provider/time_provider.cpp | 16 | ||||
-rw-r--r-- | library/cpp/time_provider/time_provider.h | 5 |
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); |