QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 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> |
vasilvv | 872e7a3 | 2019-03-12 16:42:44 -0700 | [diff] [blame] | 20 | #include <string> |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 21 | |
| 22 | #include "net/third_party/quiche/src/quic/platform/api/quic_export.h" |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 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. |
| 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 | |
zhongyi | 26818ca | 2019-05-13 17:50:37 -0700 | [diff] [blame] | 78 | std::string ToDebuggingValue() const; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 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 | |
| 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. |
| 147 | class 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. |
| 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 | |
| 217 | // Non-member relational operators for QuicTime. |
| 218 | inline bool operator==(QuicTime lhs, QuicTime rhs) { |
| 219 | return lhs.time_ == rhs.time_; |
| 220 | } |
| 221 | inline bool operator!=(QuicTime lhs, QuicTime rhs) { |
| 222 | return !(lhs == rhs); |
| 223 | } |
| 224 | inline bool operator<(QuicTime lhs, QuicTime rhs) { |
| 225 | return lhs.time_ < rhs.time_; |
| 226 | } |
| 227 | inline bool operator>(QuicTime lhs, QuicTime rhs) { |
| 228 | return rhs < lhs; |
| 229 | } |
| 230 | inline bool operator<=(QuicTime lhs, QuicTime rhs) { |
| 231 | return !(rhs < lhs); |
| 232 | } |
| 233 | inline bool operator>=(QuicTime lhs, QuicTime rhs) { |
| 234 | return !(lhs < rhs); |
| 235 | } |
| 236 | |
wub | 967ba57 | 2019-04-01 09:27:52 -0700 | [diff] [blame] | 237 | // Override stream output operator for gtest or CHECK macros. |
| 238 | inline std::ostream& operator<<(std::ostream& output, const QuicTime t) { |
| 239 | output << t.ToDebuggingValue(); |
| 240 | return output; |
| 241 | } |
| 242 | |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 243 | // Non-member arithmetic operators for QuicTime::Delta. |
| 244 | inline QuicTime::Delta operator+(QuicTime::Delta lhs, QuicTime::Delta rhs) { |
| 245 | return QuicTime::Delta(lhs.time_offset_ + rhs.time_offset_); |
| 246 | } |
| 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, int rhs) { |
| 251 | return QuicTime::Delta(lhs.time_offset_ * rhs); |
| 252 | } |
| 253 | inline QuicTime::Delta operator*(QuicTime::Delta lhs, double rhs) { |
| 254 | return QuicTime::Delta( |
| 255 | static_cast<int64_t>(std::llround(lhs.time_offset_ * rhs))); |
| 256 | } |
| 257 | inline QuicTime::Delta operator*(int lhs, QuicTime::Delta rhs) { |
| 258 | return rhs * lhs; |
| 259 | } |
| 260 | inline QuicTime::Delta operator*(double lhs, QuicTime::Delta rhs) { |
| 261 | return rhs * lhs; |
| 262 | } |
| 263 | |
| 264 | // Non-member arithmetic operators for QuicTime and QuicTime::Delta. |
| 265 | inline QuicTime operator+(QuicTime lhs, QuicTime::Delta rhs) { |
| 266 | return QuicTime(lhs.time_ + rhs.time_offset_); |
| 267 | } |
| 268 | inline QuicTime operator-(QuicTime lhs, QuicTime::Delta rhs) { |
| 269 | return QuicTime(lhs.time_ - rhs.time_offset_); |
| 270 | } |
| 271 | inline QuicTime::Delta operator-(QuicTime lhs, QuicTime rhs) { |
| 272 | return QuicTime::Delta(lhs.time_ - rhs.time_); |
| 273 | } |
| 274 | |
| 275 | // Override stream output operator for gtest. |
| 276 | inline std::ostream& operator<<(std::ostream& output, |
| 277 | const QuicTime::Delta delta) { |
zhongyi | 26818ca | 2019-05-13 17:50:37 -0700 | [diff] [blame] | 278 | output << delta.ToDebuggingValue(); |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 279 | return output; |
| 280 | } |
| 281 | } // namespace quic |
| 282 | |
| 283 | #endif // QUICHE_QUIC_CORE_QUIC_TIME_H_ |