xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/quic/core/quic_time.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef QUICHE_QUIC_CORE_QUIC_TIME_H_
6 #define QUICHE_QUIC_CORE_QUIC_TIME_H_
7 
8 #include <cmath>
9 #include <cstdint>
10 #include <limits>
11 #include <ostream>
12 #include <string>
13 
14 #include "absl/time/time.h"
15 #include "quiche/quic/platform/api/quic_export.h"
16 
17 namespace quic {
18 
19 class QuicClock;
20 class QuicTime;
21 
22 // A 64-bit signed integer type that stores a time duration as
23 // a number of microseconds. QUIC does not use absl::Duration, since the Abseil
24 // type is 128-bit, which would adversely affect certain performance-sensitive
25 // QUIC data structures.
26 class QUICHE_EXPORT QuicTimeDelta {
27  public:
28   // Creates a QuicTimeDelta from an absl::Duration. Note that this inherently
29   // loses precision, since absl::Duration is nanoseconds, and QuicTimeDelta is
30   // microseconds.
QuicTimeDelta(absl::Duration duration)31   explicit QuicTimeDelta(absl::Duration duration)
32       : time_offset_((duration == absl::InfiniteDuration())
33                          ? kInfiniteTimeUs
34                          : absl::ToInt64Microseconds(duration)) {}
35 
36   // Create a object with an offset of 0.
Zero()37   static constexpr QuicTimeDelta Zero() { return QuicTimeDelta(0); }
38 
39   // Create a object with infinite offset time.
Infinite()40   static constexpr QuicTimeDelta Infinite() {
41     return QuicTimeDelta(kInfiniteTimeUs);
42   }
43 
44   // Converts a number of seconds to a time offset.
FromSeconds(int64_t secs)45   static constexpr QuicTimeDelta FromSeconds(int64_t secs) {
46     return QuicTimeDelta(secs * 1000 * 1000);
47   }
48 
49   // Converts a number of milliseconds to a time offset.
FromMilliseconds(int64_t ms)50   static constexpr QuicTimeDelta FromMilliseconds(int64_t ms) {
51     return QuicTimeDelta(ms * 1000);
52   }
53 
54   // Converts a number of microseconds to a time offset.
FromMicroseconds(int64_t us)55   static constexpr QuicTimeDelta FromMicroseconds(int64_t us) {
56     return QuicTimeDelta(us);
57   }
58 
59   // Converts the time offset to a rounded number of seconds.
ToSeconds()60   constexpr int64_t ToSeconds() const { return time_offset_ / 1000 / 1000; }
61 
62   // Converts the time offset to a rounded number of milliseconds.
ToMilliseconds()63   constexpr int64_t ToMilliseconds() const { return time_offset_ / 1000; }
64 
65   // Converts the time offset to a rounded number of microseconds.
ToMicroseconds()66   constexpr int64_t ToMicroseconds() const { return time_offset_; }
67 
68   // Converts the time offset to an Abseil duration.
ToAbsl()69   constexpr absl::Duration ToAbsl() {
70     if (ABSL_PREDICT_FALSE(IsInfinite())) {
71       return absl::InfiniteDuration();
72     }
73     return absl::Microseconds(time_offset_);
74   }
75 
IsZero()76   constexpr bool IsZero() const { return time_offset_ == 0; }
77 
IsInfinite()78   constexpr bool IsInfinite() const { return time_offset_ == kInfiniteTimeUs; }
79 
80   std::string ToDebuggingValue() const;
81 
82  private:
83   friend inline bool operator==(QuicTimeDelta lhs, QuicTimeDelta rhs);
84   friend inline bool operator<(QuicTimeDelta lhs, QuicTimeDelta rhs);
85   friend inline QuicTimeDelta operator<<(QuicTimeDelta lhs, size_t rhs);
86   friend inline QuicTimeDelta operator>>(QuicTimeDelta lhs, size_t rhs);
87 
88   friend inline constexpr QuicTimeDelta operator+(QuicTimeDelta lhs,
89                                                   QuicTimeDelta rhs);
90   friend inline constexpr QuicTimeDelta operator-(QuicTimeDelta lhs,
91                                                   QuicTimeDelta rhs);
92   friend inline constexpr QuicTimeDelta operator*(QuicTimeDelta lhs, int rhs);
93   // Not constexpr since std::llround() is not constexpr.
94   friend inline QuicTimeDelta operator*(QuicTimeDelta lhs, double rhs);
95 
96   friend inline QuicTime operator+(QuicTime lhs, QuicTimeDelta rhs);
97   friend inline QuicTime operator-(QuicTime lhs, QuicTimeDelta rhs);
98   friend inline QuicTimeDelta operator-(QuicTime lhs, QuicTime rhs);
99 
100   static constexpr int64_t kInfiniteTimeUs =
101       std::numeric_limits<int64_t>::max();
102 
QuicTimeDelta(int64_t time_offset)103   explicit constexpr QuicTimeDelta(int64_t time_offset)
104       : time_offset_(time_offset) {}
105 
106   int64_t time_offset_;
107   friend class QuicTime;
108 };
109 
110 // A microsecond precision timestamp returned by a QuicClock. It is
111 // usually either a Unix timestamp or a timestamp returned by the
112 // platform-specific monotonic clock. QuicClock has a method to convert QuicTime
113 // to the wall time.
114 class QUICHE_EXPORT QuicTime {
115  public:
116   using Delta = QuicTimeDelta;
117 
118   // Creates a new QuicTime with an internal value of 0.  IsInitialized()
119   // will return false for these times.
Zero()120   static constexpr QuicTime Zero() { return QuicTime(0); }
121 
122   // Creates a new QuicTime with an infinite time.
Infinite()123   static constexpr QuicTime Infinite() {
124     return QuicTime(Delta::kInfiniteTimeUs);
125   }
126 
127   QuicTime(const QuicTime& other) = default;
128 
129   QuicTime& operator=(const QuicTime& other) {
130     time_ = other.time_;
131     return *this;
132   }
133 
134   // Produce the internal value to be used when logging.  This value
135   // represents the number of microseconds since some epoch.  It may
136   // be the UNIX epoch on some platforms.  On others, it may
137   // be a CPU ticks based value.
ToDebuggingValue()138   int64_t ToDebuggingValue() const { return time_; }
139 
IsInitialized()140   bool IsInitialized() const { return 0 != time_; }
141 
142  private:
143   friend class QuicClock;
144 
145   friend inline bool operator==(QuicTime lhs, QuicTime rhs);
146   friend inline bool operator<(QuicTime lhs, QuicTime rhs);
147   friend inline QuicTime operator+(QuicTime lhs, QuicTimeDelta rhs);
148   friend inline QuicTime operator-(QuicTime lhs, QuicTimeDelta rhs);
149   friend inline QuicTimeDelta operator-(QuicTime lhs, QuicTime rhs);
150 
QuicTime(int64_t time)151   explicit constexpr QuicTime(int64_t time) : time_(time) {}
152 
153   int64_t time_;
154 };
155 
156 // A UNIX timestamp.
157 //
158 // TODO(vasilvv): evaluate whether this can be replaced with absl::Time.
159 class QUICHE_EXPORT QuicWallTime {
160  public:
161   // FromUNIXSeconds constructs a QuicWallTime from a count of the seconds
162   // since the UNIX epoch.
FromUNIXSeconds(uint64_t seconds)163   static constexpr QuicWallTime FromUNIXSeconds(uint64_t seconds) {
164     return QuicWallTime(seconds * 1000000);
165   }
166 
FromUNIXMicroseconds(uint64_t microseconds)167   static constexpr QuicWallTime FromUNIXMicroseconds(uint64_t microseconds) {
168     return QuicWallTime(microseconds);
169   }
170 
171   // Zero returns a QuicWallTime set to zero. IsZero will return true for this
172   // value.
Zero()173   static constexpr QuicWallTime Zero() { return QuicWallTime(0); }
174 
175   // Returns the number of seconds since the UNIX epoch.
176   uint64_t ToUNIXSeconds() const;
177   // Returns the number of microseconds since the UNIX epoch.
178   uint64_t ToUNIXMicroseconds() const;
179 
180   bool IsAfter(QuicWallTime other) const;
181   bool IsBefore(QuicWallTime other) const;
182 
183   // IsZero returns true if this object is the result of calling |Zero|.
184   bool IsZero() const;
185 
186   // AbsoluteDifference returns the absolute value of the time difference
187   // between |this| and |other|.
188   QuicTimeDelta AbsoluteDifference(QuicWallTime other) const;
189 
190   // Add returns a new QuicWallTime that represents the time of |this| plus
191   // |delta|.
192   [[nodiscard]] QuicWallTime Add(QuicTimeDelta delta) const;
193 
194   // Subtract returns a new QuicWallTime that represents the time of |this|
195   // minus |delta|.
196   [[nodiscard]] QuicWallTime Subtract(QuicTimeDelta delta) const;
197 
198   bool operator==(const QuicWallTime& other) const {
199     return microseconds_ == other.microseconds_;
200   }
201 
202   QuicTimeDelta operator-(const QuicWallTime& rhs) const {
203     return QuicTimeDelta::FromMicroseconds(microseconds_ - rhs.microseconds_);
204   }
205 
206  private:
QuicWallTime(uint64_t microseconds)207   explicit constexpr QuicWallTime(uint64_t microseconds)
208       : microseconds_(microseconds) {}
209 
210   uint64_t microseconds_;
211 };
212 
213 // Non-member relational operators for QuicTimeDelta.
214 inline bool operator==(QuicTimeDelta lhs, QuicTimeDelta rhs) {
215   return lhs.time_offset_ == rhs.time_offset_;
216 }
217 inline bool operator!=(QuicTimeDelta lhs, QuicTimeDelta rhs) {
218   return !(lhs == rhs);
219 }
220 inline bool operator<(QuicTimeDelta lhs, QuicTimeDelta rhs) {
221   return lhs.time_offset_ < rhs.time_offset_;
222 }
223 inline bool operator>(QuicTimeDelta lhs, QuicTimeDelta rhs) {
224   return rhs < lhs;
225 }
226 inline bool operator<=(QuicTimeDelta lhs, QuicTimeDelta rhs) {
227   return !(rhs < lhs);
228 }
229 inline bool operator>=(QuicTimeDelta lhs, QuicTimeDelta rhs) {
230   return !(lhs < rhs);
231 }
232 inline QuicTimeDelta operator<<(QuicTimeDelta lhs, size_t rhs) {
233   return QuicTimeDelta(lhs.time_offset_ << rhs);
234 }
235 inline QuicTimeDelta operator>>(QuicTimeDelta lhs, size_t rhs) {
236   return QuicTimeDelta(lhs.time_offset_ >> rhs);
237 }
238 
239 // Non-member relational operators for QuicTime.
240 inline bool operator==(QuicTime lhs, QuicTime rhs) {
241   return lhs.time_ == rhs.time_;
242 }
243 inline bool operator!=(QuicTime lhs, QuicTime rhs) { return !(lhs == rhs); }
244 inline bool operator<(QuicTime lhs, QuicTime rhs) {
245   return lhs.time_ < rhs.time_;
246 }
247 inline bool operator>(QuicTime lhs, QuicTime rhs) { return rhs < lhs; }
248 inline bool operator<=(QuicTime lhs, QuicTime rhs) { return !(rhs < lhs); }
249 inline bool operator>=(QuicTime lhs, QuicTime rhs) { return !(lhs < rhs); }
250 
251 // Override stream output operator for gtest or QUICHE_CHECK macros.
252 inline std::ostream& operator<<(std::ostream& output, const QuicTime t) {
253   output << t.ToDebuggingValue();
254   return output;
255 }
256 
257 // Non-member arithmetic operators for QuicTimeDelta.
258 inline constexpr QuicTimeDelta operator+(QuicTimeDelta lhs, QuicTimeDelta rhs) {
259   return QuicTimeDelta(lhs.time_offset_ + rhs.time_offset_);
260 }
261 inline constexpr QuicTimeDelta operator-(QuicTimeDelta lhs, QuicTimeDelta rhs) {
262   return QuicTimeDelta(lhs.time_offset_ - rhs.time_offset_);
263 }
264 inline constexpr QuicTimeDelta operator*(QuicTimeDelta lhs, int rhs) {
265   return QuicTimeDelta(lhs.time_offset_ * rhs);
266 }
267 inline QuicTimeDelta operator*(QuicTimeDelta lhs, double rhs) {
268   return QuicTimeDelta(static_cast<int64_t>(
269       std::llround(static_cast<double>(lhs.time_offset_) * rhs)));
270 }
271 inline QuicTimeDelta operator*(int lhs, QuicTimeDelta rhs) { return rhs * lhs; }
272 inline QuicTimeDelta operator*(double lhs, QuicTimeDelta rhs) {
273   return rhs * lhs;
274 }
275 
276 // Non-member arithmetic operators for QuicTime and QuicTimeDelta.
277 inline QuicTime operator+(QuicTime lhs, QuicTimeDelta rhs) {
278   return QuicTime(lhs.time_ + rhs.time_offset_);
279 }
280 inline QuicTime operator-(QuicTime lhs, QuicTimeDelta rhs) {
281   return QuicTime(lhs.time_ - rhs.time_offset_);
282 }
283 inline QuicTimeDelta operator-(QuicTime lhs, QuicTime rhs) {
284   return QuicTimeDelta(lhs.time_ - rhs.time_);
285 }
286 
287 // Override stream output operator for gtest.
288 inline std::ostream& operator<<(std::ostream& output,
289                                 const QuicTimeDelta delta) {
290   output << delta.ToDebuggingValue();
291   return output;
292 }
293 }  // namespace quic
294 
295 #endif  // QUICHE_QUIC_CORE_QUIC_TIME_H_
296