• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
TickTime()151 inline TickTime::TickTime()
152     : ticks_(0) {
153 }
154 
TickTime(int64_t ticks)155 inline TickTime::TickTime(int64_t ticks)
156     : ticks_(ticks) {
157 }
158 
Now()159 inline TickTime TickTime::Now() {
160   if (use_fake_clock_)
161     return TickTime(fake_ticks_);
162   else
163     return TickTime(QueryOsForTicks());
164 }
165 
MillisecondTimestamp()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 
MicrosecondTimestamp()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 
Ticks()200 inline int64_t TickTime::Ticks() const {
201   return ticks_;
202 }
203 
MillisecondsToTicks(const int64_t ms)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 
TicksToMilliseconds(const int64_t ticks)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 
TickInterval()241 inline TickInterval::TickInterval() : interval_(0) {
242 }
243 
TickInterval(const int64_t interval)244 inline TickInterval::TickInterval(const int64_t interval)
245   : interval_(interval) {
246 }
247 
Milliseconds()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 
Microseconds()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