timestamp.h 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. // Copyright The OpenTelemetry Authors
  2. // SPDX-License-Identifier: Apache-2.0
  3. #pragma once
  4. #include <chrono>
  5. #include <cstdint>
  6. #include "opentelemetry/version.h"
  7. OPENTELEMETRY_BEGIN_NAMESPACE
  8. namespace common
  9. {
  10. /**
  11. * @brief A timepoint relative to the system clock epoch.
  12. *
  13. * This is used for marking the beginning and end of an operation.
  14. */
  15. class SystemTimestamp
  16. {
  17. public:
  18. /**
  19. * @brief Initializes a system timestamp pointing to the start of the epoch.
  20. */
  21. SystemTimestamp() noexcept : nanos_since_epoch_{0} {}
  22. /**
  23. * @brief Initializes a system timestamp from a duration.
  24. *
  25. * @param time_since_epoch Time elapsed since the beginning of the epoch.
  26. */
  27. template <class Rep, class Period>
  28. explicit SystemTimestamp(const std::chrono::duration<Rep, Period> &time_since_epoch) noexcept
  29. : nanos_since_epoch_{static_cast<int64_t>(
  30. std::chrono::duration_cast<std::chrono::nanoseconds>(time_since_epoch).count())}
  31. {}
  32. /**
  33. * @brief Initializes a system timestamp based on a point in time.
  34. *
  35. * @param time_point A point in time.
  36. */
  37. /*implicit*/ SystemTimestamp(const std::chrono::system_clock::time_point &time_point) noexcept
  38. : SystemTimestamp{time_point.time_since_epoch()}
  39. {}
  40. /**
  41. * @brief Returns a time point for the time stamp.
  42. *
  43. * @return A time point corresponding to the time stamp.
  44. */
  45. operator std::chrono::system_clock::time_point() const noexcept
  46. {
  47. return std::chrono::system_clock::time_point{
  48. std::chrono::duration_cast<std::chrono::system_clock::duration>(
  49. std::chrono::nanoseconds{nanos_since_epoch_})};
  50. }
  51. /**
  52. * @brief Returns the nanoseconds since the beginning of the epoch.
  53. *
  54. * @return Elapsed nanoseconds since the beginning of the epoch for this timestamp.
  55. */
  56. std::chrono::nanoseconds time_since_epoch() const noexcept
  57. {
  58. return std::chrono::nanoseconds{nanos_since_epoch_};
  59. }
  60. /**
  61. * @brief Compare two steady time stamps.
  62. *
  63. * @return true if the two time stamps are equal.
  64. */
  65. bool operator==(const SystemTimestamp &other) const noexcept
  66. {
  67. return nanos_since_epoch_ == other.nanos_since_epoch_;
  68. }
  69. /**
  70. * @brief Compare two steady time stamps for inequality.
  71. *
  72. * @return true if the two time stamps are not equal.
  73. */
  74. bool operator!=(const SystemTimestamp &other) const noexcept
  75. {
  76. return nanos_since_epoch_ != other.nanos_since_epoch_;
  77. }
  78. private:
  79. int64_t nanos_since_epoch_;
  80. };
  81. /**
  82. * @brief A timepoint relative to the monotonic clock epoch
  83. *
  84. * This is used for calculating the duration of an operation.
  85. */
  86. class SteadyTimestamp
  87. {
  88. public:
  89. /**
  90. * @brief Initializes a monotonic timestamp pointing to the start of the epoch.
  91. */
  92. SteadyTimestamp() noexcept : nanos_since_epoch_{0} {}
  93. /**
  94. * @brief Initializes a monotonic timestamp from a duration.
  95. *
  96. * @param time_since_epoch Time elapsed since the beginning of the epoch.
  97. */
  98. template <class Rep, class Period>
  99. explicit SteadyTimestamp(const std::chrono::duration<Rep, Period> &time_since_epoch) noexcept
  100. : nanos_since_epoch_{static_cast<int64_t>(
  101. std::chrono::duration_cast<std::chrono::nanoseconds>(time_since_epoch).count())}
  102. {}
  103. /**
  104. * @brief Initializes a monotonic timestamp based on a point in time.
  105. *
  106. * @param time_point A point in time.
  107. */
  108. /*implicit*/ SteadyTimestamp(const std::chrono::steady_clock::time_point &time_point) noexcept
  109. : SteadyTimestamp{time_point.time_since_epoch()}
  110. {}
  111. /**
  112. * @brief Returns a time point for the time stamp.
  113. *
  114. * @return A time point corresponding to the time stamp.
  115. */
  116. operator std::chrono::steady_clock::time_point() const noexcept
  117. {
  118. return std::chrono::steady_clock::time_point{
  119. std::chrono::duration_cast<std::chrono::steady_clock::duration>(
  120. std::chrono::nanoseconds{nanos_since_epoch_})};
  121. }
  122. /**
  123. * @brief Returns the nanoseconds since the beginning of the epoch.
  124. *
  125. * @return Elapsed nanoseconds since the beginning of the epoch for this timestamp.
  126. */
  127. std::chrono::nanoseconds time_since_epoch() const noexcept
  128. {
  129. return std::chrono::nanoseconds{nanos_since_epoch_};
  130. }
  131. /**
  132. * @brief Compare two steady time stamps.
  133. *
  134. * @return true if the two time stamps are equal.
  135. */
  136. bool operator==(const SteadyTimestamp &other) const noexcept
  137. {
  138. return nanos_since_epoch_ == other.nanos_since_epoch_;
  139. }
  140. /**
  141. * @brief Compare two steady time stamps for inequality.
  142. *
  143. * @return true if the two time stamps are not equal.
  144. */
  145. bool operator!=(const SteadyTimestamp &other) const noexcept
  146. {
  147. return nanos_since_epoch_ != other.nanos_since_epoch_;
  148. }
  149. private:
  150. int64_t nanos_since_epoch_;
  151. };
  152. class DurationUtil
  153. {
  154. public:
  155. template <class Rep, class Period>
  156. static std::chrono::duration<Rep, Period> AdjustWaitForTimeout(
  157. std::chrono::duration<Rep, Period> timeout,
  158. std::chrono::duration<Rep, Period> indefinite_value) noexcept
  159. {
  160. // Do not call now() when this duration is max value, now() may have a expensive cost.
  161. if (timeout == (std::chrono::duration<Rep, Period>::max)())
  162. {
  163. return indefinite_value;
  164. }
  165. // std::future<T>::wait_for, std::this_thread::sleep_for, and std::condition_variable::wait_for
  166. // may use steady_clock or system_clock.We need make sure now() + timeout do not overflow.
  167. auto max_timeout = std::chrono::duration_cast<std::chrono::duration<Rep, Period>>(
  168. (std::chrono::steady_clock::time_point::max)() - std::chrono::steady_clock::now());
  169. if (timeout >= max_timeout)
  170. {
  171. return indefinite_value;
  172. }
  173. max_timeout = std::chrono::duration_cast<std::chrono::duration<Rep, Period>>(
  174. (std::chrono::system_clock::time_point::max)() - std::chrono::system_clock::now());
  175. if (timeout >= max_timeout)
  176. {
  177. return indefinite_value;
  178. }
  179. return timeout;
  180. }
  181. };
  182. } // namespace common
  183. OPENTELEMETRY_END_NAMESPACE