/Users/deen/code/yugabyte-db/src/yb/util/monotime.h
Line | Count | Source (jump to first uncovered line) |
1 | | // Licensed to the Apache Software Foundation (ASF) under one |
2 | | // or more contributor license agreements. See the NOTICE file |
3 | | // distributed with this work for additional information |
4 | | // regarding copyright ownership. The ASF licenses this file |
5 | | // to you under the Apache License, Version 2.0 (the |
6 | | // "License"); you may not use this file except in compliance |
7 | | // with the License. You may obtain a copy of the License at |
8 | | // |
9 | | // http://www.apache.org/licenses/LICENSE-2.0 |
10 | | // |
11 | | // Unless required by applicable law or agreed to in writing, |
12 | | // software distributed under the License is distributed on an |
13 | | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
14 | | // KIND, either express or implied. See the License for the |
15 | | // specific language governing permissions and limitations |
16 | | // under the License. |
17 | | // |
18 | | // The following only applies to changes made to this file as part of YugaByte development. |
19 | | // |
20 | | // Portions Copyright (c) YugaByte, Inc. |
21 | | // |
22 | | // Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except |
23 | | // in compliance with the License. You may obtain a copy of the License at |
24 | | // |
25 | | // http://www.apache.org/licenses/LICENSE-2.0 |
26 | | // |
27 | | // Unless required by applicable law or agreed to in writing, software distributed under the License |
28 | | // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express |
29 | | // or implied. See the License for the specific language governing permissions and limitations |
30 | | // under the License. |
31 | | // |
32 | | #ifndef YB_UTIL_MONOTIME_H |
33 | | #define YB_UTIL_MONOTIME_H |
34 | | |
35 | | #include <chrono> |
36 | | #include <cstdint> |
37 | | #include <string> |
38 | | |
39 | | #include <gtest/gtest_prod.h> |
40 | | |
41 | | struct timeval; |
42 | | struct timespec; |
43 | | |
44 | | namespace yb { |
45 | | class MonoTime; |
46 | | |
47 | | // Represent an elapsed duration of time -- i.e the delta between |
48 | | // two MonoTime instances. |
49 | | // |
50 | | // A MonoDelta built with the default constructor is "uninitialized" and |
51 | | // may not be used for any operation. |
52 | | class MonoDelta { |
53 | | public: |
54 | | static MonoDelta FromMinutes(double minutes); |
55 | | static MonoDelta FromSeconds(double seconds); |
56 | | static MonoDelta FromMilliseconds(int64_t ms); |
57 | | static MonoDelta FromMicroseconds(int64_t us); |
58 | | static MonoDelta FromNanoseconds(int64_t ns); |
59 | | |
60 | | static const MonoDelta kMin; |
61 | | static const MonoDelta kMax; |
62 | | static const MonoDelta kZero; |
63 | | |
64 | | MonoDelta() noexcept; |
65 | | |
66 | | template<class Rep, class Period> |
67 | | MonoDelta(const std::chrono::duration<Rep, Period>& duration) // NOLINT |
68 | 693M | : nano_delta_(std::chrono::nanoseconds(duration).count()) {} _ZN2yb9MonoDeltaC2IxNSt3__15ratioILl1ELl1EEEEERKNS2_6chrono8durationIT_T0_EE Line | Count | Source | 68 | 153M | : nano_delta_(std::chrono::nanoseconds(duration).count()) {} |
_ZN2yb9MonoDeltaC2IxNSt3__15ratioILl1ELl1000EEEEERKNS2_6chrono8durationIT_T0_EE Line | Count | Source | 68 | 31.8M | : nano_delta_(std::chrono::nanoseconds(duration).count()) {} |
_ZN2yb9MonoDeltaC2IxNSt3__15ratioILl1ELl1000000000EEEEERKNS2_6chrono8durationIT_T0_EE Line | Count | Source | 68 | 506M | : nano_delta_(std::chrono::nanoseconds(duration).count()) {} |
Unexecuted instantiation: _ZN2yb9MonoDeltaC2IlNSt3__15ratioILl60ELl1EEEEERKNS2_6chrono8durationIT_T0_EE _ZN2yb9MonoDeltaC2IlNSt3__15ratioILl3600ELl1EEEEERKNS2_6chrono8durationIT_T0_EE Line | Count | Source | 68 | 2 | : nano_delta_(std::chrono::nanoseconds(duration).count()) {} |
Unexecuted instantiation: _ZN2yb9MonoDeltaC2IyNSt3__15ratioILl1ELl1000000EEEEERKNS2_6chrono8durationIT_T0_EE _ZN2yb9MonoDeltaC2IyNSt3__15ratioILl1ELl1000EEEEERKNS2_6chrono8durationIT_T0_EE Line | Count | Source | 68 | 1.92M | : nano_delta_(std::chrono::nanoseconds(duration).count()) {} |
_ZN2yb9MonoDeltaC2IxNSt3__15ratioILl1ELl1000000EEEEERKNS2_6chrono8durationIT_T0_EE Line | Count | Source | 68 | 381k | : nano_delta_(std::chrono::nanoseconds(duration).count()) {} |
|
69 | | |
70 | | bool Initialized() const; |
71 | | bool LessThan(const MonoDelta &rhs) const; |
72 | | bool MoreThan(const MonoDelta &rhs) const; |
73 | | bool Equals(const MonoDelta &rhs) const; |
74 | | bool IsNegative() const; |
75 | | std::string ToString() const; |
76 | | double ToSeconds() const; |
77 | | double ToMinutes() const; |
78 | | int64_t ToMilliseconds() const; |
79 | | int64_t ToMicroseconds() const; |
80 | | int64_t ToNanoseconds() const; |
81 | | std::chrono::steady_clock::duration ToSteadyDuration() const; |
82 | | |
83 | 0 | std::chrono::microseconds ToChronoMicroseconds() const { |
84 | 0 | return std::chrono::microseconds(ToMicroseconds()); |
85 | 0 | } |
86 | | |
87 | 0 | std::chrono::milliseconds ToChronoMilliseconds() const { |
88 | 0 | return std::chrono::milliseconds(ToMilliseconds()); |
89 | 0 | } |
90 | | |
91 | | MonoDelta& operator+=(const MonoDelta& rhs); |
92 | | MonoDelta& operator-=(const MonoDelta& rhs); |
93 | | MonoDelta& operator*=(int64_t mul); |
94 | | MonoDelta& operator/=(int64_t mul); |
95 | | |
96 | | // Update struct timeval to current value of delta, with microsecond accuracy. |
97 | | // Note that if MonoDelta::IsPositive() returns true, the struct timeval |
98 | | // is guaranteed to hold a positive number as well (at least 1 microsecond). |
99 | | void ToTimeVal(struct timeval *tv) const; |
100 | | |
101 | | // Update struct timespec to current value of delta, with nanosecond accuracy. |
102 | | void ToTimeSpec(struct timespec *ts) const; |
103 | | |
104 | | // Convert a nanosecond value to a timespec. |
105 | | static void NanosToTimeSpec(int64_t nanos, struct timespec* ts); |
106 | | |
107 | 55.1M | explicit operator bool() const { return Initialized(); } |
108 | 20.9M | bool operator !() const { return !Initialized(); } |
109 | | |
110 | 976k | MonoDelta operator-() const { return MonoDelta(-nano_delta_); } |
111 | | |
112 | | private: |
113 | | typedef int64_t NanoDeltaType; |
114 | | static const NanoDeltaType kUninitialized; |
115 | | |
116 | | FRIEND_TEST(TestMonoTime, TestDeltaConversions); |
117 | | explicit MonoDelta(NanoDeltaType delta); |
118 | | NanoDeltaType nano_delta_; |
119 | | }; |
120 | | |
121 | 27.3M | inline bool operator<(MonoDelta lhs, MonoDelta rhs) { return lhs.LessThan(rhs); } |
122 | 25.8M | inline bool operator>(MonoDelta lhs, MonoDelta rhs) { return rhs < lhs; } |
123 | 43.1k | inline bool operator>=(MonoDelta lhs, MonoDelta rhs) { return !(lhs < rhs); } |
124 | 6.20k | inline bool operator<=(MonoDelta lhs, MonoDelta rhs) { return !(rhs < lhs); } |
125 | | |
126 | 147M | inline bool operator==(MonoDelta lhs, MonoDelta rhs) { return lhs.Equals(rhs); } |
127 | 38.4M | inline bool operator!=(MonoDelta lhs, MonoDelta rhs) { return !(rhs == lhs); } |
128 | | |
129 | | std::string FormatForComparisonFailureMessage(const MonoDelta& op, const MonoDelta& other); |
130 | | |
131 | 39.8k | inline MonoDelta operator-(MonoDelta lhs, MonoDelta rhs) { return lhs -= rhs; } |
132 | 957k | inline MonoDelta operator+(MonoDelta lhs, MonoDelta rhs) { return lhs += rhs; } |
133 | 119M | inline MonoDelta operator*(MonoDelta lhs, int64_t rhs) { return lhs *= rhs; } |
134 | 21 | inline MonoDelta operator/(MonoDelta lhs, int64_t rhs) { return lhs /= rhs; } |
135 | | |
136 | 196k | inline std::ostream& operator<<(std::ostream& out, MonoDelta delta) { |
137 | 196k | return out << delta.ToString(); |
138 | 196k | } |
139 | | |
140 | | // Represent a particular point in time, relative to some fixed but unspecified |
141 | | // reference point. |
142 | | // |
143 | | // This time is monotonic, meaning that if the user changes his or her system |
144 | | // clock, the monotime does not change. |
145 | | class MonoTime { |
146 | | public: |
147 | | static constexpr int64_t kNanosecondsPerMicrosecond = 1000L; |
148 | | static constexpr int64_t kMicrosecondsPerMillisecond = 1000L; |
149 | | static constexpr int64_t kMillisecondsPerSecond = 1000L; |
150 | | static constexpr int64_t kSecondsPerMinute = 60L; |
151 | | |
152 | | static constexpr int64_t kNanosecondsPerMillisecond = |
153 | | kNanosecondsPerMicrosecond * kMicrosecondsPerMillisecond; |
154 | | |
155 | | static constexpr int64_t kMicrosecondsPerSecond = |
156 | | kMillisecondsPerSecond * kMicrosecondsPerMillisecond; |
157 | | |
158 | | static constexpr int64_t kNanosecondsPerSecond = |
159 | | kNanosecondsPerMillisecond * kMillisecondsPerSecond; |
160 | | |
161 | | static constexpr int64_t kNanosecondsPerMinute = |
162 | | kNanosecondsPerSecond * kSecondsPerMinute; |
163 | | |
164 | | static const MonoTime kMin; |
165 | | static const MonoTime kMax; |
166 | | static const MonoTime kUninitialized; |
167 | | |
168 | | // The coarse monotonic time is faster to retrieve, but "only" accurate to within a millisecond or |
169 | | // two. The speed difference will depend on your timer hardware. |
170 | | static MonoTime Now(); |
171 | | |
172 | | // Return MonoTime equal to farthest possible time into the future. |
173 | | static MonoTime Max(); |
174 | | |
175 | | // Return MonoTime equal to farthest possible time into the past. |
176 | | static MonoTime Min(); |
177 | | |
178 | | // Return the earliest (minimum) of the two monotimes. |
179 | | static const MonoTime& Earliest(const MonoTime& a, const MonoTime& b); |
180 | | |
181 | 296M | MonoTime() noexcept {} |
182 | 565M | MonoTime(std::chrono::steady_clock::time_point value) : value_(value) {} // NOLINT |
183 | | |
184 | 869M | bool Initialized() const { return value_ != std::chrono::steady_clock::time_point(); } |
185 | | |
186 | | MonoDelta GetDeltaSince(const MonoTime &rhs) const; |
187 | 0 | MonoDelta GetDeltaSinceMin() const { return GetDeltaSince(Min()); } |
188 | | void AddDelta(const MonoDelta &delta); |
189 | | void SubtractDelta(const MonoDelta &delta); |
190 | | bool ComesBefore(const MonoTime &rhs) const; |
191 | | std::string ToString() const; |
192 | | bool Equals(const MonoTime& other) const; |
193 | | bool IsMax() const; |
194 | | bool IsMin() const; |
195 | | |
196 | 49.9k | uint64_t ToUint64() const { return value_.time_since_epoch().count(); } |
197 | 50.3k | static MonoTime FromUint64(uint64_t value) { |
198 | 50.3k | return MonoTime(std::chrono::steady_clock::time_point(std::chrono::steady_clock::duration( |
199 | 50.3k | value))); |
200 | 50.3k | } |
201 | | |
202 | 355 | explicit operator bool() const { return Initialized(); } |
203 | 0 | bool operator !() const { return !Initialized(); } |
204 | | |
205 | | // Set this time to the given value if it is lower than that or uninitialized. |
206 | | void MakeAtLeast(MonoTime rhs); |
207 | | |
208 | 53.8M | std::chrono::steady_clock::time_point ToSteadyTimePoint() const { |
209 | 53.8M | return value_; |
210 | 53.8M | } |
211 | | |
212 | | private: |
213 | | double ToSeconds() const; |
214 | | |
215 | | std::chrono::steady_clock::time_point value_; |
216 | | }; |
217 | | |
218 | 59.6M | inline MonoTime& operator+=(MonoTime& lhs, const MonoDelta& rhs) { // NOLINT |
219 | 59.6M | lhs.AddDelta(rhs); |
220 | 59.6M | return lhs; |
221 | 59.6M | } |
222 | | |
223 | 59.6M | inline MonoTime operator+(MonoTime lhs, const MonoDelta& rhs) { |
224 | 59.6M | lhs += rhs; |
225 | 59.6M | return lhs; |
226 | 59.6M | } |
227 | | |
228 | | template <class Clock> |
229 | 129M | inline auto operator+(const std::chrono::time_point<Clock>& lhs, const MonoDelta& rhs) { |
230 | 129M | return lhs + rhs.ToSteadyDuration(); |
231 | 129M | } |
232 | | |
233 | 121M | inline MonoDelta operator-(const MonoTime& lhs, const MonoTime& rhs) { |
234 | 121M | return lhs.GetDeltaSince(rhs); |
235 | 121M | } |
236 | | |
237 | 0 | inline MonoTime& operator-=(MonoTime& lhs, const MonoDelta& rhs) { // NOLINT |
238 | 0 | lhs.SubtractDelta(rhs); |
239 | 0 | return lhs; |
240 | 0 | } |
241 | | |
242 | 975k | inline MonoTime operator-(const MonoTime& lhs, const MonoDelta& rhs) { |
243 | 975k | MonoTime result = lhs; |
244 | 975k | result.AddDelta(-rhs); |
245 | 975k | return MonoTime(result); |
246 | 975k | } |
247 | | |
248 | 26.6M | inline bool operator<(const MonoTime& lhs, const MonoTime& rhs) { |
249 | 26.6M | return lhs.ComesBefore(rhs); |
250 | 26.6M | } |
251 | | |
252 | 13.8M | inline bool operator>(const MonoTime& lhs, const MonoTime& rhs) { return rhs < lhs; } |
253 | 0 | inline bool operator<=(const MonoTime& lhs, const MonoTime& rhs) { return !(rhs < lhs); } |
254 | 6.63k | inline bool operator>=(const MonoTime& lhs, const MonoTime& rhs) { return !(lhs < rhs); } |
255 | | |
256 | 8.68k | inline bool operator==(const MonoTime& lhs, const MonoTime& rhs) { return lhs.Equals(rhs); } |
257 | 333 | inline bool operator!=(const MonoTime& lhs, const MonoTime& rhs) { return !(lhs == rhs); } |
258 | | |
259 | | // Sleep for a MonoDelta duration. |
260 | | // |
261 | | // This is preferred over sleep(3), usleep(3), and nanosleep(3). It's less prone to mixups with |
262 | | // units since it uses a MonoDelta. It also ignores EINTR, so will reliably sleep at least the |
263 | | // MonoDelta duration. |
264 | | void SleepFor(const MonoDelta& delta); |
265 | | |
266 | | class CoarseMonoClock { |
267 | | public: |
268 | | typedef std::chrono::nanoseconds duration; |
269 | | typedef duration Duration; |
270 | | typedef std::chrono::time_point<CoarseMonoClock> time_point; |
271 | | typedef time_point TimePoint; |
272 | | |
273 | | static constexpr bool is_steady = true; |
274 | | |
275 | | static time_point now(); |
276 | 391M | static TimePoint Now() { return now(); } |
277 | | }; |
278 | | |
279 | | template <class Clock> |
280 | 18.2k | typename Clock::duration ClockResolution() { |
281 | 18.2k | return typename Clock::duration(1); |
282 | 18.2k | } |
283 | | |
284 | | template <> |
285 | | CoarseMonoClock::Duration ClockResolution<CoarseMonoClock>(); |
286 | | |
287 | | typedef CoarseMonoClock::TimePoint CoarseTimePoint; |
288 | | typedef CoarseMonoClock::Duration CoarseDuration; |
289 | | |
290 | | template <class Rep, class Period> |
291 | 26.1k | int64_t ToMilliseconds(const std::chrono::duration<Rep, Period>& duration) { |
292 | 26.1k | return std::chrono::duration_cast<std::chrono::milliseconds>(duration).count(); |
293 | 26.1k | } _ZN2yb14ToMillisecondsIxNSt3__15ratioILl1ELl1EEEEExRKNS1_6chrono8durationIT_T0_EE Line | Count | Source | 291 | 2 | int64_t ToMilliseconds(const std::chrono::duration<Rep, Period>& duration) { | 292 | 2 | return std::chrono::duration_cast<std::chrono::milliseconds>(duration).count(); | 293 | 2 | } |
_ZN2yb14ToMillisecondsIxNSt3__15ratioILl1ELl1000000000EEEEExRKNS1_6chrono8durationIT_T0_EE Line | Count | Source | 291 | 26.1k | int64_t ToMilliseconds(const std::chrono::duration<Rep, Period>& duration) { | 292 | 26.1k | return std::chrono::duration_cast<std::chrono::milliseconds>(duration).count(); | 293 | 26.1k | } |
|
294 | | |
295 | | template <class Rep, class Period> |
296 | 11.6M | int64_t ToMicroseconds(const std::chrono::duration<Rep, Period>& duration) { |
297 | 11.6M | return std::chrono::duration_cast<std::chrono::microseconds>(duration).count(); |
298 | 11.6M | } _ZN2yb14ToMicrosecondsIxNSt3__15ratioILl1ELl1000000000EEEEExRKNS1_6chrono8durationIT_T0_EE Line | Count | Source | 296 | 11.6M | int64_t ToMicroseconds(const std::chrono::duration<Rep, Period>& duration) { | 297 | 11.6M | return std::chrono::duration_cast<std::chrono::microseconds>(duration).count(); | 298 | 11.6M | } |
_ZN2yb14ToMicrosecondsIxNSt3__15ratioILl1ELl1EEEEExRKNS1_6chrono8durationIT_T0_EE Line | Count | Source | 296 | 231 | int64_t ToMicroseconds(const std::chrono::duration<Rep, Period>& duration) { | 297 | 231 | return std::chrono::duration_cast<std::chrono::microseconds>(duration).count(); | 298 | 231 | } |
|
299 | | |
300 | | template <class Rep, class Period> |
301 | 3 | int64_t ToNanoseconds(const std::chrono::duration<Rep, Period>& duration) { |
302 | 3 | return std::chrono::duration_cast<std::chrono::nanoseconds>(duration).count(); |
303 | 3 | } |
304 | | |
305 | | template <class Rep, class Period> |
306 | 385k | double ToSeconds(const std::chrono::duration<Rep, Period>& duration) { |
307 | 385k | return duration.count() / |
308 | 385k | static_cast<double>(std::chrono::duration_cast<std::chrono::duration<Rep, Period>>( |
309 | 385k | std::chrono::seconds(1)).count()); |
310 | 385k | } |
311 | | |
312 | 1 | inline double ToSeconds(MonoDelta delta) { |
313 | 1 | return delta.ToSeconds(); |
314 | 1 | } |
315 | | |
316 | | std::string ToString(CoarseMonoClock::TimePoint value); |
317 | | |
318 | | CoarseTimePoint ToCoarse(MonoTime monotime); |
319 | | std::chrono::steady_clock::time_point ToSteady(CoarseTimePoint time_point); |
320 | | |
321 | | } // namespace yb |
322 | | |
323 | | #endif // YB_UTIL_MONOTIME_H |