LogCabin
Core/Time.h
Go to the documentation of this file.
00001 /* Copyright (c) 2011-2012 Stanford University
00002  * Copyright (c) 2014-2015 Diego Ongaro
00003  *
00004  * Permission to use, copy, modify, and distribute this software for any
00005  * purpose with or without fee is hereby granted, provided that the above
00006  * copyright notice and this permission notice appear in all copies.
00007  *
00008  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR(S) DISCLAIM ALL WARRANTIES
00009  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
00010  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL AUTHORS BE LIABLE FOR
00011  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
00012  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
00013  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
00014  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
00015  */
00016 
00017 #include <cassert>
00018 #include <chrono>
00019 #include <iostream>
00020 #include <time.h>
00021 
00022 #include "Core/StringUtil.h"
00023 
00024 #ifndef LOGCABIN_CORE_TIME_H
00025 #define LOGCABIN_CORE_TIME_H
00026 
00027 namespace LogCabin {
00028 namespace Core {
00029 namespace Time {
00030 
00031 /**
00032  * Convert a C++11 time point into a POSIX timespec.
00033  * \param when
00034  *      Time point to convert.
00035  * \return
00036  *      Time in seconds and nanoseconds relative to the Clock's epoch.
00037  */
00038 template<typename Clock, typename Duration>
00039 struct timespec
00040 makeTimeSpec(const std::chrono::time_point<Clock, Duration>& when)
00041 {
00042     std::chrono::nanoseconds::rep nanosSinceEpoch =
00043         std::chrono::duration_cast<std::chrono::nanoseconds>(
00044            when.time_since_epoch()).count();
00045     struct timespec ts;
00046     ts.tv_sec  = nanosSinceEpoch / 1000000000L;
00047     ts.tv_nsec = nanosSinceEpoch % 1000000000L;
00048     // tv_nsec must always be in range [0, 1e9)
00049     if (nanosSinceEpoch < 0) {
00050         ts.tv_sec  -= 1;
00051         ts.tv_nsec += 1000000000L;
00052     }
00053     return ts;
00054 }
00055 
00056 /**
00057  * Wall clock in nanosecond granularity.
00058  * Wrapper around clock_gettime(CLOCK_REALTIME).
00059  * Usually, you'll want to access this through #SystemClock.
00060  *
00061  * This is preferred over std::chrono::system_clock for earlier libstdc++
00062  * versions, since those use only a microsecond granularity.
00063  */
00064 struct CSystemClock {
00065     typedef std::chrono::nanoseconds duration;
00066     typedef duration::rep rep;
00067     typedef duration::period period;
00068     typedef std::chrono::time_point<CSystemClock, duration> time_point;
00069 
00070     static const bool is_steady = false;
00071     static time_point now();
00072 };
00073 
00074 /**
00075  * The clock used by CSteadyClock. For now (2014), we can't use
00076  * CLOCK_MONOTONIC_RAW in condition variables since glibc doesn't support that,
00077  * so stick with CLOCK_MONOTONIC. This rate of this clock may change due to NTP
00078  * adjustments, but at least it won't jump.
00079  */
00080 const clockid_t STEADY_CLOCK_ID = CLOCK_MONOTONIC;
00081 
00082 /**
00083  * Monotonic clock in nanosecond granularity.
00084  * Wrapper around clock_gettime(STEADY_CLOCK_ID = CLOCK_MONOTONIC).
00085  * Usually, you'll want to access this through #SteadyClock.
00086  *
00087  * This is preferred over std::chrono::monotonic_clock and
00088  * std::chrono::steady_clock for earlier libstdc++ versions, since those use
00089  * are not actually monotonic (they're typedefed to system_clock).
00090  */
00091 struct CSteadyClock {
00092     typedef std::chrono::nanoseconds duration;
00093     typedef duration::rep rep;
00094     typedef duration::period period;
00095     typedef std::chrono::time_point<CSteadyClock, duration> time_point;
00096     static const bool is_steady = true;
00097 
00098     static time_point now();
00099 };
00100 
00101 
00102 /**
00103  * Reads the current time. This time may not correspond to wall time, depending
00104  * on the underlying BaseClock. This class gives unit tests a way to fake the
00105  * current time.
00106  */
00107 template<typename _BaseClock>
00108 struct MockableClock
00109 {
00110     typedef _BaseClock BaseClock;
00111     typedef typename BaseClock::duration duration;
00112     typedef typename BaseClock::rep rep;
00113     typedef typename BaseClock::period period;
00114     typedef typename BaseClock::time_point time_point;
00115 
00116     // libstdc++ 4.7 renamed monotonic_clock to steady_clock to conform with
00117     // C++11. This file doesn't use a BaseClock from libstdc++ before 4.8, so
00118     // it's ok to just assume is_steady is present.
00119     static const bool is_steady = BaseClock::is_steady;
00120 
00121     static time_point now() {
00122         if (useMockValue)
00123             return mockValue;
00124         else
00125             return BaseClock::now();
00126     }
00127 
00128     static bool useMockValue;
00129     static time_point mockValue;
00130 
00131     /// RAII class to mock out the clock and then restore it.
00132     struct Mocker {
00133         explicit Mocker(time_point value = now()) {
00134             assert(!useMockValue);
00135             useMockValue = true;
00136             mockValue = value;
00137         }
00138         ~Mocker() {
00139             useMockValue = false;
00140         }
00141     };
00142 };
00143 
00144 template<typename BaseClock>
00145 bool
00146 MockableClock<BaseClock>::useMockValue = false;
00147 
00148 template<typename BaseClock>
00149 typename MockableClock<BaseClock>::time_point
00150 MockableClock<BaseClock>::mockValue;
00151 
00152 /**
00153  * The best available clock on this system for uses where a steady, monotonic
00154  * clock is desired.
00155  */
00156 // libstdc++ 4.7 renamed monotonic_clock to steady_clock to conform with C++11.
00157 // libstdc++ 4.8 seems to be the first version where std::chrono::steady_clock
00158 // is usable with nanosecond granularity.
00159 // Clang with libstdc++ gives us no way to check the version,
00160 // so we just use CSteadyClock in that case.
00161 // Clang with libc++ is known not to work at _LIBCPP_VERSION 1101 and hasn't
00162 // been tried with other versions (use CSteadyClock).
00163 #if __clang__ || (__GNUC__ == 4 && __GNUC_MINOR__ < 8)
00164 typedef MockableClock<CSteadyClock> SteadyClock;
00165 #else
00166 typedef MockableClock<std::chrono::steady_clock> SteadyClock;
00167 #endif
00168 
00169 /**
00170  * A clock that reads wall time and is affected by NTP adjustments.
00171  */
00172 // libstdc++ 4.8 seems to be the first version where std::chrono::system_clock
00173 // has nanosecond granularity.
00174 // Clang with libstdc++ gives us no way to check the version,
00175 // so we just use CSystemClock in that case.
00176 // Clang with libc++ is known not to work at _LIBCPP_VERSION 1101 and hasn't
00177 // been tried with other versions (use CSteadyClock).
00178 #if __clang__ || (__GNUC__ == 4 && __GNUC_MINOR__ < 8)
00179 typedef MockableClock<CSystemClock> SystemClock;
00180 #else
00181 typedef MockableClock<std::chrono::system_clock> SystemClock;
00182 #endif
00183 
00184 /**
00185  * Convert a human-readable description of a time duration into a number of
00186  * nanoseconds.
00187  * \param description
00188  *      Something like 10, 10s, -200ms, 3us, or -999ns. With no units, defaults
00189  *      to seconds. May be negative.
00190  *      Allowed units:
00191  *          ns, nanosecond(s),
00192  *          ms, millisecond(s),
00193  *          s, second(s),
00194  *          min, minute(s),
00195  *          h, hr, hour(s),
00196  *          d, day(s),
00197  *          w, wk, week(s),
00198  *          mo, month(s),
00199  *          y, yr, year(s).
00200  * \return
00201  *      Number of nanoseconds, capped to the range of a signed 64-bit integer.
00202  * \throw std::runtime_error
00203  *      If description could not be parsed successfully.
00204  */
00205 int64_t parseSignedDuration(const std::string& description);
00206 
00207 /**
00208  * Convert a human-readable description of a time duration into a number of
00209  * nanoseconds.
00210  * \param description
00211  *      Something like 10, 10s, 200ms, 3us, or 999ns. With no units, defaults
00212  *      to seconds. May not be negative.
00213  *      Allowed units:
00214  *          ns, nanosecond(s),
00215  *          ms, millisecond(s),
00216  *          s, second(s),
00217  *          min, minute(s),
00218  *          h, hr, hour(s),
00219  *          d, day(s),
00220  *          w, wk, week(s),
00221  *          mo, month(s),
00222  *          y, yr, year(s).
00223  * \return
00224  *      Number of nanoseconds, capped on the high end to the range of a signed
00225  *      64-bit integer.
00226  * \throw std::runtime_error
00227  *      If description could not be parsed successfully.
00228  */
00229 uint64_t parseNonNegativeDuration(const std::string& description);
00230 
00231 /**
00232  * Read the CPU's cycle counter.
00233  * This is useful for benchmarking.
00234  */
00235 static __inline __attribute__((always_inline))
00236 uint64_t
00237 rdtsc()
00238 {
00239 #if defined(__i386) || defined(__x86_64__)
00240     uint32_t lo, hi;
00241     __asm__ __volatile__("rdtsc" : "=a" (lo), "=d" (hi));
00242     return ((uint64_t(hi) << 32) | lo);
00243 #elif defined(__powerpc64__)
00244     return (__builtin_ppc_get_timebase());
00245 #else
00246 #error "Unsupported platform."
00247 #endif
00248 }
00249 
00250 /**
00251  * Block the calling thread until the given time.
00252  */
00253 void sleep(SteadyClock::time_point wake);
00254 
00255 /**
00256  * Block the calling thread for the given duration.
00257  */
00258 void sleep(std::chrono::nanoseconds duration);
00259 
00260 /**
00261  * Used to convert one or more SteadyClock::time_point values into values of
00262  * the SystemClock. Using the same instance for many conversions is more
00263  * efficient, since the current time only has to be queried once for each clock
00264  * in the constructor.
00265  */
00266 class SteadyTimeConverter {
00267   public:
00268     /**
00269      * Constructor.
00270      */
00271     SteadyTimeConverter();
00272 
00273     /**
00274      * Return the given time according the system clock (assuming no time
00275      * jumps).
00276      */
00277     SystemClock::time_point
00278     convert(SteadyClock::time_point when);
00279 
00280     /**
00281      * Return the given time in nanoseconds since the Unix epoch according the
00282      * system clock (assuming no time jumps).
00283      */
00284     int64_t
00285     unixNanos(SteadyClock::time_point when);
00286 
00287   private:
00288     /**
00289      * Time this object was constructed according to the SteadyClock.
00290      */
00291     SteadyClock::time_point steadyNow;
00292     /**
00293      * Time this object was constructed according to the SystemClock.
00294      */
00295     SystemClock::time_point systemNow;
00296 };
00297 
00298 } // namespace LogCabin::Core::Time
00299 } // namespace LogCabin::Core
00300 } // namespace LogCabin
00301 
00302 namespace std {
00303 
00304 // The following set of functions prints duration values in a human-friendly
00305 // way, including their units.
00306 
00307 std::ostream&
00308 operator<<(std::ostream& os,
00309            const std::chrono::nanoseconds& duration);
00310 std::ostream&
00311 operator<<(std::ostream& os,
00312            const std::chrono::microseconds& duration);
00313 std::ostream&
00314 operator<<(std::ostream& os,
00315            const std::chrono::milliseconds& duration);
00316 std::ostream&
00317 operator<<(std::ostream& os,
00318            const std::chrono::seconds& duration);
00319 std::ostream&
00320 operator<<(std::ostream& os,
00321            const std::chrono::minutes& duration);
00322 std::ostream&
00323 operator<<(std::ostream& os,
00324            const std::chrono::hours& duration);
00325 
00326 /**
00327  * Prints std::time_point values in a way that is useful for unit tests.
00328  */
00329 template<typename Clock, typename Duration>
00330 std::ostream&
00331 operator<<(std::ostream& os,
00332            const std::chrono::time_point<Clock, Duration>& timePoint) {
00333     typedef std::chrono::time_point<Clock, Duration> TimePoint;
00334     using LogCabin::Core::StringUtil::format;
00335 
00336     if (timePoint == TimePoint::min())
00337         return os << "TimePoint::min()";
00338     if (timePoint == TimePoint::max())
00339         return os << "TimePoint::max()";
00340 
00341     struct timespec ts = LogCabin::Core::Time::makeTimeSpec(timePoint);
00342     return os << format("%ld.%09ld", ts.tv_sec, ts.tv_nsec);
00343 }
00344 
00345 } // namespace std
00346 
00347 #endif /* LOGCABIN_CORE_TIME_H */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines