userver: userver/engine/deadline.hpp Source File
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
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>& incoming_duration) noexcept {
49 using IncomingDuration = std::chrono::duration<Rep, Period>;
50
51 // Require resolution 'IncomingDuration' <= 'Duration',
52 // so it is safe casting 'Duration::max' to 'IncomingDuration'
53
54 static_assert(std::is_constructible_v<Duration, IncomingDuration>);
55
56 if (std::chrono::duration_cast<IncomingDuration>(Duration::max()) <= incoming_duration) {
57 return Deadline{};
58 }
59
60 if (incoming_duration < IncomingDuration::zero()) {
61 return Deadline::Passed();
62 }
63
64 return Deadline{SumWithSaturation(Clock::now(), std::chrono::duration_cast<Duration>(incoming_duration))};
65 }
66
67 /// @brief Converts time point to a Deadline
68 ///
69 /// Non-steady clocks may produce inaccurate Deadlines. Prefer using
70 /// Deadline::FromDuration or std::chrono::steady_clock::time_point
71 /// if possible.
72 template <typename Clock, typename Duration>
73 static Deadline FromTimePoint(const std::chrono::time_point<Clock, Duration>& time_point) noexcept {
74 return FromDuration(time_point - Clock::now());
75 }
76
77 /// @cond
78 /// Specialization for the native time point type
79 constexpr static Deadline FromTimePoint(const TimePoint& time_point) noexcept { return Deadline(time_point); }
80 /// @endcond
81
82 /// A Deadline that is guaranteed to be IsReached
83 constexpr static Deadline Passed() noexcept { return Deadline{kPassed}; }
84
85 constexpr bool operator==(const Deadline& r) const noexcept { return value_ == r.value_; }
86
87 constexpr bool operator<(const Deadline& r) const noexcept {
88 if (!IsReachable()) return false;
89 if (!r.IsReachable()) return true;
90 return value_ < r.value_;
91 }
92
93private:
94 constexpr explicit Deadline(TimePoint value) noexcept : value_(value) {}
95
96 constexpr static TimePoint SumWithSaturation(const TimePoint& time_point, Duration duration) noexcept {
97 return TimePoint::max() - time_point < duration ? TimePoint::max() : time_point + duration;
98 }
99
100 static constexpr TimePoint kUnreachable = TimePoint::max();
101 static constexpr TimePoint kPassed = TimePoint::min();
102
103 TimePoint value_{kUnreachable};
104};
105
106} // namespace engine
107
108USERVER_NAMESPACE_END