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