]> git.proxmox.com Git - ceph.git/blob - ceph/src/common/ceph_time.h
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / common / ceph_time.h
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3 /*
4 * Ceph - scalable distributed file system
5 *
6 * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
7 *
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
12 *
13 */
14
15 #ifndef COMMON_CEPH_TIME_H
16 #define COMMON_CEPH_TIME_H
17
18 #include <chrono>
19 #include <ctime>
20
21 #include "include/encoding.h"
22
23 #if defined(DARWIN)
24 #include <sys/_types/_timespec.h>
25 #include <mach/mach.h>
26 #include <mach/clock.h>
27
28 #define CLOCK_REALTIME CALENDAR_CLOCK
29 #define CLOCK_MONOTONIC SYSTEM_CLOCK
30 #define CLOCK_REALTIME_COARSE CLOCK_REALTIME
31 #define CLOCK_MONOTONIC_COARSE CLOCK_MONOTONIC
32
33 int clock_gettime(int clk_id, struct timespec *tp);
34 #endif
35
36 struct ceph_timespec;
37
38 namespace ceph {
39 namespace time_detail {
40 using std::chrono::duration_cast;
41 using std::chrono::seconds;
42 using std::chrono::microseconds;
43 using std::chrono::nanoseconds;
44 // Currently we use a 64-bit count of nanoseconds.
45
46 // We could, if we wished, use a struct holding a uint64_t count
47 // of seconds and a uint32_t count of nanoseconds.
48
49 // At least this way we can change it to something else if we
50 // want.
51 typedef uint64_t rep;
52
53 // A concrete duration, unsigned. The timespan Ceph thinks in.
54 typedef std::chrono::duration<rep, std::nano> timespan;
55
56
57 // Like the above but signed.
58 typedef int64_t signed_rep;
59
60 typedef std::chrono::duration<signed_rep, std::nano> signedspan;
61
62 // We define our own clocks so we can have our choice of all time
63 // sources supported by the operating system. With the standard
64 // library the resolution and cost are unspecified. (For example,
65 // the libc++ system_clock class gives only microsecond
66 // resolution.)
67
68 // One potential issue is that we should accept system_clock
69 // timepoints in user-facing APIs alongside (or instead of)
70 // ceph::real_clock times.
71 class real_clock {
72 public:
73 typedef timespan duration;
74 typedef duration::rep rep;
75 typedef duration::period period;
76 // The second template parameter defaults to the clock's duration
77 // type.
78 typedef std::chrono::time_point<real_clock> time_point;
79 static constexpr const bool is_steady = false;
80
81 static time_point now() noexcept {
82 struct timespec ts;
83 clock_gettime(CLOCK_REALTIME, &ts);
84 return from_timespec(ts);
85 }
86
87 static bool is_zero(const time_point& t) {
88 return (t == time_point::min());
89 }
90
91 // Allow conversion to/from any clock with the same interface as
92 // std::chrono::system_clock)
93 template<typename Clock, typename Duration>
94 static time_point to_system_time_point(
95 const std::chrono::time_point<Clock, Duration>& t) {
96 return time_point(seconds(Clock::to_time_t(t)) +
97 duration_cast<duration>(t.time_since_epoch() %
98 seconds(1)));
99 }
100 template<typename Clock, typename Duration>
101 static std::chrono::time_point<Clock, Duration> to_system_time_point(
102 const time_point& t) {
103 return (Clock::from_time_t(to_time_t(t)) +
104 duration_cast<Duration>(t.time_since_epoch() % seconds(1)));
105 }
106
107 static time_t to_time_t(const time_point& t) noexcept {
108 return duration_cast<seconds>(t.time_since_epoch()).count();
109 }
110 static time_point from_time_t(const time_t& t) noexcept {
111 return time_point(seconds(t));
112 }
113
114 static void to_timespec(const time_point& t, struct timespec& ts) {
115 ts.tv_sec = to_time_t(t);
116 ts.tv_nsec = (t.time_since_epoch() % seconds(1)).count();
117 }
118 static struct timespec to_timespec(const time_point& t) {
119 struct timespec ts;
120 to_timespec(t, ts);
121 return ts;
122 }
123 static time_point from_timespec(const struct timespec& ts) {
124 return time_point(seconds(ts.tv_sec) + nanoseconds(ts.tv_nsec));
125 }
126
127 static void to_ceph_timespec(const time_point& t,
128 struct ceph_timespec& ts);
129 static struct ceph_timespec to_ceph_timespec(const time_point& t);
130 static time_point from_ceph_timespec(const struct ceph_timespec& ts);
131
132 static void to_timeval(const time_point& t, struct timeval& tv) {
133 tv.tv_sec = to_time_t(t);
134 tv.tv_usec = duration_cast<microseconds>(t.time_since_epoch() %
135 seconds(1)).count();
136 }
137 static struct timeval to_timeval(const time_point& t) {
138 struct timeval tv;
139 to_timeval(t, tv);
140 return tv;
141 }
142 static time_point from_timeval(const struct timeval& tv) {
143 return time_point(seconds(tv.tv_sec) + microseconds(tv.tv_usec));
144 }
145
146 static double to_double(const time_point& t) {
147 return std::chrono::duration<double>(t.time_since_epoch()).count();
148 }
149 static time_point from_double(const double d) {
150 return time_point(duration_cast<duration>(
151 std::chrono::duration<double>(d)));
152 }
153 };
154
155 class coarse_real_clock {
156 public:
157 typedef timespan duration;
158 typedef duration::rep rep;
159 typedef duration::period period;
160 // The second template parameter defaults to the clock's duration
161 // type.
162 typedef std::chrono::time_point<coarse_real_clock> time_point;
163 static constexpr const bool is_steady = false;
164
165 static time_point now() noexcept {
166 struct timespec ts;
167 #if defined(CLOCK_REALTIME_COARSE)
168 // Linux systems have _COARSE clocks.
169 clock_gettime(CLOCK_REALTIME_COARSE, &ts);
170 #elif defined(CLOCK_REALTIME_FAST)
171 // BSD systems have _FAST clocks.
172 clock_gettime(CLOCK_REALTIME_FAST, &ts);
173 #else
174 // And if we find neither, you may wish to consult your system's
175 // documentation.
176 #warning Falling back to CLOCK_REALTIME, may be slow.
177 clock_gettime(CLOCK_REALTIME, &ts);
178 #endif
179 return from_timespec(ts);
180 }
181
182 static time_t to_time_t(const time_point& t) noexcept {
183 return duration_cast<seconds>(t.time_since_epoch()).count();
184 }
185 static time_point from_time_t(const time_t t) noexcept {
186 return time_point(seconds(t));
187 }
188
189 static void to_timespec(const time_point& t, struct timespec& ts) {
190 ts.tv_sec = to_time_t(t);
191 ts.tv_nsec = (t.time_since_epoch() % seconds(1)).count();
192 }
193 static struct timespec to_timespec(const time_point& t) {
194 struct timespec ts;
195 to_timespec(t, ts);
196 return ts;
197 }
198 static time_point from_timespec(const struct timespec& ts) {
199 return time_point(seconds(ts.tv_sec) + nanoseconds(ts.tv_nsec));
200 }
201
202 static void to_ceph_timespec(const time_point& t,
203 struct ceph_timespec& ts);
204 static struct ceph_timespec to_ceph_timespec(const time_point& t);
205 static time_point from_ceph_timespec(const struct ceph_timespec& ts);
206
207 static void to_timeval(const time_point& t, struct timeval& tv) {
208 tv.tv_sec = to_time_t(t);
209 tv.tv_usec = duration_cast<microseconds>(t.time_since_epoch() %
210 seconds(1)).count();
211 }
212 static struct timeval to_timeval(const time_point& t) {
213 struct timeval tv;
214 to_timeval(t, tv);
215 return tv;
216 }
217 static time_point from_timeval(const struct timeval& tv) {
218 return time_point(seconds(tv.tv_sec) + microseconds(tv.tv_usec));
219 }
220
221 static double to_double(const time_point& t) {
222 return std::chrono::duration<double>(t.time_since_epoch()).count();
223 }
224 static time_point from_double(const double d) {
225 return time_point(duration_cast<duration>(
226 std::chrono::duration<double>(d)));
227 }
228 };
229
230 class mono_clock {
231 public:
232 typedef timespan duration;
233 typedef duration::rep rep;
234 typedef duration::period period;
235 typedef std::chrono::time_point<mono_clock> time_point;
236 static constexpr const bool is_steady = true;
237
238 static time_point now() noexcept {
239 struct timespec ts;
240 clock_gettime(CLOCK_MONOTONIC, &ts);
241 return time_point(seconds(ts.tv_sec) + nanoseconds(ts.tv_nsec));
242 }
243
244 // A monotonic clock's timepoints are only meaningful to the
245 // computer on which they were generated. Thus having an
246 // optional skew is meaningless.
247 };
248
249 class coarse_mono_clock {
250 public:
251 typedef timespan duration;
252 typedef duration::rep rep;
253 typedef duration::period period;
254 typedef std::chrono::time_point<coarse_mono_clock> time_point;
255 static constexpr const bool is_steady = true;
256
257 static time_point now() noexcept {
258 struct timespec ts;
259 #if defined(CLOCK_MONOTONIC_COARSE)
260 // Linux systems have _COARSE clocks.
261 clock_gettime(CLOCK_MONOTONIC_COARSE, &ts);
262 #elif defined(CLOCK_MONOTONIC_FAST)
263 // BSD systems have _FAST clocks.
264 clock_gettime(CLOCK_MONOTONIC_FAST, &ts);
265 #else
266 // And if we find neither, you may wish to consult your system's
267 // documentation.
268 #warning Falling back to CLOCK_MONOTONIC, may be slow.
269 clock_gettime(CLOCK_MONOTONIC, &ts);
270 #endif
271 return time_point(seconds(ts.tv_sec) + nanoseconds(ts.tv_nsec));
272 }
273 };
274
275 // So that our subtractions produce negative spans rather than
276 // arithmetic underflow.
277 namespace {
278 template<typename Rep1, typename Period1, typename Rep2,
279 typename Period2>
280 inline auto difference(std::chrono::duration<Rep1, Period1> minuend,
281 std::chrono::duration<Rep2, Period2> subtrahend)
282 -> typename std::common_type<
283 std::chrono::duration<typename std::make_signed<Rep1>::type,
284 Period1>,
285 std::chrono::duration<typename std::make_signed<Rep2>::type,
286 Period2> >::type {
287 // Foo.
288 using srep =
289 typename std::common_type<
290 std::chrono::duration<typename std::make_signed<Rep1>::type,
291 Period1>,
292 std::chrono::duration<typename std::make_signed<Rep2>::type,
293 Period2> >::type;
294 return srep(srep(minuend).count() - srep(subtrahend).count());
295 }
296
297 template<typename Clock, typename Duration1, typename Duration2>
298 inline auto difference(
299 typename std::chrono::time_point<Clock, Duration1> minuend,
300 typename std::chrono::time_point<Clock, Duration2> subtrahend)
301 -> typename std::common_type<
302 std::chrono::duration<typename std::make_signed<
303 typename Duration1::rep>::type,
304 typename Duration1::period>,
305 std::chrono::duration<typename std::make_signed<
306 typename Duration2::rep>::type,
307 typename Duration2::period> >::type {
308 return difference(minuend.time_since_epoch(),
309 subtrahend.time_since_epoch());
310 }
311 }
312 } // namespace time_detail
313
314 // duration is the concrete time representation for our code in the
315 // case that we are only interested in durations between now and the
316 // future. Using it means we don't have to have EVERY function that
317 // deals with a duration be a template. We can do so for user-facing
318 // APIs, however.
319 using time_detail::timespan;
320
321 // Similar to the above but for durations that can specify
322 // differences between now and a time point in the past.
323 using time_detail::signedspan;
324
325 // High-resolution real-time clock
326 using time_detail::real_clock;
327
328 // Low-resolution but preusmably faster real-time clock
329 using time_detail::coarse_real_clock;
330
331
332 // High-resolution monotonic clock
333 using time_detail::mono_clock;
334
335 // Low-resolution but, I would hope or there's no point, faster
336 // monotonic clock
337 using time_detail::coarse_mono_clock;
338
339 // Please note that the coarse clocks are disjoint. You cannot
340 // subtract a real_clock timepoint from a coarse_real_clock
341 // timepoint as, from C++'s perspective, they are disjoint types.
342
343 // This is not necessarily bad. If I sample a mono_clock and then a
344 // coarse_mono_clock, the coarse_mono_clock's time could potentially
345 // be previous to the mono_clock's time (just due to differing
346 // resolution) which would be Incorrect.
347
348 // This is not horrible, though, since you can use an idiom like
349 // mono_clock::timepoint(coarsepoint.time_since_epoch()) to unwrap
350 // and rewrap if you know what you're doing.
351
352
353 // Actual wall-clock times
354 typedef real_clock::time_point real_time;
355 typedef coarse_real_clock::time_point coarse_real_time;
356
357 // Monotonic times should never be serialized or communicated
358 // between machines, since they are incomparable. Thus we also don't
359 // make any provision for converting between
360 // std::chrono::steady_clock time and ceph::mono_clock time.
361 typedef mono_clock::time_point mono_time;
362 typedef coarse_mono_clock::time_point coarse_mono_time;
363
364 template<typename Rep1, typename Ratio1, typename Rep2, typename Ratio2>
365 auto floor(const std::chrono::duration<Rep1, Ratio1>& duration,
366 const std::chrono::duration<Rep2, Ratio2>& precision) ->
367 typename std::common_type<std::chrono::duration<Rep1, Ratio1>,
368 std::chrono::duration<Rep2, Ratio2> >::type {
369 return duration - (duration % precision);
370 }
371
372 template<typename Rep1, typename Ratio1, typename Rep2, typename Ratio2>
373 auto ceil(const std::chrono::duration<Rep1, Ratio1>& duration,
374 const std::chrono::duration<Rep2, Ratio2>& precision) ->
375 typename std::common_type<std::chrono::duration<Rep1, Ratio1>,
376 std::chrono::duration<Rep2, Ratio2> >::type {
377 auto tmod = duration % precision;
378 return duration - tmod + (tmod > tmod.zero() ? 1 : 0) * precision;
379 }
380
381 template<typename Clock, typename Duration, typename Rep, typename Ratio>
382 auto floor(const std::chrono::time_point<Clock, Duration>& timepoint,
383 const std::chrono::duration<Rep, Ratio>& precision) ->
384 std::chrono::time_point<Clock,
385 typename std::common_type<
386 Duration, std::chrono::duration<Rep, Ratio>
387 >::type> {
388 return std::chrono::time_point<
389 Clock, typename std::common_type<
390 Duration, std::chrono::duration<Rep, Ratio> >::type>(
391 floor(timepoint.time_since_epoch(), precision));
392 }
393 template<typename Clock, typename Duration, typename Rep, typename Ratio>
394 auto ceil(const std::chrono::time_point<Clock, Duration>& timepoint,
395 const std::chrono::duration<Rep, Ratio>& precision) ->
396 std::chrono::time_point<Clock,
397 typename std::common_type<
398 Duration,
399 std::chrono::duration<Rep, Ratio> >::type> {
400 return std::chrono::time_point<
401 Clock, typename std::common_type<
402 Duration, std::chrono::duration<Rep, Ratio> >::type>(
403 ceil(timepoint.time_since_epoch(), precision));
404 }
405
406 namespace {
407 inline timespan make_timespan(const double d) {
408 return std::chrono::duration_cast<timespan>(
409 std::chrono::duration<double>(d));
410 }
411 }
412
413 std::ostream& operator<<(std::ostream& m, const timespan& t);
414 template<typename Clock,
415 typename std::enable_if<!Clock::is_steady>::type* = nullptr>
416 std::ostream& operator<<(std::ostream& m,
417 const std::chrono::time_point<Clock>& t);
418 template<typename Clock,
419 typename std::enable_if<Clock::is_steady>::type* = nullptr>
420 std::ostream& operator<<(std::ostream& m,
421 const std::chrono::time_point<Clock>& t);
422
423 // The way std::chrono handles the return type of subtraction is not
424 // wonderful. The difference of two unsigned types SHOULD be signed.
425
426 namespace {
427 inline signedspan operator -(real_time minuend,
428 real_time subtrahend) {
429 return time_detail::difference(minuend, subtrahend);
430 }
431
432 inline signedspan operator -(coarse_real_time minuend,
433 coarse_real_time subtrahend) {
434 return time_detail::difference(minuend, subtrahend);
435 }
436
437 inline signedspan operator -(mono_time minuend,
438 mono_time subtrahend) {
439 return time_detail::difference(minuend, subtrahend);
440 }
441
442 inline signedspan operator -(coarse_mono_time minuend,
443 coarse_mono_time subtrahend) {
444 return time_detail::difference(minuend, subtrahend);
445 }
446 }
447
448 // We could add specializations of time_point - duration and
449 // time_point + duration to assert on overflow, but I don't think we
450 // should.
451
452 } // namespace ceph
453
454 // We need these definitions to be able to hande ::encode/::decode on
455 // time points.
456
457 template<typename Clock, typename Duration>
458 void encode(const std::chrono::time_point<Clock, Duration>& t,
459 ceph::bufferlist &bl) {
460 auto ts = Clock::to_timespec(t);
461 // A 32 bit count of seconds causes me vast unhappiness.
462 uint32_t s = ts.tv_sec;
463 uint32_t ns = ts.tv_nsec;
464 ::encode(s, bl);
465 ::encode(ns, bl);
466 }
467
468 template<typename Clock, typename Duration>
469 void decode(std::chrono::time_point<Clock, Duration>& t,
470 bufferlist::iterator& p) {
471 uint32_t s;
472 uint32_t ns;
473 ::decode(s, p);
474 ::decode(ns, p);
475 struct timespec ts = {
476 static_cast<time_t>(s),
477 static_cast<long int>(ns)};
478
479 t = Clock::from_timespec(ts);
480 }
481
482 // C++ Overload Resolution requires that our encode/decode functions
483 // be defined in the same namespace as the type. So we need this
484 // to handle things like ::encode(std::vector<ceph::real_time // > >)
485
486 namespace std {
487 namespace chrono {
488 template<typename Clock, typename Duration>
489 void encode(const time_point<Clock, Duration>& t,
490 ceph::bufferlist &bl) {
491 ::encode(t, bl);
492 }
493
494 template<typename Clock, typename Duration>
495 void decode(time_point<Clock, Duration>& t, bufferlist::iterator &p) {
496 ::decode(t, p);
497 }
498 } // namespace chrono
499
500 // An overload of our own
501 namespace {
502 inline timespan abs(signedspan z) {
503 return z > signedspan::zero() ?
504 std::chrono::duration_cast<timespan>(z) :
505 timespan(-z.count());
506 }
507 }
508 } // namespace std
509
510 #endif // COMMON_CEPH_TIME_H