userver: userver/engine/deadline.hpp Source File
Loading...
Searching...
No Matches
deadline.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/engine/deadline.hpp
4/// @brief Internal representation of a deadline time point
5
6#include <chrono>
7#include <type_traits>
8
9USERVER_NAMESPACE_BEGIN
10
11namespace engine {
12
13/// @brief Internal representation of a deadline time point
14class Deadline final {
15public:
16 using Clock = std::chrono::steady_clock;
17 using TimePoint = Clock::time_point;
18 using Duration = TimePoint::duration;
19
20 /// Creates an unreachable deadline
21 constexpr Deadline() = default;
22
23 /// Returns whether the deadline can be reached
24 constexpr bool IsReachable() const noexcept { return value_ != kUnreachable; }
25
26 /// Returns whether the deadline is reached
27 bool IsReached() const noexcept;
28
29 /// Returns whether the deadline is reached. Will report false-negatives, will
30 /// never report false-positives.
31 bool IsSurelyReachedApprox() const noexcept;
32
33 /// Returns the duration of time left before the reachable deadline
34 Duration TimeLeft() const noexcept;
35
36 /// Returns the approximate duration of time left before the reachable
37 /// deadline. May be faster than TimeLeft.
38 /// @see utils::datetime::SteadyCoarseClock
39 Duration TimeLeftApprox() const noexcept;
40
41 /// Returns the native time point value.
42 /// Returns `TimePoint::max()` for unreachable deadline
43 /// and `TimePoint::min()` for `Deadline::Passed()`
44 constexpr TimePoint GetTimePoint() const noexcept { return value_; }
45
46 /// Converts duration to a Deadline
47 template <typename Rep, typename Period>
48 static Deadline FromDuration(const std::chrono::duration<Rep, Period>& duration) noexcept {
49 return FromDuration(ToDurationSaturating(duration));
50 }
51
52 static Deadline FromDuration(const Duration& duration) noexcept {
53 if (duration < Duration::zero()) {
54 return Deadline::Passed();
55 }
56 return Deadline{SumWithSaturation(Clock::now(), duration)};
57 }
58
59 /// @brief Converts time point to a Deadline
60 ///
61 /// Non-steady clocks may produce inaccurate Deadlines. Prefer using
62 /// Deadline::FromDuration or std::chrono::steady_clock::time_point
63 /// if possible.
64 template <typename Clock, typename Duration>
65 static Deadline FromTimePoint(const std::chrono::time_point<Clock, Duration>& time_point) noexcept {
66 return FromDuration(time_point - Clock::now());
67 }
68
69 /// @cond
70 /// Specialization for the native time point type
71 constexpr static Deadline FromTimePoint(const TimePoint& time_point) noexcept { return Deadline(time_point); }
72 /// @endcond
73
74 /// A Deadline that is guaranteed to be IsReached
75 constexpr static Deadline Passed() noexcept { return Deadline{kPassed}; }
76
77 constexpr bool operator==(const Deadline& r) const noexcept { return value_ == r.value_; }
78
79 constexpr bool operator<(const Deadline& r) const noexcept {
80 if (!IsReachable()) return false;
81 if (!r.IsReachable()) return true;
82 return value_ < r.value_;
83 }
84
85 /// Converts 'std::chrono::duration<>' to 'Deadline::Duration'
86 template <typename Rep, typename Period>
87 static Duration ToDurationSaturating(const std::chrono::duration<Rep, Period>& from) noexcept {
88 using FromDuration = std::chrono::duration<Rep, Period>;
89
90 // Require resolution of 'FromDuration' higher than 'Duration',
91 // to safely cast 'Duration::max' value to 'FromDuration'
92 static_assert(std::is_constructible_v<Duration, FromDuration>);
93
94 if (std::chrono::duration_cast<FromDuration>(Duration::max()) < from) {
95 return Duration::max();
96 }
97
98 if constexpr (std::is_signed_v<Rep>) {
99 if (from < std::chrono::duration_cast<FromDuration>(Duration::min())) {
100 return Duration::min();
101 }
102 }
103
104 return std::chrono::duration_cast<Duration>(from);
105 }
106
107private:
108 constexpr explicit Deadline(TimePoint value) noexcept : value_(value) {}
109
110 constexpr static TimePoint SumWithSaturation(const TimePoint& time_point, Duration duration) noexcept {
111 return TimePoint::max() - time_point < duration ? TimePoint::max() : time_point + duration;
112 }
113
114 static constexpr TimePoint kUnreachable = TimePoint::max();
115 static constexpr TimePoint kPassed = TimePoint::min();
116
117 TimePoint value_{kUnreachable};
118};
119
120} // namespace engine
121
122USERVER_NAMESPACE_END