1 /* 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 // System independant wrapper for polling elapsed time in ms and us. 12 // The implementation works in the tick domain which can be mapped over to the 13 // time domain. 14 #ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_TICK_UTIL_H_ 15 #define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_TICK_UTIL_H_ 16 17 #if _WIN32 18 // Note: The Windows header must always be included before mmsystem.h 19 #include <windows.h> 20 #include <mmsystem.h> 21 #elif WEBRTC_LINUX 22 #include <time.h> 23 #elif WEBRTC_MAC 24 #include <mach/mach_time.h> 25 #include <string.h> 26 #else 27 #include <sys/time.h> 28 #include <time.h> 29 #endif 30 31 #include "webrtc/typedefs.h" 32 33 namespace webrtc { 34 35 class TickInterval; 36 37 // Class representing the current time. 38 class TickTime { 39 public: 40 TickTime(); 41 explicit TickTime(int64_t ticks); 42 43 // Current time in the tick domain. 44 static TickTime Now(); 45 46 // Now in the time domain in ms. 47 static int64_t MillisecondTimestamp(); 48 49 // Now in the time domain in us. 50 static int64_t MicrosecondTimestamp(); 51 52 // Returns the number of ticks in the tick domain. 53 int64_t Ticks() const; 54 55 static int64_t MillisecondsToTicks(const int64_t ms); 56 57 static int64_t TicksToMilliseconds(const int64_t ticks); 58 59 // Returns a TickTime that is ticks later than the passed TickTime. 60 friend TickTime operator+(const TickTime lhs, const int64_t ticks); 61 TickTime& operator+=(const int64_t& ticks); 62 63 // Returns a TickInterval that is the difference in ticks beween rhs and lhs. 64 friend TickInterval operator-(const TickTime& lhs, const TickTime& rhs); 65 66 // Call to engage the fake clock. This is useful for tests since relying on 67 // a real clock often makes the test flaky. 68 static void UseFakeClock(int64_t start_millisecond); 69 70 // Advance the fake clock. Must be called after UseFakeClock. 71 static void AdvanceFakeClock(int64_t milliseconds); 72 73 private: 74 static int64_t QueryOsForTicks(); 75 76 static bool use_fake_clock_; 77 static int64_t fake_ticks_; 78 79 int64_t ticks_; 80 }; 81 82 // Represents a time delta in ticks. 83 class TickInterval { 84 public: 85 TickInterval(); 86 87 int64_t Milliseconds() const; 88 int64_t Microseconds() const; 89 90 // Returns the sum of two TickIntervals as a TickInterval. 91 friend TickInterval operator+(const TickInterval& lhs, 92 const TickInterval& rhs); 93 TickInterval& operator+=(const TickInterval& rhs); 94 95 // Returns a TickInterval corresponding to rhs - lhs. 96 friend TickInterval operator-(const TickInterval& lhs, 97 const TickInterval& rhs); 98 TickInterval& operator-=(const TickInterval& rhs); 99 100 friend bool operator>(const TickInterval& lhs, const TickInterval& rhs); 101 friend bool operator<=(const TickInterval& lhs, const TickInterval& rhs); 102 friend bool operator<(const TickInterval& lhs, const TickInterval& rhs); 103 friend bool operator>=(const TickInterval& lhs, const TickInterval& rhs); 104 105 private: 106 explicit TickInterval(int64_t interval); 107 108 friend class TickTime; 109 friend TickInterval operator-(const TickTime& lhs, const TickTime& rhs); 110 111 private: 112 int64_t interval_; 113 }; 114 115 inline TickInterval operator+(const TickInterval& lhs, 116 const TickInterval& rhs) { 117 return TickInterval(lhs.interval_ + rhs.interval_); 118 } 119 120 inline TickInterval operator-(const TickInterval& lhs, 121 const TickInterval& rhs) { 122 return TickInterval(lhs.interval_ - rhs.interval_); 123 } 124 125 inline TickInterval operator-(const TickTime& lhs, const TickTime& rhs) { 126 return TickInterval(lhs.ticks_ - rhs.ticks_); 127 } 128 129 inline TickTime operator+(const TickTime lhs, const int64_t ticks) { 130 TickTime time = lhs; 131 time.ticks_ += ticks; 132 return time; 133 } 134 135 inline bool operator>(const TickInterval& lhs, const TickInterval& rhs) { 136 return lhs.interval_ > rhs.interval_; 137 } 138 139 inline bool operator<=(const TickInterval& lhs, const TickInterval& rhs) { 140 return lhs.interval_ <= rhs.interval_; 141 } 142 143 inline bool operator<(const TickInterval& lhs, const TickInterval& rhs) { 144 return lhs.interval_ <= rhs.interval_; 145 } 146 147 inline bool operator>=(const TickInterval& lhs, const TickInterval& rhs) { 148 return lhs.interval_ >= rhs.interval_; 149 } 150 151 inline TickTime::TickTime() 152 : ticks_(0) { 153 } 154 155 inline TickTime::TickTime(int64_t ticks) 156 : ticks_(ticks) { 157 } 158 159 inline TickTime TickTime::Now() { 160 if (use_fake_clock_) 161 return TickTime(fake_ticks_); 162 else 163 return TickTime(QueryOsForTicks()); 164 } 165 166 inline int64_t TickTime::MillisecondTimestamp() { 167 int64_t ticks = TickTime::Now().Ticks(); 168 #if _WIN32 169 #ifdef USE_QUERY_PERFORMANCE_COUNTER 170 LARGE_INTEGER qpfreq; 171 QueryPerformanceFrequency(&qpfreq); 172 return (ticks * 1000) / qpfreq.QuadPart; 173 #else 174 return ticks; 175 #endif 176 #elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC) 177 return ticks / 1000000LL; 178 #else 179 return ticks / 1000LL; 180 #endif 181 } 182 183 inline int64_t TickTime::MicrosecondTimestamp() { 184 int64_t ticks = TickTime::Now().Ticks(); 185 #if _WIN32 186 #ifdef USE_QUERY_PERFORMANCE_COUNTER 187 LARGE_INTEGER qpfreq; 188 QueryPerformanceFrequency(&qpfreq); 189 return (ticks * 1000) / (qpfreq.QuadPart / 1000); 190 #else 191 return ticks * 1000LL; 192 #endif 193 #elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC) 194 return ticks / 1000LL; 195 #else 196 return ticks; 197 #endif 198 } 199 200 inline int64_t TickTime::Ticks() const { 201 return ticks_; 202 } 203 204 inline int64_t TickTime::MillisecondsToTicks(const int64_t ms) { 205 #if _WIN32 206 #ifdef USE_QUERY_PERFORMANCE_COUNTER 207 LARGE_INTEGER qpfreq; 208 QueryPerformanceFrequency(&qpfreq); 209 return (qpfreq.QuadPart * ms) / 1000; 210 #else 211 return ms; 212 #endif 213 #elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC) 214 return ms * 1000000LL; 215 #else 216 return ms * 1000LL; 217 #endif 218 } 219 220 inline int64_t TickTime::TicksToMilliseconds(const int64_t ticks) { 221 #if _WIN32 222 #ifdef USE_QUERY_PERFORMANCE_COUNTER 223 LARGE_INTEGER qpfreq; 224 QueryPerformanceFrequency(&qpfreq); 225 return (ticks * 1000) / qpfreq.QuadPart; 226 #else 227 return ticks; 228 #endif 229 #elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC) 230 return ticks / 1000000LL; 231 #else 232 return ticks / 1000LL; 233 #endif 234 } 235 236 inline TickTime& TickTime::operator+=(const int64_t& ticks) { 237 ticks_ += ticks; 238 return *this; 239 } 240 241 inline TickInterval::TickInterval() : interval_(0) { 242 } 243 244 inline TickInterval::TickInterval(const int64_t interval) 245 : interval_(interval) { 246 } 247 248 inline int64_t TickInterval::Milliseconds() const { 249 #if _WIN32 250 #ifdef USE_QUERY_PERFORMANCE_COUNTER 251 LARGE_INTEGER qpfreq; 252 QueryPerformanceFrequency(&qpfreq); 253 return (interval_ * 1000) / qpfreq.QuadPart; 254 #else 255 // interval_ is in ms 256 return interval_; 257 #endif 258 #elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC) 259 // interval_ is in ns 260 return interval_ / 1000000; 261 #else 262 // interval_ is usecs 263 return interval_ / 1000; 264 #endif 265 } 266 267 inline int64_t TickInterval::Microseconds() const { 268 #if _WIN32 269 #ifdef USE_QUERY_PERFORMANCE_COUNTER 270 LARGE_INTEGER qpfreq; 271 QueryPerformanceFrequency(&qpfreq); 272 return (interval_ * 1000000) / qpfreq.QuadPart; 273 #else 274 // interval_ is in ms 275 return interval_ * 1000LL; 276 #endif 277 #elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC) 278 // interval_ is in ns 279 return interval_ / 1000; 280 #else 281 // interval_ is usecs 282 return interval_; 283 #endif 284 } 285 286 inline TickInterval& TickInterval::operator+=(const TickInterval& rhs) { 287 interval_ += rhs.interval_; 288 return *this; 289 } 290 291 inline TickInterval& TickInterval::operator-=(const TickInterval& rhs) { 292 interval_ -= rhs.interval_; 293 return *this; 294 } 295 296 } // namespace webrtc 297 298 #endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_TICK_UTIL_H_ 299