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 // QuicTime represents one point in time, stored in microsecond resolution.
6 // QuicTime is monotonically increasing, even across system clock adjustments.
7 // The epoch (time 0) of QuicTime is unspecified.
8 //
9 // This implementation wraps a int64_t of usec since the epoch.  While
10 // the epoch is the Unix epoch, do not depend on this fact because other
11 // implementations, like Chrome's, do NOT have the same epoch.
12 
13 #ifndef QUICHE_QUIC_CORE_QUIC_TIME_H_
14 #define QUICHE_QUIC_CORE_QUIC_TIME_H_
15 
16 #include <cmath>
17 #include <cstdint>
18 #include <limits>
19 #include <ostream>
20 #include <string>
21 
22 #include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
23 
24 // TODO(vasilvv): replace with ABSL_MUST_USE_RESULT once we're using absl.
25 #if defined(__clang__)
26 #define QUIC_TIME_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
27 #else
28 #define QUIC_TIME_WARN_UNUSED_RESULT
29 #endif /* defined(__clang__) */
30 
31 namespace quic {
32 
33 class QuicClock;
34 
35 // A QuicTime is a purely relative time. QuicTime values from different clocks
36 // cannot be compared to each other. If you need an absolute time, see
37 // QuicWallTime, below.
38 class QUIC_EXPORT_PRIVATE QuicTime {
39  public:
40   // A QuicTime::Delta represents the signed difference between two points in
41   // time, stored in microsecond resolution.
42   class QUIC_EXPORT_PRIVATE Delta {
43    public:
44     // Create a object with an offset of 0.
Zero()45     static constexpr Delta Zero() { return Delta(0); }
46 
47     // Create a object with infinite offset time.
Infinite()48     static constexpr Delta Infinite() { return Delta(kQuicInfiniteTimeUs); }
49 
50     // Converts a number of seconds to a time offset.
FromSeconds(int64_t secs)51     static constexpr Delta FromSeconds(int64_t secs) {
52       return Delta(secs * 1000 * 1000);
53     }
54 
55     // Converts a number of milliseconds to a time offset.
FromMilliseconds(int64_t ms)56     static constexpr Delta FromMilliseconds(int64_t ms) {
57       return Delta(ms * 1000);
58     }
59 
60     // Converts a number of microseconds to a time offset.
FromMicroseconds(int64_t us)61     static constexpr Delta FromMicroseconds(int64_t us) { return Delta(us); }
62 
63     // Converts the time offset to a rounded number of seconds.
ToSeconds()64     inline int64_t ToSeconds() const { return time_offset_ / 1000 / 1000; }
65 
66     // Converts the time offset to a rounded number of milliseconds.
ToMilliseconds()67     inline int64_t ToMilliseconds() const { return time_offset_ / 1000; }
68 
69     // Converts the time offset to a rounded number of microseconds.
ToMicroseconds()70     inline int64_t ToMicroseconds() const { return time_offset_; }
71 
IsZero()72     inline bool IsZero() const { return time_offset_ == 0; }
73 
IsInfinite()74     inline bool IsInfinite() const {
75       return time_offset_ == kQuicInfiniteTimeUs;
76     }
77 
78     std::string ToDebuggingValue() const;
79 
80    private:
81     friend inline bool operator==(QuicTime::Delta lhs, QuicTime::Delta rhs);
82     friend inline bool operator<(QuicTime::Delta lhs, QuicTime::Delta rhs);
83     friend inline QuicTime::Delta operator<<(QuicTime::Delta lhs, size_t rhs);
84     friend inline QuicTime::Delta operator>>(QuicTime::Delta lhs, size_t rhs);
85 
86     friend inline QuicTime::Delta operator+(QuicTime::Delta lhs,
87                                             QuicTime::Delta rhs);
88     friend inline QuicTime::Delta operator-(QuicTime::Delta lhs,
89                                             QuicTime::Delta rhs);
90     friend inline QuicTime::Delta operator*(QuicTime::Delta lhs, int rhs);
91     friend inline QuicTime::Delta operator*(QuicTime::Delta lhs, double rhs);
92 
93     friend inline QuicTime operator+(QuicTime lhs, QuicTime::Delta rhs);
94     friend inline QuicTime operator-(QuicTime lhs, QuicTime::Delta rhs);
95     friend inline QuicTime::Delta operator-(QuicTime lhs, QuicTime rhs);
96 
97     static const int64_t kQuicInfiniteTimeUs =
98         std::numeric_limits<int64_t>::max();
99 
Delta(int64_t time_offset)100     explicit constexpr Delta(int64_t time_offset) : time_offset_(time_offset) {}
101 
102     int64_t time_offset_;
103     friend class QuicTime;
104   };
105 
106   // Creates a new QuicTime with an internal value of 0.  IsInitialized()
107   // will return false for these times.
Zero()108   static constexpr QuicTime Zero() { return QuicTime(0); }
109 
110   // Creates a new QuicTime with an infinite time.
Infinite()111   static constexpr QuicTime Infinite() {
112     return QuicTime(Delta::kQuicInfiniteTimeUs);
113   }
114 
115   QuicTime(const QuicTime& other) = default;
116 
117   QuicTime& operator=(const QuicTime& other) {
118     time_ = other.time_;
119     return *this;
120   }
121 
122   // Produce the internal value to be used when logging.  This value
123   // represents the number of microseconds since some epoch.  It may
124   // be the UNIX epoch on some platforms.  On others, it may
125   // be a CPU ticks based value.
ToDebuggingValue()126   inline int64_t ToDebuggingValue() const { return time_; }
127 
IsInitialized()128   inline bool IsInitialized() const { return 0 != time_; }
129 
130  private:
131   friend class QuicClock;
132 
133   friend inline bool operator==(QuicTime lhs, QuicTime rhs);
134   friend inline bool operator<(QuicTime lhs, QuicTime rhs);
135   friend inline QuicTime operator+(QuicTime lhs, QuicTime::Delta rhs);
136   friend inline QuicTime operator-(QuicTime lhs, QuicTime::Delta rhs);
137   friend inline QuicTime::Delta operator-(QuicTime lhs, QuicTime rhs);
138 
QuicTime(int64_t time)139   explicit constexpr QuicTime(int64_t time) : time_(time) {}
140 
141   int64_t time_;
142 };
143 
144 // A QuicWallTime represents an absolute time that is globally consistent. In
145 // practice, clock-skew means that comparing values from different machines
146 // requires some flexibility.
147 class QUIC_EXPORT_PRIVATE QuicWallTime {
148  public:
149   // FromUNIXSeconds constructs a QuicWallTime from a count of the seconds
150   // since the UNIX epoch.
FromUNIXSeconds(uint64_t seconds)151   static constexpr QuicWallTime FromUNIXSeconds(uint64_t seconds) {
152     return QuicWallTime(seconds * 1000000);
153   }
154 
FromUNIXMicroseconds(uint64_t microseconds)155   static constexpr QuicWallTime FromUNIXMicroseconds(uint64_t microseconds) {
156     return QuicWallTime(microseconds);
157   }
158 
159   // Zero returns a QuicWallTime set to zero. IsZero will return true for this
160   // value.
Zero()161   static constexpr QuicWallTime Zero() { return QuicWallTime(0); }
162 
163   // Returns the number of seconds since the UNIX epoch.
164   uint64_t ToUNIXSeconds() const;
165   // Returns the number of microseconds since the UNIX epoch.
166   uint64_t ToUNIXMicroseconds() const;
167 
168   bool IsAfter(QuicWallTime other) const;
169   bool IsBefore(QuicWallTime other) const;
170 
171   // IsZero returns true if this object is the result of calling |Zero|.
172   bool IsZero() const;
173 
174   // AbsoluteDifference returns the absolute value of the time difference
175   // between |this| and |other|.
176   QuicTime::Delta AbsoluteDifference(QuicWallTime other) const;
177 
178   // Add returns a new QuicWallTime that represents the time of |this| plus
179   // |delta|.
180   QUIC_TIME_WARN_UNUSED_RESULT QuicWallTime Add(QuicTime::Delta delta) const;
181 
182   // Subtract returns a new QuicWallTime that represents the time of |this|
183   // minus |delta|.
184   QUIC_TIME_WARN_UNUSED_RESULT QuicWallTime
185   Subtract(QuicTime::Delta delta) const;
186 
187  private:
QuicWallTime(uint64_t microseconds)188   explicit constexpr QuicWallTime(uint64_t microseconds)
189       : microseconds_(microseconds) {}
190 
191   uint64_t microseconds_;
192 };
193 
194 // Non-member relational operators for QuicTime::Delta.
195 inline bool operator==(QuicTime::Delta lhs, QuicTime::Delta rhs) {
196   return lhs.time_offset_ == rhs.time_offset_;
197 }
198 inline bool operator!=(QuicTime::Delta lhs, QuicTime::Delta rhs) {
199   return !(lhs == rhs);
200 }
201 inline bool operator<(QuicTime::Delta lhs, QuicTime::Delta rhs) {
202   return lhs.time_offset_ < rhs.time_offset_;
203 }
204 inline bool operator>(QuicTime::Delta lhs, QuicTime::Delta rhs) {
205   return rhs < lhs;
206 }
207 inline bool operator<=(QuicTime::Delta lhs, QuicTime::Delta rhs) {
208   return !(rhs < lhs);
209 }
210 inline bool operator>=(QuicTime::Delta lhs, QuicTime::Delta rhs) {
211   return !(lhs < rhs);
212 }
213 inline QuicTime::Delta operator<<(QuicTime::Delta lhs, size_t rhs) {
214   return QuicTime::Delta(lhs.time_offset_ << rhs);
215 }
216 inline QuicTime::Delta operator>>(QuicTime::Delta lhs, size_t rhs) {
217   return QuicTime::Delta(lhs.time_offset_ >> rhs);
218 }
219 
220 // Non-member relational operators for QuicTime.
221 inline bool operator==(QuicTime lhs, QuicTime rhs) {
222   return lhs.time_ == rhs.time_;
223 }
224 inline bool operator!=(QuicTime lhs, QuicTime rhs) {
225   return !(lhs == rhs);
226 }
227 inline bool operator<(QuicTime lhs, QuicTime rhs) {
228   return lhs.time_ < rhs.time_;
229 }
230 inline bool operator>(QuicTime lhs, QuicTime rhs) {
231   return rhs < lhs;
232 }
233 inline bool operator<=(QuicTime lhs, QuicTime rhs) {
234   return !(rhs < lhs);
235 }
236 inline bool operator>=(QuicTime lhs, QuicTime rhs) {
237   return !(lhs < rhs);
238 }
239 
240 // Override stream output operator for gtest or CHECK macros.
241 inline std::ostream& operator<<(std::ostream& output, const QuicTime t) {
242   output << t.ToDebuggingValue();
243   return output;
244 }
245 
246 // Non-member arithmetic operators for QuicTime::Delta.
247 inline QuicTime::Delta operator+(QuicTime::Delta lhs, QuicTime::Delta rhs) {
248   return QuicTime::Delta(lhs.time_offset_ + rhs.time_offset_);
249 }
250 inline QuicTime::Delta operator-(QuicTime::Delta lhs, QuicTime::Delta rhs) {
251   return QuicTime::Delta(lhs.time_offset_ - rhs.time_offset_);
252 }
253 inline QuicTime::Delta operator*(QuicTime::Delta lhs, int rhs) {
254   return QuicTime::Delta(lhs.time_offset_ * rhs);
255 }
256 inline QuicTime::Delta operator*(QuicTime::Delta lhs, double rhs) {
257   return QuicTime::Delta(
258       static_cast<int64_t>(std::llround(lhs.time_offset_ * rhs)));
259 }
260 inline QuicTime::Delta operator*(int lhs, QuicTime::Delta rhs) {
261   return rhs * lhs;
262 }
263 inline QuicTime::Delta operator*(double lhs, QuicTime::Delta rhs) {
264   return rhs * lhs;
265 }
266 
267 // Non-member arithmetic operators for QuicTime and QuicTime::Delta.
268 inline QuicTime operator+(QuicTime lhs, QuicTime::Delta rhs) {
269   return QuicTime(lhs.time_ + rhs.time_offset_);
270 }
271 inline QuicTime operator-(QuicTime lhs, QuicTime::Delta rhs) {
272   return QuicTime(lhs.time_ - rhs.time_offset_);
273 }
274 inline QuicTime::Delta operator-(QuicTime lhs, QuicTime rhs) {
275   return QuicTime::Delta(lhs.time_ - rhs.time_);
276 }
277 
278 // Override stream output operator for gtest.
279 inline std::ostream& operator<<(std::ostream& output,
280                                 const QuicTime::Delta delta) {
281   output << delta.ToDebuggingValue();
282   return output;
283 }
284 }  // namespace quic
285 
286 #endif  // QUICHE_QUIC_CORE_QUIC_TIME_H_
287