#include <optional>
#include <sys/time.h>
-#include "include/ceph_assert.h"
-
#if defined(__APPLE__)
#include <sys/_types/_timespec.h>
struct ceph_timespec;
namespace ceph {
-namespace time_detail {
-using std::chrono::duration_cast;
-using std::chrono::seconds;
-using std::chrono::microseconds;
-using std::chrono::nanoseconds;
// Currently we use a 64-bit count of nanoseconds.
// We could, if we wished, use a struct holding a uint64_t count
// want.
typedef uint64_t rep;
-// A concrete duration, unsigned. The timespan Ceph thinks in.
+
+// duration is the concrete time representation for our code in the
+// case that we are only interested in durations between now and the
+// future. Using it means we don't have to have EVERY function that
+// deals with a duration be a template. We can do so for user-facing
+// APIs, however.
typedef std::chrono::duration<rep, std::nano> timespan;
// Like the above but signed.
typedef int64_t signed_rep;
+// Similar to the above but for durations that can specify
+// differences between now and a time point in the past.
typedef std::chrono::duration<signed_rep, std::nano> signedspan;
// We define our own clocks so we can have our choice of all time
// One potential issue is that we should accept system_clock
// timepoints in user-facing APIs alongside (or instead of)
// ceph::real_clock times.
+
+// High-resolution real-time clock
class real_clock {
public:
typedef timespan duration;
static time_point to_system_time_point(
const std::chrono::time_point<Clock, Duration>& t) {
return time_point(seconds(Clock::to_time_t(t)) +
- duration_cast<duration>(t.time_since_epoch() %
- seconds(1)));
+ std::chrono::duration_cast<duration>(t.time_since_epoch() %
+ std::chrono::seconds(1)));
}
template<typename Clock, typename Duration>
static std::chrono::time_point<Clock, Duration> to_system_time_point(
const time_point& t) {
return (Clock::from_time_t(to_time_t(t)) +
- duration_cast<Duration>(t.time_since_epoch() % seconds(1)));
+ std::chrono::duration_cast<Duration>(t.time_since_epoch() %
+ std::chrono::seconds(1)));
}
static time_t to_time_t(const time_point& t) noexcept {
- return duration_cast<seconds>(t.time_since_epoch()).count();
+ return std::chrono::duration_cast<std::chrono::seconds>(t.time_since_epoch()).count();
}
static time_point from_time_t(const time_t& t) noexcept {
- return time_point(seconds(t));
+ return time_point(std::chrono::seconds(t));
}
static void to_timespec(const time_point& t, struct timespec& ts) {
ts.tv_sec = to_time_t(t);
- ts.tv_nsec = (t.time_since_epoch() % seconds(1)).count();
+ ts.tv_nsec = (t.time_since_epoch() % std::chrono::seconds(1)).count();
}
static struct timespec to_timespec(const time_point& t) {
struct timespec ts;
return ts;
}
static time_point from_timespec(const struct timespec& ts) {
- return time_point(seconds(ts.tv_sec) + nanoseconds(ts.tv_nsec));
+ return time_point(std::chrono::seconds(ts.tv_sec) +
+ std::chrono::nanoseconds(ts.tv_nsec));
}
static void to_ceph_timespec(const time_point& t,
static void to_timeval(const time_point& t, struct timeval& tv) {
tv.tv_sec = to_time_t(t);
- tv.tv_usec = duration_cast<microseconds>(t.time_since_epoch() %
- seconds(1)).count();
+ tv.tv_usec = std::chrono::duration_cast<std::chrono::microseconds>(
+ t.time_since_epoch() % std::chrono::seconds(1)).count();
}
static struct timeval to_timeval(const time_point& t) {
struct timeval tv;
return tv;
}
static time_point from_timeval(const struct timeval& tv) {
- return time_point(seconds(tv.tv_sec) + microseconds(tv.tv_usec));
+ return time_point(std::chrono::seconds(tv.tv_sec) +
+ std::chrono::microseconds(tv.tv_usec));
}
static double to_double(const time_point& t) {
return std::chrono::duration<double>(t.time_since_epoch()).count();
}
static time_point from_double(const double d) {
- return time_point(duration_cast<duration>(
+ return time_point(std::chrono::duration_cast<duration>(
std::chrono::duration<double>(d)));
}
};
+// Low-resolution but preusmably faster real-time clock
class coarse_real_clock {
public:
typedef timespan duration;
}
static time_t to_time_t(const time_point& t) noexcept {
- return duration_cast<seconds>(t.time_since_epoch()).count();
+ return std::chrono::duration_cast<std::chrono::seconds>(
+ t.time_since_epoch()).count();
}
static time_point from_time_t(const time_t t) noexcept {
- return time_point(seconds(t));
+ return time_point(std::chrono::seconds(t));
}
static void to_timespec(const time_point& t, struct timespec& ts) {
ts.tv_sec = to_time_t(t);
- ts.tv_nsec = (t.time_since_epoch() % seconds(1)).count();
+ ts.tv_nsec = (t.time_since_epoch() % std::chrono::seconds(1)).count();
}
static struct timespec to_timespec(const time_point& t) {
struct timespec ts;
return ts;
}
static time_point from_timespec(const struct timespec& ts) {
- return time_point(seconds(ts.tv_sec) + nanoseconds(ts.tv_nsec));
+ return time_point(std::chrono::seconds(ts.tv_sec) +
+ std::chrono::nanoseconds(ts.tv_nsec));
}
static void to_ceph_timespec(const time_point& t,
static void to_timeval(const time_point& t, struct timeval& tv) {
tv.tv_sec = to_time_t(t);
- tv.tv_usec = duration_cast<microseconds>(t.time_since_epoch() %
- seconds(1)).count();
+ tv.tv_usec = std::chrono::duration_cast<std::chrono::microseconds>(
+ t.time_since_epoch() % std::chrono::seconds(1)).count();
}
static struct timeval to_timeval(const time_point& t) {
struct timeval tv;
return tv;
}
static time_point from_timeval(const struct timeval& tv) {
- return time_point(seconds(tv.tv_sec) + microseconds(tv.tv_usec));
+ return time_point(std::chrono::seconds(tv.tv_sec) +
+ std::chrono::microseconds(tv.tv_usec));
}
static double to_double(const time_point& t) {
return std::chrono::duration<double>(t.time_since_epoch()).count();
}
static time_point from_double(const double d) {
- return time_point(duration_cast<duration>(
+ return time_point(std::chrono::duration_cast<duration>(
std::chrono::duration<double>(d)));
}
};
+// High-resolution monotonic clock
class mono_clock {
public:
typedef timespan duration;
static time_point now() noexcept {
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
- return time_point(seconds(ts.tv_sec) + nanoseconds(ts.tv_nsec));
+ return time_point(std::chrono::seconds(ts.tv_sec) +
+ std::chrono::nanoseconds(ts.tv_nsec));
}
static bool is_zero(const time_point& t) {
static time_point zero() {
return time_point::min();
}
-
- // A monotonic clock's timepoints are only meaningful to the
- // computer on which they were generated. Thus having an
- // optional skew is meaningless.
};
+// Low-resolution but, I would hope or there's no point, faster
+// monotonic clock
class coarse_mono_clock {
public:
typedef timespan duration;
#warning Falling back to CLOCK_MONOTONIC, may be slow.
clock_gettime(CLOCK_MONOTONIC, &ts);
#endif
- return time_point(seconds(ts.tv_sec) + nanoseconds(ts.tv_nsec));
+ return time_point(std::chrono::seconds(ts.tv_sec) +
+ std::chrono::nanoseconds(ts.tv_nsec));
}
static bool is_zero(const time_point& t) {
}
};
+namespace time_detail {
// So that our subtractions produce negative spans rather than
// arithmetic underflow.
-namespace {
template<typename Rep1, typename Period1, typename Rep2,
typename Period2>
inline auto difference(std::chrono::duration<Rep1, Period1> minuend,
subtrahend.time_since_epoch());
}
}
-} // namespace time_detail
-
- // duration is the concrete time representation for our code in the
- // case that we are only interested in durations between now and the
- // future. Using it means we don't have to have EVERY function that
- // deals with a duration be a template. We can do so for user-facing
- // APIs, however.
-using time_detail::timespan;
-
-// Similar to the above but for durations that can specify
-// differences between now and a time point in the past.
-using time_detail::signedspan;
-
-// High-resolution real-time clock
-using time_detail::real_clock;
-
-// Low-resolution but preusmably faster real-time clock
-using time_detail::coarse_real_clock;
-
-
-// High-resolution monotonic clock
-using time_detail::mono_clock;
-
-// Low-resolution but, I would hope or there's no point, faster
-// monotonic clock
-using time_detail::coarse_mono_clock;
// Please note that the coarse clocks are disjoint. You cannot
// subtract a real_clock timepoint from a coarse_real_clock
ceil(timepoint.time_since_epoch(), precision));
}
-namespace {
inline timespan make_timespan(const double d) {
return std::chrono::duration_cast<timespan>(
std::chrono::duration<double>(d));
inline std::optional<timespan> maybe_timespan(const double d) {
return d ? std::make_optional(make_timespan(d)) : std::nullopt;
}
-}
std::ostream& operator<<(std::ostream& m, const timespan& t);
template<typename Clock,
// The way std::chrono handles the return type of subtraction is not
// wonderful. The difference of two unsigned types SHOULD be signed.
-namespace {
inline signedspan operator -(real_time minuend,
real_time subtrahend) {
return time_detail::difference(minuend, subtrahend);
coarse_mono_time subtrahend) {
return time_detail::difference(minuend, subtrahend);
}
-}
// We could add specializations of time_point - duration and
// time_point + duration to assert on overflow, but I don't think we
// should.
-
-
inline timespan abs(signedspan z) {
return z > signedspan::zero() ?
std::chrono::duration_cast<timespan>(z) :