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
21 #include "include/encoding.h"
24 #include <sys/_types/_timespec.h>
25 #include <mach/mach.h>
26 #include <mach/clock.h>
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
33 int clock_gettime(int clk_id
, struct timespec
*tp
);
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.
46 // We could, if we wished, use a struct holding a uint64_t count
47 // of seconds and a uint32_t count of nanoseconds.
49 // At least this way we can change it to something else if we
53 // A concrete duration, unsigned. The timespan Ceph thinks in.
54 typedef std::chrono::duration
<rep
, std::nano
> timespan
;
57 // Like the above but signed.
58 typedef int64_t signed_rep
;
60 typedef std::chrono::duration
<signed_rep
, std::nano
> signedspan
;
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
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.
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
78 typedef std::chrono::time_point
<real_clock
> time_point
;
79 static constexpr const bool is_steady
= false;
81 static time_point
now() noexcept
{
83 clock_gettime(CLOCK_REALTIME
, &ts
);
84 return from_timespec(ts
);
87 static bool is_zero(const time_point
& t
) {
88 return (t
== time_point::min());
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() %
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)));
107 static time_t to_time_t(const time_point
& t
) noexcept
{
108 return duration_cast
<seconds
>(t
.time_since_epoch()).count();
110 static time_point
from_time_t(const time_t& t
) noexcept
{
111 return time_point(seconds(t
));
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();
118 static struct timespec
to_timespec(const time_point
& t
) {
123 static time_point
from_timespec(const struct timespec
& ts
) {
124 return time_point(seconds(ts
.tv_sec
) + nanoseconds(ts
.tv_nsec
));
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
);
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() %
137 static struct timeval
to_timeval(const time_point
& t
) {
142 static time_point
from_timeval(const struct timeval
& tv
) {
143 return time_point(seconds(tv
.tv_sec
) + microseconds(tv
.tv_usec
));
146 static double to_double(const time_point
& t
) {
147 return std::chrono::duration
<double>(t
.time_since_epoch()).count();
149 static time_point
from_double(const double d
) {
150 return time_point(duration_cast
<duration
>(
151 std::chrono::duration
<double>(d
)));
155 class coarse_real_clock
{
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
162 typedef std::chrono::time_point
<coarse_real_clock
> time_point
;
163 static constexpr const bool is_steady
= false;
165 static time_point
now() noexcept
{
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
);
174 // And if we find neither, you may wish to consult your system's
176 #warning Falling back to CLOCK_REALTIME, may be slow.
177 clock_gettime(CLOCK_REALTIME
, &ts
);
179 return from_timespec(ts
);
182 static time_t to_time_t(const time_point
& t
) noexcept
{
183 return duration_cast
<seconds
>(t
.time_since_epoch()).count();
185 static time_point
from_time_t(const time_t t
) noexcept
{
186 return time_point(seconds(t
));
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();
193 static struct timespec
to_timespec(const time_point
& t
) {
198 static time_point
from_timespec(const struct timespec
& ts
) {
199 return time_point(seconds(ts
.tv_sec
) + nanoseconds(ts
.tv_nsec
));
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
);
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() %
212 static struct timeval
to_timeval(const time_point
& t
) {
217 static time_point
from_timeval(const struct timeval
& tv
) {
218 return time_point(seconds(tv
.tv_sec
) + microseconds(tv
.tv_usec
));
221 static double to_double(const time_point
& t
) {
222 return std::chrono::duration
<double>(t
.time_since_epoch()).count();
224 static time_point
from_double(const double d
) {
225 return time_point(duration_cast
<duration
>(
226 std::chrono::duration
<double>(d
)));
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;
238 static time_point
now() noexcept
{
240 clock_gettime(CLOCK_MONOTONIC
, &ts
);
241 return time_point(seconds(ts
.tv_sec
) + nanoseconds(ts
.tv_nsec
));
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.
249 class coarse_mono_clock
{
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;
257 static time_point
now() noexcept
{
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
);
266 // And if we find neither, you may wish to consult your system's
268 #warning Falling back to CLOCK_MONOTONIC, may be slow.
269 clock_gettime(CLOCK_MONOTONIC
, &ts
);
271 return time_point(seconds(ts
.tv_sec
) + nanoseconds(ts
.tv_nsec
));
275 // So that our subtractions produce negative spans rather than
276 // arithmetic underflow.
278 template<typename Rep1
, typename Period1
, typename Rep2
,
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
,
285 std::chrono::duration
<typename
std::make_signed
<Rep2
>::type
,
289 typename
std::common_type
<
290 std::chrono::duration
<typename
std::make_signed
<Rep1
>::type
,
292 std::chrono::duration
<typename
std::make_signed
<Rep2
>::type
,
294 return srep(srep(minuend
).count() - srep(subtrahend
).count());
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());
312 } // namespace time_detail
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
319 using time_detail::timespan
;
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
;
325 // High-resolution real-time clock
326 using time_detail::real_clock
;
328 // Low-resolution but preusmably faster real-time clock
329 using time_detail::coarse_real_clock
;
332 // High-resolution monotonic clock
333 using time_detail::mono_clock
;
335 // Low-resolution but, I would hope or there's no point, faster
337 using time_detail::coarse_mono_clock
;
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.
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.
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.
353 // Actual wall-clock times
354 typedef real_clock::time_point real_time
;
355 typedef coarse_real_clock::time_point coarse_real_time
;
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
;
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
);
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
;
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
>
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
));
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
<
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
));
407 inline timespan
make_timespan(const double d
) {
408 return std::chrono::duration_cast
<timespan
>(
409 std::chrono::duration
<double>(d
));
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
);
423 // The way std::chrono handles the return type of subtraction is not
424 // wonderful. The difference of two unsigned types SHOULD be signed.
427 inline signedspan
operator -(real_time minuend
,
428 real_time subtrahend
) {
429 return time_detail::difference(minuend
, subtrahend
);
432 inline signedspan
operator -(coarse_real_time minuend
,
433 coarse_real_time subtrahend
) {
434 return time_detail::difference(minuend
, subtrahend
);
437 inline signedspan
operator -(mono_time minuend
,
438 mono_time subtrahend
) {
439 return time_detail::difference(minuend
, subtrahend
);
442 inline signedspan
operator -(coarse_mono_time minuend
,
443 coarse_mono_time subtrahend
) {
444 return time_detail::difference(minuend
, subtrahend
);
448 // We could add specializations of time_point - duration and
449 // time_point + duration to assert on overflow, but I don't think we
454 // We need these definitions to be able to hande ::encode/::decode on
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
;
468 template<typename Clock
, typename Duration
>
469 void decode(std::chrono::time_point
<Clock
, Duration
>& t
,
470 bufferlist::iterator
& p
) {
475 struct timespec ts
= {
476 static_cast<time_t>(s
),
477 static_cast<long int>(ns
)};
479 t
= Clock::from_timespec(ts
);
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 // > >)
488 template<typename Clock
, typename Duration
>
489 void encode(const time_point
<Clock
, Duration
>& t
,
490 ceph::bufferlist
&bl
) {
494 template<typename Clock
, typename Duration
>
495 void decode(time_point
<Clock
, Duration
>& t
, bufferlist::iterator
&p
) {
498 } // namespace chrono
500 // An overload of our own
502 inline timespan
abs(signedspan z
) {
503 return z
> signedspan::zero() ?
504 std::chrono::duration_cast
<timespan
>(z
) :
505 timespan(-z
.count());
510 #endif // COMMON_CEPH_TIME_H