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