Program Listing for File timestamp.h

Return to documentation for file (/home/docs/checkouts/readthedocs.org/user_builds/opentelemetry-cpp/checkouts/latest/api/include/opentelemetry/common/timestamp.h)

// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

#pragma once

#include <chrono>
#include <cstdint>

#include "opentelemetry/version.h"

OPENTELEMETRY_BEGIN_NAMESPACE
namespace common
{
class SystemTimestamp
{
public:
  SystemTimestamp() noexcept : nanos_since_epoch_{0} {}

  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())}
  {}

  /*implicit*/ SystemTimestamp(const std::chrono::system_clock::time_point &time_point) noexcept
      : SystemTimestamp{time_point.time_since_epoch()}
  {}

  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_})};
  }

  std::chrono::nanoseconds time_since_epoch() const noexcept
  {
    return std::chrono::nanoseconds{nanos_since_epoch_};
  }

  bool operator==(const SystemTimestamp &other) const noexcept
  {
    return nanos_since_epoch_ == other.nanos_since_epoch_;
  }

  bool operator!=(const SystemTimestamp &other) const noexcept
  {
    return nanos_since_epoch_ != other.nanos_since_epoch_;
  }

private:
  int64_t nanos_since_epoch_;
};

class SteadyTimestamp
{
public:
  SteadyTimestamp() noexcept : nanos_since_epoch_{0} {}

  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())}
  {}

  /*implicit*/ SteadyTimestamp(const std::chrono::steady_clock::time_point &time_point) noexcept
      : SteadyTimestamp{time_point.time_since_epoch()}
  {}

  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_})};
  }

  std::chrono::nanoseconds time_since_epoch() const noexcept
  {
    return std::chrono::nanoseconds{nanos_since_epoch_};
  }

  bool operator==(const SteadyTimestamp &other) const noexcept
  {
    return nanos_since_epoch_ == other.nanos_since_epoch_;
  }

  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 common
OPENTELEMETRY_END_NAMESPACE