1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
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.
15 #ifndef COMMON_CEPH_TIME_H
16 #define COMMON_CEPH_TIME_H
20 #include "include/encoding.h"
23 #include <sys/_types/_timespec.h>
24 #include <mach/mach.h>
25 #include <mach/clock.h>
27 #define CLOCK_REALTIME CALENDAR_CLOCK
28 #define CLOCK_MONOTONIC SYSTEM_CLOCK
29 #define CLOCK_REALTIME_COARSE CLOCK_REALTIME
30 #define CLOCK_MONOTONIC_COARSE CLOCK_MONOTONIC
32 int clock_gettime(int clk_id
, struct timespec
*tp
);
38 namespace time_detail
{
39 using std::chrono::duration_cast
;
40 using std::chrono::seconds
;
41 using std::chrono::microseconds
;
42 using std::chrono::nanoseconds
;
43 // Currently we use a 64-bit count of nanoseconds.
45 // We could, if we wished, use a struct holding a uint64_t count
46 // of seconds and a uint32_t count of nanoseconds.
48 // At least this way we can change it to something else if we
52 // A concrete duration, unsigned. The timespan Ceph thinks in.
53 typedef std::chrono::duration
<rep
, std::nano
> timespan
;
56 // Like the above but signed.
57 typedef int64_t signed_rep
;
59 typedef std::chrono::duration
<signed_rep
, std::nano
> signedspan
;
61 // We define our own clocks so we can have our choice of all time
62 // sources supported by the operating system. With the standard
63 // library the resolution and cost are unspecified. (For example,
64 // the libc++ system_clock class gives only microsecond
67 // One potential issue is that we should accept system_clock
68 // timepoints in user-facing APIs alongside (or instead of)
69 // ceph::real_clock times.
72 typedef timespan duration
;
73 typedef duration::rep rep
;
74 typedef duration::period period
;
75 // The second template parameter defaults to the clock's duration
77 typedef std::chrono::time_point
<real_clock
> time_point
;
78 static constexpr const bool is_steady
= false;
80 static time_point
now() noexcept
{
82 clock_gettime(CLOCK_REALTIME
, &ts
);
83 return from_timespec(ts
);
86 static bool is_zero(const time_point
& t
) {
87 return (t
== time_point::min());
90 // Allow conversion to/from any clock with the same interface as
91 // std::chrono::system_clock)
92 template<typename Clock
, typename Duration
>
93 static time_point
to_system_time_point(
94 const std::chrono::time_point
<Clock
, Duration
>& t
) {
95 return time_point(seconds(Clock::to_time_t(t
)) +
96 duration_cast
<duration
>(t
.time_since_epoch() %
99 template<typename Clock
, typename Duration
>
100 static std::chrono::time_point
<Clock
, Duration
> to_system_time_point(
101 const time_point
& t
) {
102 return (Clock::from_time_t(to_time_t(t
)) +
103 duration_cast
<Duration
>(t
.time_since_epoch() % seconds(1)));
106 static time_t to_time_t(const time_point
& t
) noexcept
{
107 return duration_cast
<seconds
>(t
.time_since_epoch()).count();
109 static time_point
from_time_t(const time_t& t
) noexcept
{
110 return time_point(seconds(t
));
113 static void to_timespec(const time_point
& t
, struct timespec
& ts
) {
114 ts
.tv_sec
= to_time_t(t
);
115 ts
.tv_nsec
= (t
.time_since_epoch() % seconds(1)).count();
117 static struct timespec
to_timespec(const time_point
& t
) {
122 static time_point
from_timespec(const struct timespec
& ts
) {
123 return time_point(seconds(ts
.tv_sec
) + nanoseconds(ts
.tv_nsec
));
126 static void to_ceph_timespec(const time_point
& t
,
127 struct ceph_timespec
& ts
);
128 static struct ceph_timespec
to_ceph_timespec(const time_point
& t
);
129 static time_point
from_ceph_timespec(const struct ceph_timespec
& ts
);
131 static void to_timeval(const time_point
& t
, struct timeval
& tv
) {
132 tv
.tv_sec
= to_time_t(t
);
133 tv
.tv_usec
= duration_cast
<microseconds
>(t
.time_since_epoch() %
136 static struct timeval
to_timeval(const time_point
& t
) {
141 static time_point
from_timeval(const struct timeval
& tv
) {
142 return time_point(seconds(tv
.tv_sec
) + microseconds(tv
.tv_usec
));
145 static double to_double(const time_point
& t
) {
146 return std::chrono::duration
<double>(t
.time_since_epoch()).count();
148 static time_point
from_double(const double d
) {
149 return time_point(duration_cast
<duration
>(
150 std::chrono::duration
<double>(d
)));
154 class coarse_real_clock
{
156 typedef timespan duration
;
157 typedef duration::rep rep
;
158 typedef duration::period period
;
159 // The second template parameter defaults to the clock's duration
161 typedef std::chrono::time_point
<coarse_real_clock
> time_point
;
162 static constexpr const bool is_steady
= false;
164 static time_point
now() noexcept
{
166 #if defined(CLOCK_REALTIME_COARSE)
167 // Linux systems have _COARSE clocks.
168 clock_gettime(CLOCK_REALTIME_COARSE
, &ts
);
169 #elif defined(CLOCK_REALTIME_FAST)
170 // BSD systems have _FAST clocks.
171 clock_gettime(CLOCK_REALTIME_FAST
, &ts
);
173 // And if we find neither, you may wish to consult your system's
175 #warning Falling back to CLOCK_REALTIME, may be slow.
176 clock_gettime(CLOCK_REALTIME
, &ts
);
178 return from_timespec(ts
);
181 static time_t to_time_t(const time_point
& t
) noexcept
{
182 return duration_cast
<seconds
>(t
.time_since_epoch()).count();
184 static time_point
from_time_t(const time_t t
) noexcept
{
185 return time_point(seconds(t
));
188 static void to_timespec(const time_point
& t
, struct timespec
& ts
) {
189 ts
.tv_sec
= to_time_t(t
);
190 ts
.tv_nsec
= (t
.time_since_epoch() % seconds(1)).count();
192 static struct timespec
to_timespec(const time_point
& t
) {
197 static time_point
from_timespec(const struct timespec
& ts
) {
198 return time_point(seconds(ts
.tv_sec
) + nanoseconds(ts
.tv_nsec
));
201 static void to_ceph_timespec(const time_point
& t
,
202 struct ceph_timespec
& ts
);
203 static struct ceph_timespec
to_ceph_timespec(const time_point
& t
);
204 static time_point
from_ceph_timespec(const struct ceph_timespec
& ts
);
206 static void to_timeval(const time_point
& t
, struct timeval
& tv
) {
207 tv
.tv_sec
= to_time_t(t
);
208 tv
.tv_usec
= duration_cast
<microseconds
>(t
.time_since_epoch() %
211 static struct timeval
to_timeval(const time_point
& t
) {
216 static time_point
from_timeval(const struct timeval
& tv
) {
217 return time_point(seconds(tv
.tv_sec
) + microseconds(tv
.tv_usec
));
220 static double to_double(const time_point
& t
) {
221 return std::chrono::duration
<double>(t
.time_since_epoch()).count();
223 static time_point
from_double(const double d
) {
224 return time_point(duration_cast
<duration
>(
225 std::chrono::duration
<double>(d
)));
231 typedef timespan duration
;
232 typedef duration::rep rep
;
233 typedef duration::period period
;
234 typedef std::chrono::time_point
<mono_clock
> time_point
;
235 static constexpr const bool is_steady
= true;
237 static time_point
now() noexcept
{
239 clock_gettime(CLOCK_MONOTONIC
, &ts
);
240 return time_point(seconds(ts
.tv_sec
) + nanoseconds(ts
.tv_nsec
));
243 // A monotonic clock's timepoints are only meaningful to the
244 // computer on which they were generated. Thus having an
245 // optional skew is meaningless.
248 class coarse_mono_clock
{
250 typedef timespan duration
;
251 typedef duration::rep rep
;
252 typedef duration::period period
;
253 typedef std::chrono::time_point
<coarse_mono_clock
> time_point
;
254 static constexpr const bool is_steady
= true;
256 static time_point
now() noexcept
{
258 #if defined(CLOCK_MONOTONIC_COARSE)
259 // Linux systems have _COARSE clocks.
260 clock_gettime(CLOCK_MONOTONIC_COARSE
, &ts
);
261 #elif defined(CLOCK_MONOTONIC_FAST)
262 // BSD systems have _FAST clocks.
263 clock_gettime(CLOCK_MONOTONIC_FAST
, &ts
);
265 // And if we find neither, you may wish to consult your system's
267 #warning Falling back to CLOCK_MONOTONIC, may be slow.
268 clock_gettime(CLOCK_MONOTONIC
, &ts
);
270 return time_point(seconds(ts
.tv_sec
) + nanoseconds(ts
.tv_nsec
));
274 // So that our subtractions produce negative spans rather than
275 // arithmetic underflow.
277 template<typename Rep1
, typename Period1
, typename Rep2
,
279 inline auto difference(std::chrono::duration
<Rep1
, Period1
> minuend
,
280 std::chrono::duration
<Rep2
, Period2
> subtrahend
)
281 -> typename
std::common_type
<
282 std::chrono::duration
<typename
std::make_signed
<Rep1
>::type
,
284 std::chrono::duration
<typename
std::make_signed
<Rep2
>::type
,
288 typename
std::common_type
<
289 std::chrono::duration
<typename
std::make_signed
<Rep1
>::type
,
291 std::chrono::duration
<typename
std::make_signed
<Rep2
>::type
,
293 return srep(srep(minuend
).count() - srep(subtrahend
).count());
296 template<typename Clock
, typename Duration1
, typename Duration2
>
297 inline auto difference(
298 typename
std::chrono::time_point
<Clock
, Duration1
> minuend
,
299 typename
std::chrono::time_point
<Clock
, Duration2
> subtrahend
)
300 -> typename
std::common_type
<
301 std::chrono::duration
<typename
std::make_signed
<
302 typename
Duration1::rep
>::type
,
303 typename
Duration1::period
>,
304 std::chrono::duration
<typename
std::make_signed
<
305 typename
Duration2::rep
>::type
,
306 typename
Duration2::period
> >::type
{
307 return difference(minuend
.time_since_epoch(),
308 subtrahend
.time_since_epoch());
311 } // namespace time_detail
313 // duration is the concrete time representation for our code in the
314 // case that we are only interested in durations between now and the
315 // future. Using it means we don't have to have EVERY function that
316 // deals with a duration be a template. We can do so for user-facing
318 using time_detail::timespan
;
320 // Similar to the above but for durations that can specify
321 // differences between now and a time point in the past.
322 using time_detail::signedspan
;
324 // High-resolution real-time clock
325 using time_detail::real_clock
;
327 // Low-resolution but preusmably faster real-time clock
328 using time_detail::coarse_real_clock
;
331 // High-resolution monotonic clock
332 using time_detail::mono_clock
;
334 // Low-resolution but, I would hope or there's no point, faster
336 using time_detail::coarse_mono_clock
;
338 // Please note that the coarse clocks are disjoint. You cannot
339 // subtract a real_clock timepoint from a coarse_real_clock
340 // timepoint as, from C++'s perspective, they are disjoint types.
342 // This is not necessarily bad. If I sample a mono_clock and then a
343 // coarse_mono_clock, the coarse_mono_clock's time could potentially
344 // be previous to the mono_clock's time (just due to differing
345 // resolution) which would be Incorrect.
347 // This is not horrible, though, since you can use an idiom like
348 // mono_clock::timepoint(coarsepoint.time_since_epoch()) to unwrap
349 // and rewrap if you know what you're doing.
352 // Actual wall-clock times
353 typedef real_clock::time_point real_time
;
354 typedef coarse_real_clock::time_point coarse_real_time
;
356 // Monotonic times should never be serialized or communicated
357 // between machines, since they are incomparable. Thus we also don't
358 // make any provision for converting between
359 // std::chrono::steady_clock time and ceph::mono_clock time.
360 typedef mono_clock::time_point mono_time
;
361 typedef coarse_mono_clock::time_point coarse_mono_time
;
363 template<typename Rep1
, typename Ratio1
, typename Rep2
, typename Ratio2
>
364 auto floor(const std::chrono::duration
<Rep1
, Ratio1
>& duration
,
365 const std::chrono::duration
<Rep2
, Ratio2
>& precision
) ->
366 typename
std::common_type
<std::chrono::duration
<Rep1
, Ratio1
>,
367 std::chrono::duration
<Rep2
, Ratio2
> >::type
{
368 return duration
- (duration
% precision
);
371 template<typename Rep1
, typename Ratio1
, typename Rep2
, typename Ratio2
>
372 auto ceil(const std::chrono::duration
<Rep1
, Ratio1
>& duration
,
373 const std::chrono::duration
<Rep2
, Ratio2
>& precision
) ->
374 typename
std::common_type
<std::chrono::duration
<Rep1
, Ratio1
>,
375 std::chrono::duration
<Rep2
, Ratio2
> >::type
{
376 auto tmod
= duration
% precision
;
377 return duration
- tmod
+ (tmod
> tmod
.zero() ? 1 : 0) * precision
;
380 template<typename Clock
, typename Duration
, typename Rep
, typename Ratio
>
381 auto floor(const std::chrono::time_point
<Clock
, Duration
>& timepoint
,
382 const std::chrono::duration
<Rep
, Ratio
>& precision
) ->
383 std::chrono::time_point
<Clock
,
384 typename
std::common_type
<
385 Duration
, std::chrono::duration
<Rep
, Ratio
>
387 return std::chrono::time_point
<
388 Clock
, typename
std::common_type
<
389 Duration
, std::chrono::duration
<Rep
, Ratio
> >::type
>(
390 floor(timepoint
.time_since_epoch(), precision
));
392 template<typename Clock
, typename Duration
, typename Rep
, typename Ratio
>
393 auto ceil(const std::chrono::time_point
<Clock
, Duration
>& timepoint
,
394 const std::chrono::duration
<Rep
, Ratio
>& precision
) ->
395 std::chrono::time_point
<Clock
,
396 typename
std::common_type
<
398 std::chrono::duration
<Rep
, Ratio
> >::type
> {
399 return std::chrono::time_point
<
400 Clock
, typename
std::common_type
<
401 Duration
, std::chrono::duration
<Rep
, Ratio
> >::type
>(
402 ceil(timepoint
.time_since_epoch(), precision
));
406 inline timespan
make_timespan(const double d
) {
407 return std::chrono::duration_cast
<timespan
>(
408 std::chrono::duration
<double>(d
));
412 std::ostream
& operator<<(std::ostream
& m
, const timespan
& t
);
413 template<typename Clock
,
414 typename
std::enable_if
<!Clock::is_steady
>::type
* = nullptr>
415 std::ostream
& operator<<(std::ostream
& m
,
416 const std::chrono::time_point
<Clock
>& t
);
417 template<typename Clock
,
418 typename
std::enable_if
<Clock::is_steady
>::type
* = nullptr>
419 std::ostream
& operator<<(std::ostream
& m
,
420 const std::chrono::time_point
<Clock
>& t
);
422 // The way std::chrono handles the return type of subtraction is not
423 // wonderful. The difference of two unsigned types SHOULD be signed.
426 inline signedspan
operator -(real_time minuend
,
427 real_time subtrahend
) {
428 return time_detail::difference(minuend
, subtrahend
);
431 inline signedspan
operator -(coarse_real_time minuend
,
432 coarse_real_time subtrahend
) {
433 return time_detail::difference(minuend
, subtrahend
);
436 inline signedspan
operator -(mono_time minuend
,
437 mono_time subtrahend
) {
438 return time_detail::difference(minuend
, subtrahend
);
441 inline signedspan
operator -(coarse_mono_time minuend
,
442 coarse_mono_time subtrahend
) {
443 return time_detail::difference(minuend
, subtrahend
);
447 // We could add specializations of time_point - duration and
448 // time_point + duration to assert on overflow, but I don't think we
453 // We need these definitions to be able to hande ::encode/::decode on
456 template<typename Clock
, typename Duration
>
457 void encode(const std::chrono::time_point
<Clock
, Duration
>& t
,
458 ceph::bufferlist
&bl
) {
459 auto ts
= Clock::to_timespec(t
);
460 // A 32 bit count of seconds causes me vast unhappiness.
461 uint32_t s
= ts
.tv_sec
;
462 uint32_t ns
= ts
.tv_nsec
;
467 template<typename Clock
, typename Duration
>
468 void decode(std::chrono::time_point
<Clock
, Duration
>& t
,
469 bufferlist::iterator
& p
) {
474 struct timespec ts
= {
475 static_cast<time_t>(s
),
476 static_cast<long int>(ns
)};
478 t
= Clock::from_timespec(ts
);
481 // C++ Overload Resolution requires that our encode/decode functions
482 // be defined in the same namespace as the type. So we need this
483 // to handle things like ::encode(std::vector<ceph::real_time // > >)
487 template<typename Clock
, typename Duration
>
488 void encode(const time_point
<Clock
, Duration
>& t
,
489 ceph::bufferlist
&bl
) {
493 template<typename Clock
, typename Duration
>
494 void decode(time_point
<Clock
, Duration
>& t
, bufferlist::iterator
&p
) {
497 } // namespace chrono
499 // An overload of our own
501 inline timespan
abs(signedspan z
) {
502 return z
> signedspan::zero() ?
503 std::chrono::duration_cast
<timespan
>(z
) :
504 timespan(-z
.count());
509 #endif // COMMON_CEPH_TIME_H