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