Home | History | Annotate | Download | only in interface
      1 /*
      2  *  Copyright (c) 2011 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 #include <windows.h>
     19 #include <mmsystem.h>
     20 #elif WEBRTC_LINUX
     21 #include <ctime>
     22 #else
     23 #include <sys/time.h>
     24 #include <time.h>
     25 #endif
     26 
     27 #include "typedefs.h"
     28 
     29 namespace webrtc {
     30 class TickInterval;
     31 
     32 class TickTime
     33 {
     34 public:
     35     // Current time in the tick domain.
     36     static TickTime Now();
     37 
     38     // Now in the time domain in ms.
     39     static WebRtc_Word64 MillisecondTimestamp();
     40 
     41     // Now in the time domain in us.
     42     static WebRtc_Word64 MicrosecondTimestamp();
     43 
     44     WebRtc_Word64 Ticks() const;
     45 
     46     static WebRtc_Word64 MillisecondsToTicks(const WebRtc_Word64 ms);
     47 
     48     static WebRtc_Word64 TicksToMilliseconds(const WebRtc_Word64 ticks);
     49 
     50     // Returns a TickTime that is ticks later than the passed TickTime
     51     friend TickTime operator+(const TickTime lhs, const WebRtc_Word64 ticks);
     52     TickTime& operator+=(const WebRtc_Word64& rhs);
     53 
     54 
     55     // Returns a TickInterval that is the difference in ticks beween rhs and lhs
     56     friend TickInterval operator-(const TickTime& lhs, const TickTime& rhs);
     57 private:
     58     WebRtc_Word64 _ticks;
     59 };
     60 
     61 class TickInterval
     62 {
     63 public:
     64     TickInterval();
     65 
     66     WebRtc_Word64 Milliseconds() const;
     67     WebRtc_Word64 Microseconds() const;
     68 
     69     // Returns the sum of two TickIntervals as a TickInterval
     70     friend TickInterval operator+(const TickInterval& lhs,
     71                                   const TickInterval& rhs);
     72     TickInterval& operator-=(const TickInterval& rhs);
     73 
     74     // Returns a TickInterval corresponding to rhs - lhs
     75     friend TickInterval operator-(const TickInterval& lhs,
     76                                   const TickInterval& rhs);
     77     TickInterval& operator+=(const TickInterval& rhs);
     78 
     79     friend bool operator>(const TickInterval& lhs, const TickInterval& rhs);
     80     friend bool operator<=(const TickInterval& lhs, const TickInterval& rhs);
     81     friend bool operator<(const TickInterval& lhs, const TickInterval& rhs);
     82     friend bool operator>=(const TickInterval& lhs, const TickInterval& rhs);
     83 
     84 private:
     85     TickInterval(WebRtc_Word64 interval);
     86 
     87     friend class TickTime;
     88     friend TickInterval operator-(const TickTime& lhs, const TickTime& rhs);
     89 
     90 private:
     91     WebRtc_Word64 _interval;
     92 };
     93 
     94 inline TickInterval operator+(const TickInterval& lhs, const TickInterval& rhs)
     95 {
     96     return TickInterval(lhs._interval + rhs._interval);
     97 }
     98 
     99 inline TickInterval operator-(const TickInterval& lhs, const TickInterval& rhs)
    100 {
    101     return TickInterval(lhs._interval - rhs._interval);
    102 }
    103 
    104 inline TickInterval operator-(const TickTime& lhs,const TickTime& rhs)
    105 {
    106     return TickInterval(lhs._ticks - rhs._ticks);
    107 }
    108 
    109 inline TickTime operator+(const TickTime lhs, const WebRtc_Word64 ticks)
    110 {
    111     TickTime time = lhs;
    112     time._ticks += ticks;
    113     return time;
    114 }
    115 inline bool operator>(const TickInterval& lhs, const TickInterval& rhs)
    116 {
    117     return lhs._interval > rhs._interval;
    118 }
    119 inline bool operator<=(const TickInterval& lhs, const TickInterval& rhs)
    120 {
    121     return lhs._interval <= rhs._interval;
    122 }
    123 inline bool operator<(const TickInterval& lhs, const TickInterval& rhs)
    124 {
    125     return lhs._interval <= rhs._interval;
    126 }
    127 inline bool operator>=(const TickInterval& lhs, const TickInterval& rhs)
    128 {
    129     return lhs._interval >= rhs._interval;
    130 }
    131 
    132 inline TickTime TickTime::Now()
    133 {
    134     TickTime result;
    135 #if _WIN32
    136     #ifdef USE_QUERY_PERFORMANCE_COUNTER
    137         // QueryPerformanceCounter returns the value from the TSC which is
    138         // incremented at the CPU frequency. The algorithm used requires
    139         // the CPU frequency to be constant. Technology like speed stepping
    140         // which has variable CPU frequency will therefore yield unpredictable,
    141         // incorrect time estimations.
    142         LARGE_INTEGER qpcnt;
    143         QueryPerformanceCounter(&qpcnt);
    144         result._ticks = qpcnt.QuadPart;
    145     #else
    146         static volatile LONG lastTimeGetTime = 0;
    147         static volatile WebRtc_Word64 numWrapTimeGetTime = 0;
    148         volatile LONG* lastTimeGetTimePtr = &lastTimeGetTime;
    149         DWORD now = timeGetTime();
    150         // Atomically update the last gotten time
    151         DWORD old = InterlockedExchange(lastTimeGetTimePtr, now);
    152         if(now < old)
    153         {
    154             // If now is earlier than old, there may have been a race between
    155             // threads.
    156             // 0x0fffffff ~3.1 days, the code will not take that long to execute
    157             // so it must have been a wrap around.
    158             if(old > 0xf0000000 && now < 0x0fffffff)
    159             {
    160                 numWrapTimeGetTime++;
    161             }
    162         }
    163         result._ticks = now + (numWrapTimeGetTime<<32);
    164     #endif
    165 #elif defined(WEBRTC_LINUX)
    166     struct timespec ts;
    167     #ifdef WEBRTC_CLOCK_TYPE_REALTIME
    168         clock_gettime(CLOCK_REALTIME, &ts);
    169     #else
    170         clock_gettime(CLOCK_MONOTONIC, &ts);
    171     #endif
    172     result._ticks = 1000000000LL * static_cast<WebRtc_Word64>(ts.tv_sec) + static_cast<WebRtc_Word64>(ts.tv_nsec);
    173 #else
    174     struct timeval tv;
    175     gettimeofday(&tv, NULL);
    176     result._ticks = 1000000LL * static_cast<WebRtc_Word64>(tv.tv_sec) + static_cast<WebRtc_Word64>(tv.tv_usec);
    177 #endif
    178     return result;
    179 }
    180 
    181 inline WebRtc_Word64 TickTime::MillisecondTimestamp()
    182 {
    183     TickTime now = TickTime::Now();
    184 #if _WIN32
    185     #ifdef USE_QUERY_PERFORMANCE_COUNTER
    186         LARGE_INTEGER qpfreq;
    187         QueryPerformanceFrequency(&qpfreq);
    188         return (now._ticks * 1000) / qpfreq.QuadPart;
    189     #else
    190         return now._ticks;
    191     #endif
    192 #elif WEBRTC_LINUX
    193     return now._ticks / 1000000LL;
    194 #else
    195     return now._ticks / 1000LL;
    196 #endif
    197 }
    198 
    199 inline WebRtc_Word64 TickTime::MicrosecondTimestamp()
    200 {
    201     TickTime now = TickTime::Now();
    202 
    203 #if _WIN32
    204     #ifdef USE_QUERY_PERFORMANCE_COUNTER
    205         LARGE_INTEGER qpfreq;
    206         QueryPerformanceFrequency(&qpfreq);
    207         return (now._ticks * 1000) / (qpfreq.QuadPart/1000);
    208     #else
    209         return now._ticks *1000LL;
    210     #endif
    211 #elif WEBRTC_LINUX
    212     return now._ticks / 1000LL;
    213 #else
    214     return now._ticks;
    215 #endif
    216 }
    217 
    218 inline WebRtc_Word64 TickTime::Ticks() const
    219 {
    220     return _ticks;
    221 }
    222 
    223 inline WebRtc_Word64 TickTime::MillisecondsToTicks(const WebRtc_Word64 ms)
    224 {
    225 #if _WIN32
    226     #ifdef USE_QUERY_PERFORMANCE_COUNTER
    227         LARGE_INTEGER qpfreq;
    228         QueryPerformanceFrequency(&qpfreq);
    229         return (qpfreq.QuadPart * ms) / 1000;
    230     #else
    231         return ms;
    232     #endif
    233 #elif WEBRTC_LINUX
    234     return ms * 1000000LL;
    235 #else
    236     return ms * 1000LL;
    237 #endif
    238 }
    239 
    240 inline WebRtc_Word64 TickTime::TicksToMilliseconds(const WebRtc_Word64 ticks)
    241 {
    242 #if _WIN32
    243     #ifdef USE_QUERY_PERFORMANCE_COUNTER
    244         LARGE_INTEGER qpfreq;
    245         QueryPerformanceFrequency(&qpfreq);
    246         return (ticks * 1000) / qpfreq.QuadPart;
    247     #else
    248         return ticks;
    249     #endif
    250 #elif WEBRTC_LINUX
    251     return ticks / 1000000LL;
    252 #else
    253     return ticks / 1000LL;
    254 #endif
    255 }
    256 
    257 inline TickTime& TickTime::operator+=(const WebRtc_Word64& ticks)
    258 {
    259     _ticks += ticks;
    260     return *this;
    261 }
    262 
    263 inline TickInterval::TickInterval() : _interval(0)
    264 {
    265 }
    266 
    267 inline TickInterval::TickInterval(const WebRtc_Word64 interval)
    268     : _interval(interval)
    269 {
    270 }
    271 
    272 inline WebRtc_Word64 TickInterval::Milliseconds() const
    273 {
    274 #if _WIN32
    275     #ifdef USE_QUERY_PERFORMANCE_COUNTER
    276         LARGE_INTEGER qpfreq;
    277         QueryPerformanceFrequency(&qpfreq);
    278         return (_interval * 1000) / qpfreq.QuadPart;
    279     #else
    280 	// _interval is in ms
    281         return _interval;
    282     #endif
    283 #elif WEBRTC_LINUX
    284     // _interval is in ns
    285     return _interval / 1000000;
    286 #else
    287     // _interval is usecs
    288     return _interval / 1000;
    289 #endif
    290 }
    291 
    292 inline WebRtc_Word64 TickInterval::Microseconds() const
    293 {
    294 #if _WIN32
    295     #ifdef USE_QUERY_PERFORMANCE_COUNTER
    296         LARGE_INTEGER qpfreq;
    297         QueryPerformanceFrequency(&qpfreq);
    298         return (_interval * 1000000) / qpfreq.QuadPart;
    299     #else
    300 	// _interval is in ms
    301         return _interval *1000LL;
    302     #endif
    303 #elif WEBRTC_LINUX
    304     // _interval is in ns
    305     return _interval / 1000;
    306 #else
    307     // _interval is usecs
    308     return _interval;
    309 #endif
    310 }
    311 
    312 inline TickInterval& TickInterval::operator+=(const TickInterval& rhs)
    313 {
    314     _interval += rhs._interval;
    315     return *this;
    316 }
    317 
    318 inline TickInterval& TickInterval::operator-=(const TickInterval& rhs)
    319 {
    320     _interval -= rhs._interval;
    321     return *this;
    322 }
    323 } // namespace webrtc
    324 
    325 #endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_TICK_UTIL_H_
    326