blob: 9a5ae7dd5b2e48135f2ddab30701fb2c7e73b2c1 [file] [log] [blame]
QUICHE teama6ef0a62019-03-07 20:34:33 -05001// 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>
vasilvv872e7a32019-03-12 16:42:44 -070020#include <string>
QUICHE teama6ef0a62019-03-07 20:34:33 -050021
22#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050023
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
31namespace quic {
32
33class 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.
38class 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.
45 static constexpr Delta Zero() { return Delta(0); }
46
47 // Create a object with infinite offset time.
48 static constexpr Delta Infinite() { return Delta(kQuicInfiniteTimeUs); }
49
50 // Converts a number of seconds to a time offset.
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.
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.
61 static constexpr Delta FromMicroseconds(int64_t us) { return Delta(us); }
62
63 // Converts the time offset to a rounded number of seconds.
64 inline int64_t ToSeconds() const { return time_offset_ / 1000 / 1000; }
65
66 // Converts the time offset to a rounded number of milliseconds.
67 inline int64_t ToMilliseconds() const { return time_offset_ / 1000; }
68
69 // Converts the time offset to a rounded number of microseconds.
70 inline int64_t ToMicroseconds() const { return time_offset_; }
71
72 inline bool IsZero() const { return time_offset_ == 0; }
73
74 inline bool IsInfinite() const {
75 return time_offset_ == kQuicInfiniteTimeUs;
76 }
77
zhongyi26818ca2019-05-13 17:50:37 -070078 std::string ToDebuggingValue() const;
QUICHE teama6ef0a62019-03-07 20:34:33 -050079
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
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.
108 static constexpr QuicTime Zero() { return QuicTime(0); }
109
110 // Creates a new QuicTime with an infinite time.
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.
126 inline int64_t ToDebuggingValue() const { return time_; }
127
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
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.
147class QUIC_EXPORT_PRIVATE QuicWallTime {
148 public:
149 // FromUNIXSeconds constructs a QuicWallTime from a count of the seconds
150 // since the UNIX epoch.
151 static constexpr QuicWallTime FromUNIXSeconds(uint64_t seconds) {
152 return QuicWallTime(seconds * 1000000);
153 }
154
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.
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:
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.
195inline bool operator==(QuicTime::Delta lhs, QuicTime::Delta rhs) {
196 return lhs.time_offset_ == rhs.time_offset_;
197}
198inline bool operator!=(QuicTime::Delta lhs, QuicTime::Delta rhs) {
199 return !(lhs == rhs);
200}
201inline bool operator<(QuicTime::Delta lhs, QuicTime::Delta rhs) {
202 return lhs.time_offset_ < rhs.time_offset_;
203}
204inline bool operator>(QuicTime::Delta lhs, QuicTime::Delta rhs) {
205 return rhs < lhs;
206}
207inline bool operator<=(QuicTime::Delta lhs, QuicTime::Delta rhs) {
208 return !(rhs < lhs);
209}
210inline bool operator>=(QuicTime::Delta lhs, QuicTime::Delta rhs) {
211 return !(lhs < rhs);
212}
213inline QuicTime::Delta operator>>(QuicTime::Delta lhs, size_t rhs) {
214 return QuicTime::Delta(lhs.time_offset_ >> rhs);
215}
216
217// Non-member relational operators for QuicTime.
218inline bool operator==(QuicTime lhs, QuicTime rhs) {
219 return lhs.time_ == rhs.time_;
220}
221inline bool operator!=(QuicTime lhs, QuicTime rhs) {
222 return !(lhs == rhs);
223}
224inline bool operator<(QuicTime lhs, QuicTime rhs) {
225 return lhs.time_ < rhs.time_;
226}
227inline bool operator>(QuicTime lhs, QuicTime rhs) {
228 return rhs < lhs;
229}
230inline bool operator<=(QuicTime lhs, QuicTime rhs) {
231 return !(rhs < lhs);
232}
233inline bool operator>=(QuicTime lhs, QuicTime rhs) {
234 return !(lhs < rhs);
235}
236
wub967ba572019-04-01 09:27:52 -0700237// Override stream output operator for gtest or CHECK macros.
238inline std::ostream& operator<<(std::ostream& output, const QuicTime t) {
239 output << t.ToDebuggingValue();
240 return output;
241}
242
QUICHE teama6ef0a62019-03-07 20:34:33 -0500243// Non-member arithmetic operators for QuicTime::Delta.
244inline QuicTime::Delta operator+(QuicTime::Delta lhs, QuicTime::Delta rhs) {
245 return QuicTime::Delta(lhs.time_offset_ + rhs.time_offset_);
246}
247inline QuicTime::Delta operator-(QuicTime::Delta lhs, QuicTime::Delta rhs) {
248 return QuicTime::Delta(lhs.time_offset_ - rhs.time_offset_);
249}
250inline QuicTime::Delta operator*(QuicTime::Delta lhs, int rhs) {
251 return QuicTime::Delta(lhs.time_offset_ * rhs);
252}
253inline QuicTime::Delta operator*(QuicTime::Delta lhs, double rhs) {
254 return QuicTime::Delta(
255 static_cast<int64_t>(std::llround(lhs.time_offset_ * rhs)));
256}
257inline QuicTime::Delta operator*(int lhs, QuicTime::Delta rhs) {
258 return rhs * lhs;
259}
260inline QuicTime::Delta operator*(double lhs, QuicTime::Delta rhs) {
261 return rhs * lhs;
262}
263
264// Non-member arithmetic operators for QuicTime and QuicTime::Delta.
265inline QuicTime operator+(QuicTime lhs, QuicTime::Delta rhs) {
266 return QuicTime(lhs.time_ + rhs.time_offset_);
267}
268inline QuicTime operator-(QuicTime lhs, QuicTime::Delta rhs) {
269 return QuicTime(lhs.time_ - rhs.time_offset_);
270}
271inline QuicTime::Delta operator-(QuicTime lhs, QuicTime rhs) {
272 return QuicTime::Delta(lhs.time_ - rhs.time_);
273}
274
275// Override stream output operator for gtest.
276inline std::ostream& operator<<(std::ostream& output,
277 const QuicTime::Delta delta) {
zhongyi26818ca2019-05-13 17:50:37 -0700278 output << delta.ToDebuggingValue();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500279 return output;
280}
281} // namespace quic
282
283#endif // QUICHE_QUIC_CORE_QUIC_TIME_H_