time.h raw

   1  // Copyright (c) 2009-2010 Satoshi Nakamoto
   2  // Copyright (c) 2009-present The Limenka developers
   3  // Distributed under the MIT software license, see the accompanying
   4  // file COPYING or http://www.opensource.org/licenses/mit-license.php.
   5  
   6  #ifndef LIMENKA_UTIL_TIME_H
   7  #define LIMENKA_UTIL_TIME_H
   8  
   9  #include <atomic>
  10  #include <chrono> // IWYU pragma: export
  11  #include <cstdint>
  12  #include <functional>
  13  #include <optional>
  14  #include <string>
  15  #include <string_view>
  16  
  17  using namespace std::chrono_literals;
  18  
  19  /** Mockable clock in the context of tests, otherwise the system clock */
  20  struct NodeClock : public std::chrono::system_clock {
  21      using time_point = std::chrono::time_point<NodeClock>;
  22      /** Return current system time or mocked time, if set */
  23      static time_point now() noexcept;
  24      static std::time_t to_time_t(const time_point&) = delete; // unused
  25      static time_point from_time_t(std::time_t) = delete;      // unused
  26  };
  27  using NodeSeconds = std::chrono::time_point<NodeClock, std::chrono::seconds>;
  28  
  29  using SteadyClock = std::chrono::steady_clock;
  30  using SteadySeconds = std::chrono::time_point<std::chrono::steady_clock, std::chrono::seconds>;
  31  using SteadyMilliseconds = std::chrono::time_point<std::chrono::steady_clock, std::chrono::milliseconds>;
  32  using SteadyMicroseconds = std::chrono::time_point<std::chrono::steady_clock, std::chrono::microseconds>;
  33  
  34  using SystemClock = std::chrono::system_clock;
  35  
  36  /**
  37   * Version of SteadyClock that is mockable in the context of tests (set the
  38   * current value with SetMockTime), otherwise the system steady clock.
  39   */
  40  struct MockableSteadyClock : public std::chrono::steady_clock {
  41      using time_point = std::chrono::time_point<MockableSteadyClock>;
  42  
  43      static constexpr std::chrono::milliseconds INITIAL_MOCK_TIME{1};
  44  
  45      /** Return current system time or mocked time, if set */
  46      static time_point now() noexcept;
  47      static std::time_t to_time_t(const time_point&) = delete; // unused
  48      static time_point from_time_t(std::time_t) = delete;      // unused
  49  
  50      /** Set mock time for testing.
  51       * When mocking the steady clock, start at INITIAL_MOCK_TIME and add durations to elapse time as necessary
  52       * for testing.
  53       * To stop mocking, call ClearMockTime().
  54       */
  55      static void SetMockTime(std::chrono::milliseconds mock_time_in);
  56  
  57      /** Clear mock time, go back to system steady clock. */
  58      static void ClearMockTime();
  59  };
  60  
  61  void UninterruptibleSleep(const std::chrono::microseconds& n);
  62  
  63  /**
  64   * Helper to count the seconds of a duration/time_point.
  65   *
  66   * All durations/time_points should be using std::chrono and calling this should generally
  67   * be avoided in code. Though, it is still preferred to an inline t.count() to
  68   * protect against a reliance on the exact type of t.
  69   *
  70   * This helper is used to convert durations/time_points before passing them over an
  71   * interface that doesn't support std::chrono (e.g. RPC, debug log, or the GUI)
  72   */
  73  template <typename Dur1, typename Dur2>
  74  constexpr auto Ticks(Dur2 d)
  75  {
  76      return std::chrono::duration_cast<Dur1>(d).count();
  77  }
  78  
  79  template <typename Duration>
  80  constexpr int64_t TicksSeconds(Duration d)
  81  {
  82      return int64_t{Ticks<std::chrono::seconds>(d)};
  83  }
  84  template <typename Duration, typename Timepoint>
  85  constexpr auto TicksSinceEpoch(Timepoint t)
  86  {
  87      return Ticks<Duration>(t.time_since_epoch());
  88  }
  89  constexpr int64_t count_seconds(std::chrono::seconds t) { return t.count(); }
  90  constexpr int64_t count_milliseconds(std::chrono::milliseconds t) { return t.count(); }
  91  constexpr int64_t count_microseconds(std::chrono::microseconds t) { return t.count(); }
  92  
  93  using HoursDouble = std::chrono::duration<double, std::chrono::hours::period>;
  94  using SecondsDouble = std::chrono::duration<double, std::chrono::seconds::period>;
  95  using MillisecondsDouble = std::chrono::duration<double, std::chrono::milliseconds::period>;
  96  
  97  /**
  98   * DEPRECATED
  99   * Use either ClockType::now() or Now<TimePointType>() if a cast is needed.
 100   * ClockType is
 101   * - SteadyClock/std::chrono::steady_clock for steady time
 102   * - SystemClock/std::chrono::system_clock for system time
 103   * - NodeClock                             for mockable system time
 104   */
 105  int64_t GetTime();
 106  
 107  /**
 108   * DEPRECATED
 109   * Use SetMockTime with chrono type
 110   *
 111   * @param[in] nMockTimeIn Time in seconds.
 112   */
 113  void SetMockTime(int64_t nMockTimeIn);
 114  
 115  /** For testing. Set e.g. with the setmocktime rpc, or -mocktime argument */
 116  void SetMockTime(std::chrono::seconds mock_time_in);
 117  
 118  /** For testing */
 119  std::chrono::seconds GetMockTime();
 120  
 121  /**
 122   * Return the current time point cast to the given precision. Only use this
 123   * when an exact precision is needed, otherwise use T::clock::now() directly.
 124   */
 125  template <typename T>
 126  T Now()
 127  {
 128      return std::chrono::time_point_cast<typename T::duration>(T::clock::now());
 129  }
 130  /** DEPRECATED, see GetTime */
 131  template <typename T>
 132  T GetTime()
 133  {
 134      return Now<std::chrono::time_point<NodeClock, T>>().time_since_epoch();
 135  }
 136  
 137  /**
 138   * ISO 8601 formatting is preferred. Use the FormatISO8601{DateTime,Date}
 139   * helper functions if possible.
 140   */
 141  std::string FormatISO8601DateTime(int64_t nTime);
 142  std::string FormatISO8601Date(int64_t nTime);
 143  std::string FormatISO8601Time(int64_t nTime);
 144  std::optional<int64_t> ParseISO8601DateTime(std::string_view str);
 145  
 146  /**
 147   * Convert milliseconds to a struct timeval for e.g. select.
 148   */
 149  struct timeval MillisToTimeval(int64_t nTimeout);
 150  
 151  /**
 152   * Convert milliseconds to a struct timeval for e.g. select.
 153   */
 154  struct timeval MillisToTimeval(std::chrono::milliseconds ms);
 155  
 156  /**
 157   * Retrieve the CPU time (user + system) spent by the current thread.
 158   */
 159  std::chrono::nanoseconds ThreadCpuTime();
 160  
 161  /**
 162   * Measure CPU time spent by the current thread.
 163   * A clock is started when a CpuTimer is created. When the object is destroyed
 164   * the elapsed CPU time is calculated and a callback function is invoked,
 165   * providing it the elapsed CPU time.
 166   */
 167  class CpuTimer
 168  {
 169  public:
 170      using FinishedCB = std::function<void(std::chrono::nanoseconds)>;
 171  
 172      /**
 173       * Construct a timer.
 174       * @param[in] finished_cb A callback to invoke when this object is destroyed.
 175       */
 176      CpuTimer(const FinishedCB& finished_cb)
 177          : m_start{ThreadCpuTime()},
 178            m_finished_cb{finished_cb}
 179      {
 180      }
 181  
 182      ~CpuTimer()
 183      {
 184          m_finished_cb(ThreadCpuTime() - m_start);
 185      }
 186  
 187  private:
 188      const std::chrono::nanoseconds m_start;
 189      FinishedCB m_finished_cb;
 190  };
 191  
 192  /**
 193   * Add `b` nanoseconds to a nanoseconds atomic.
 194   * @return The value of `a` immediately after the operation.
 195   */
 196  std::chrono::nanoseconds operator+=(std::atomic<std::chrono::nanoseconds>& a, std::chrono::nanoseconds b);
 197  
 198  #endif // LIMENKA_UTIL_TIME_H
 199