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()) {
81 return false;
82 }
83 if (!r.IsReachable()) {
84 return true;
85 }
86 return value_ < r.value_;
87 }
88
89 /// Converts 'std::chrono::duration<>' to 'Deadline::Duration'
90 template <typename Rep, typename Period>
91 static Duration ToDurationSaturating(const std::chrono::duration<Rep, Period>& from) noexcept {
92 using FromDuration = std::chrono::duration<Rep, Period>;
93
94 // Require resolution of 'FromDuration' higher than 'Duration',
95 // to safely cast 'Duration::max' value to 'FromDuration'
96 static_assert(std::is_constructible_v<Duration, FromDuration>);
97
98 if (std::chrono::duration_cast<FromDuration>(Duration::max()) < from) {
99 return Duration::max();
100 }
101
102 if constexpr (std::is_signed_v<Rep>) {
103 if (from < std::chrono::duration_cast<FromDuration>(Duration::min())) {
104 return Duration::min();
105 }
106 }
107
108 return std::chrono::duration_cast<Duration>(from);
109 }
110
111private:
112 constexpr explicit Deadline(TimePoint value) noexcept : value_(value) {}
113
114 constexpr static TimePoint SumWithSaturation(const TimePoint& time_point, Duration duration) noexcept {
115 return TimePoint::max() - time_point < duration ? TimePoint::max() : time_point + duration;
116 }
117
118 static constexpr TimePoint kUnreachable = TimePoint::max();
119 static constexpr TimePoint kPassed = TimePoint::min();
120
121 TimePoint value_{kUnreachable};
122};
123
124} // namespace engine
125
126USERVER_NAMESPACE_END