Project import generated by Copybara.
PiperOrigin-RevId: 237361882
Change-Id: I109a68f44db867b20f8c6a7732b0ce657133e52a
diff --git a/quic/core/quic_time.h b/quic/core/quic_time.h
new file mode 100644
index 0000000..6bd3f68
--- /dev/null
+++ b/quic/core/quic_time.h
@@ -0,0 +1,277 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// QuicTime represents one point in time, stored in microsecond resolution.
+// QuicTime is monotonically increasing, even across system clock adjustments.
+// The epoch (time 0) of QuicTime is unspecified.
+//
+// This implementation wraps a int64_t of usec since the epoch. While
+// the epoch is the Unix epoch, do not depend on this fact because other
+// implementations, like Chrome's, do NOT have the same epoch.
+
+#ifndef QUICHE_QUIC_CORE_QUIC_TIME_H_
+#define QUICHE_QUIC_CORE_QUIC_TIME_H_
+
+#include <cmath>
+#include <cstdint>
+#include <limits>
+#include <ostream>
+
+#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_string.h"
+
+// TODO(vasilvv): replace with ABSL_MUST_USE_RESULT once we're using absl.
+#if defined(__clang__)
+#define QUIC_TIME_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
+#else
+#define QUIC_TIME_WARN_UNUSED_RESULT
+#endif /* defined(__clang__) */
+
+namespace quic {
+
+class QuicClock;
+
+// A QuicTime is a purely relative time. QuicTime values from different clocks
+// cannot be compared to each other. If you need an absolute time, see
+// QuicWallTime, below.
+class QUIC_EXPORT_PRIVATE QuicTime {
+ public:
+ // A QuicTime::Delta represents the signed difference between two points in
+ // time, stored in microsecond resolution.
+ class QUIC_EXPORT_PRIVATE Delta {
+ public:
+ // Create a object with an offset of 0.
+ static constexpr Delta Zero() { return Delta(0); }
+
+ // Create a object with infinite offset time.
+ static constexpr Delta Infinite() { return Delta(kQuicInfiniteTimeUs); }
+
+ // Converts a number of seconds to a time offset.
+ static constexpr Delta FromSeconds(int64_t secs) {
+ return Delta(secs * 1000 * 1000);
+ }
+
+ // Converts a number of milliseconds to a time offset.
+ static constexpr Delta FromMilliseconds(int64_t ms) {
+ return Delta(ms * 1000);
+ }
+
+ // Converts a number of microseconds to a time offset.
+ static constexpr Delta FromMicroseconds(int64_t us) { return Delta(us); }
+
+ // Converts the time offset to a rounded number of seconds.
+ inline int64_t ToSeconds() const { return time_offset_ / 1000 / 1000; }
+
+ // Converts the time offset to a rounded number of milliseconds.
+ inline int64_t ToMilliseconds() const { return time_offset_ / 1000; }
+
+ // Converts the time offset to a rounded number of microseconds.
+ inline int64_t ToMicroseconds() const { return time_offset_; }
+
+ inline bool IsZero() const { return time_offset_ == 0; }
+
+ inline bool IsInfinite() const {
+ return time_offset_ == kQuicInfiniteTimeUs;
+ }
+
+ QuicString ToDebugValue() const;
+
+ private:
+ friend inline bool operator==(QuicTime::Delta lhs, QuicTime::Delta rhs);
+ friend inline bool operator<(QuicTime::Delta lhs, QuicTime::Delta rhs);
+ friend inline QuicTime::Delta operator<<(QuicTime::Delta lhs, size_t rhs);
+ friend inline QuicTime::Delta operator>>(QuicTime::Delta lhs, size_t rhs);
+
+ friend inline QuicTime::Delta operator+(QuicTime::Delta lhs,
+ QuicTime::Delta rhs);
+ friend inline QuicTime::Delta operator-(QuicTime::Delta lhs,
+ QuicTime::Delta rhs);
+ friend inline QuicTime::Delta operator*(QuicTime::Delta lhs, int rhs);
+ friend inline QuicTime::Delta operator*(QuicTime::Delta lhs, double rhs);
+
+ friend inline QuicTime operator+(QuicTime lhs, QuicTime::Delta rhs);
+ friend inline QuicTime operator-(QuicTime lhs, QuicTime::Delta rhs);
+ friend inline QuicTime::Delta operator-(QuicTime lhs, QuicTime rhs);
+
+ static const int64_t kQuicInfiniteTimeUs =
+ std::numeric_limits<int64_t>::max();
+
+ explicit constexpr Delta(int64_t time_offset) : time_offset_(time_offset) {}
+
+ int64_t time_offset_;
+ friend class QuicTime;
+ };
+
+ // Creates a new QuicTime with an internal value of 0. IsInitialized()
+ // will return false for these times.
+ static constexpr QuicTime Zero() { return QuicTime(0); }
+
+ // Creates a new QuicTime with an infinite time.
+ static constexpr QuicTime Infinite() {
+ return QuicTime(Delta::kQuicInfiniteTimeUs);
+ }
+
+ QuicTime(const QuicTime& other) = default;
+
+ QuicTime& operator=(const QuicTime& other) {
+ time_ = other.time_;
+ return *this;
+ }
+
+ // Produce the internal value to be used when logging. This value
+ // represents the number of microseconds since some epoch. It may
+ // be the UNIX epoch on some platforms. On others, it may
+ // be a CPU ticks based value.
+ inline int64_t ToDebuggingValue() const { return time_; }
+
+ inline bool IsInitialized() const { return 0 != time_; }
+
+ private:
+ friend class QuicClock;
+
+ friend inline bool operator==(QuicTime lhs, QuicTime rhs);
+ friend inline bool operator<(QuicTime lhs, QuicTime rhs);
+ friend inline QuicTime operator+(QuicTime lhs, QuicTime::Delta rhs);
+ friend inline QuicTime operator-(QuicTime lhs, QuicTime::Delta rhs);
+ friend inline QuicTime::Delta operator-(QuicTime lhs, QuicTime rhs);
+
+ explicit constexpr QuicTime(int64_t time) : time_(time) {}
+
+ int64_t time_;
+};
+
+// A QuicWallTime represents an absolute time that is globally consistent. In
+// practice, clock-skew means that comparing values from different machines
+// requires some flexibility.
+class QUIC_EXPORT_PRIVATE QuicWallTime {
+ public:
+ // FromUNIXSeconds constructs a QuicWallTime from a count of the seconds
+ // since the UNIX epoch.
+ static constexpr QuicWallTime FromUNIXSeconds(uint64_t seconds) {
+ return QuicWallTime(seconds * 1000000);
+ }
+
+ static constexpr QuicWallTime FromUNIXMicroseconds(uint64_t microseconds) {
+ return QuicWallTime(microseconds);
+ }
+
+ // Zero returns a QuicWallTime set to zero. IsZero will return true for this
+ // value.
+ static constexpr QuicWallTime Zero() { return QuicWallTime(0); }
+
+ // Returns the number of seconds since the UNIX epoch.
+ uint64_t ToUNIXSeconds() const;
+ // Returns the number of microseconds since the UNIX epoch.
+ uint64_t ToUNIXMicroseconds() const;
+
+ bool IsAfter(QuicWallTime other) const;
+ bool IsBefore(QuicWallTime other) const;
+
+ // IsZero returns true if this object is the result of calling |Zero|.
+ bool IsZero() const;
+
+ // AbsoluteDifference returns the absolute value of the time difference
+ // between |this| and |other|.
+ QuicTime::Delta AbsoluteDifference(QuicWallTime other) const;
+
+ // Add returns a new QuicWallTime that represents the time of |this| plus
+ // |delta|.
+ QUIC_TIME_WARN_UNUSED_RESULT QuicWallTime Add(QuicTime::Delta delta) const;
+
+ // Subtract returns a new QuicWallTime that represents the time of |this|
+ // minus |delta|.
+ QUIC_TIME_WARN_UNUSED_RESULT QuicWallTime
+ Subtract(QuicTime::Delta delta) const;
+
+ private:
+ explicit constexpr QuicWallTime(uint64_t microseconds)
+ : microseconds_(microseconds) {}
+
+ uint64_t microseconds_;
+};
+
+// Non-member relational operators for QuicTime::Delta.
+inline bool operator==(QuicTime::Delta lhs, QuicTime::Delta rhs) {
+ return lhs.time_offset_ == rhs.time_offset_;
+}
+inline bool operator!=(QuicTime::Delta lhs, QuicTime::Delta rhs) {
+ return !(lhs == rhs);
+}
+inline bool operator<(QuicTime::Delta lhs, QuicTime::Delta rhs) {
+ return lhs.time_offset_ < rhs.time_offset_;
+}
+inline bool operator>(QuicTime::Delta lhs, QuicTime::Delta rhs) {
+ return rhs < lhs;
+}
+inline bool operator<=(QuicTime::Delta lhs, QuicTime::Delta rhs) {
+ return !(rhs < lhs);
+}
+inline bool operator>=(QuicTime::Delta lhs, QuicTime::Delta rhs) {
+ return !(lhs < rhs);
+}
+inline QuicTime::Delta operator>>(QuicTime::Delta lhs, size_t rhs) {
+ return QuicTime::Delta(lhs.time_offset_ >> rhs);
+}
+
+// Non-member relational operators for QuicTime.
+inline bool operator==(QuicTime lhs, QuicTime rhs) {
+ return lhs.time_ == rhs.time_;
+}
+inline bool operator!=(QuicTime lhs, QuicTime rhs) {
+ return !(lhs == rhs);
+}
+inline bool operator<(QuicTime lhs, QuicTime rhs) {
+ return lhs.time_ < rhs.time_;
+}
+inline bool operator>(QuicTime lhs, QuicTime rhs) {
+ return rhs < lhs;
+}
+inline bool operator<=(QuicTime lhs, QuicTime rhs) {
+ return !(rhs < lhs);
+}
+inline bool operator>=(QuicTime lhs, QuicTime rhs) {
+ return !(lhs < rhs);
+}
+
+// Non-member arithmetic operators for QuicTime::Delta.
+inline QuicTime::Delta operator+(QuicTime::Delta lhs, QuicTime::Delta rhs) {
+ return QuicTime::Delta(lhs.time_offset_ + rhs.time_offset_);
+}
+inline QuicTime::Delta operator-(QuicTime::Delta lhs, QuicTime::Delta rhs) {
+ return QuicTime::Delta(lhs.time_offset_ - rhs.time_offset_);
+}
+inline QuicTime::Delta operator*(QuicTime::Delta lhs, int rhs) {
+ return QuicTime::Delta(lhs.time_offset_ * rhs);
+}
+inline QuicTime::Delta operator*(QuicTime::Delta lhs, double rhs) {
+ return QuicTime::Delta(
+ static_cast<int64_t>(std::llround(lhs.time_offset_ * rhs)));
+}
+inline QuicTime::Delta operator*(int lhs, QuicTime::Delta rhs) {
+ return rhs * lhs;
+}
+inline QuicTime::Delta operator*(double lhs, QuicTime::Delta rhs) {
+ return rhs * lhs;
+}
+
+// Non-member arithmetic operators for QuicTime and QuicTime::Delta.
+inline QuicTime operator+(QuicTime lhs, QuicTime::Delta rhs) {
+ return QuicTime(lhs.time_ + rhs.time_offset_);
+}
+inline QuicTime operator-(QuicTime lhs, QuicTime::Delta rhs) {
+ return QuicTime(lhs.time_ - rhs.time_offset_);
+}
+inline QuicTime::Delta operator-(QuicTime lhs, QuicTime rhs) {
+ return QuicTime::Delta(lhs.time_ - rhs.time_);
+}
+
+// Override stream output operator for gtest.
+inline std::ostream& operator<<(std::ostream& output,
+ const QuicTime::Delta delta) {
+ output << delta.ToDebugValue();
+ return output;
+}
+} // namespace quic
+
+#endif // QUICHE_QUIC_CORE_QUIC_TIME_H_