LogCabin
|
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 */