| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206 | // Copyright The OpenTelemetry Authors// SPDX-License-Identifier: Apache-2.0#pragma once#include <chrono>#include <cstdint>#include "opentelemetry/version.h"OPENTELEMETRY_BEGIN_NAMESPACEnamespace common{/** * @brief A timepoint relative to the system clock epoch. * * This is used for marking the beginning and end of an operation. */class SystemTimestamp{public:  /**   * @brief Initializes a system timestamp pointing to the start of the epoch.   */  SystemTimestamp() noexcept : nanos_since_epoch_{0} {}  /**   * @brief Initializes a system timestamp from a duration.   *   * @param time_since_epoch Time elapsed since the beginning of the epoch.   */  template <class Rep, class Period>  explicit SystemTimestamp(const std::chrono::duration<Rep, Period> &time_since_epoch) noexcept      : nanos_since_epoch_{static_cast<int64_t>(            std::chrono::duration_cast<std::chrono::nanoseconds>(time_since_epoch).count())}  {}  /**   * @brief Initializes a system timestamp based on a point in time.   *   * @param time_point A point in time.   */  /*implicit*/ SystemTimestamp(const std::chrono::system_clock::time_point &time_point) noexcept      : SystemTimestamp{time_point.time_since_epoch()}  {}  /**   * @brief Returns a time point for the time stamp.   *   * @return A time point corresponding to the time stamp.   */  operator std::chrono::system_clock::time_point() const noexcept  {    return std::chrono::system_clock::time_point{        std::chrono::duration_cast<std::chrono::system_clock::duration>(            std::chrono::nanoseconds{nanos_since_epoch_})};  }  /**   * @brief Returns the nanoseconds since the beginning of the epoch.   *   * @return Elapsed nanoseconds since the beginning of the epoch for this timestamp.   */  std::chrono::nanoseconds time_since_epoch() const noexcept  {    return std::chrono::nanoseconds{nanos_since_epoch_};  }  /**   * @brief Compare two steady time stamps.   *   * @return true if the two time stamps are equal.   */  bool operator==(const SystemTimestamp &other) const noexcept  {    return nanos_since_epoch_ == other.nanos_since_epoch_;  }  /**   * @brief Compare two steady time stamps for inequality.   *   * @return true if the two time stamps are not equal.   */  bool operator!=(const SystemTimestamp &other) const noexcept  {    return nanos_since_epoch_ != other.nanos_since_epoch_;  }private:  int64_t nanos_since_epoch_;};/** * @brief A timepoint relative to the monotonic clock epoch * * This is used for calculating the duration of an operation. */class SteadyTimestamp{public:  /**   * @brief Initializes a monotonic timestamp pointing to the start of the epoch.   */  SteadyTimestamp() noexcept : nanos_since_epoch_{0} {}  /**   * @brief Initializes a monotonic timestamp from a duration.   *   * @param time_since_epoch Time elapsed since the beginning of the epoch.   */  template <class Rep, class Period>  explicit SteadyTimestamp(const std::chrono::duration<Rep, Period> &time_since_epoch) noexcept      : nanos_since_epoch_{static_cast<int64_t>(            std::chrono::duration_cast<std::chrono::nanoseconds>(time_since_epoch).count())}  {}  /**   * @brief Initializes a monotonic timestamp based on a point in time.   *   * @param time_point A point in time.   */  /*implicit*/ SteadyTimestamp(const std::chrono::steady_clock::time_point &time_point) noexcept      : SteadyTimestamp{time_point.time_since_epoch()}  {}  /**   * @brief Returns a time point for the time stamp.   *   * @return A time point corresponding to the time stamp.   */  operator std::chrono::steady_clock::time_point() const noexcept  {    return std::chrono::steady_clock::time_point{        std::chrono::duration_cast<std::chrono::steady_clock::duration>(            std::chrono::nanoseconds{nanos_since_epoch_})};  }  /**   * @brief Returns the nanoseconds since the beginning of the epoch.   *   * @return Elapsed nanoseconds since the beginning of the epoch for this timestamp.   */  std::chrono::nanoseconds time_since_epoch() const noexcept  {    return std::chrono::nanoseconds{nanos_since_epoch_};  }  /**   * @brief Compare two steady time stamps.   *   * @return true if the two time stamps are equal.   */  bool operator==(const SteadyTimestamp &other) const noexcept  {    return nanos_since_epoch_ == other.nanos_since_epoch_;  }  /**   * @brief Compare two steady time stamps for inequality.   *   * @return true if the two time stamps are not equal.   */  bool operator!=(const SteadyTimestamp &other) const noexcept  {    return nanos_since_epoch_ != other.nanos_since_epoch_;  }private:  int64_t nanos_since_epoch_;};class DurationUtil{public:  template <class Rep, class Period>  static std::chrono::duration<Rep, Period> AdjustWaitForTimeout(      std::chrono::duration<Rep, Period> timeout,      std::chrono::duration<Rep, Period> indefinite_value) noexcept  {    // Do not call now() when this duration is max value, now() may have a expensive cost.    if (timeout == (std::chrono::duration<Rep, Period>::max)())    {      return indefinite_value;    }    // std::future<T>::wait_for, std::this_thread::sleep_for, and std::condition_variable::wait_for    // may use steady_clock or system_clock.We need make sure now() + timeout do not overflow.    auto max_timeout = std::chrono::duration_cast<std::chrono::duration<Rep, Period>>(        (std::chrono::steady_clock::time_point::max)() - std::chrono::steady_clock::now());    if (timeout >= max_timeout)    {      return indefinite_value;    }    max_timeout = std::chrono::duration_cast<std::chrono::duration<Rep, Period>>(        (std::chrono::system_clock::time_point::max)() - std::chrono::system_clock::now());    if (timeout >= max_timeout)    {      return indefinite_value;    }    return timeout;  }};}  // namespace commonOPENTELEMETRY_END_NAMESPACE
 |