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