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 private:
     80     TickInterval(WebRtc_Word64 interval);
     81 
     82     friend class TickTime;
     83     friend TickInterval operator-(const TickTime& lhs, const TickTime& rhs);
     84 
     85 private:
     86     WebRtc_Word64 _interval;
     87 };
     88 
     89 inline TickInterval operator+(const TickInterval& lhs, const TickInterval& rhs)
     90 {
     91     return TickInterval(lhs._interval + rhs._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 TickTime& lhs,const TickTime& rhs)
    100 {
    101     return TickInterval(lhs._ticks - rhs._ticks);
    102 }
    103 
    104 inline TickTime operator+(const TickTime lhs, const WebRtc_Word64 ticks)
    105 {
    106     TickTime time = lhs;
    107     time._ticks += ticks;
    108     return time;
    109 }
    110 
    111 inline TickTime TickTime::Now()
    112 {
    113     TickTime result;
    114 #if _WIN32
    115     #ifdef USE_QUERY_PERFORMANCE_COUNTER
    116         // QueryPerformanceCounter returns the value from the TSC which is
    117         // incremented at the CPU frequency. The algorithm used requires
    118         // the CPU frequency to be constant. Technology like speed stepping
    119         // which has variable CPU frequency will therefore yield unpredictable,
    120         // incorrect time estimations.
    121         LARGE_INTEGER qpcnt;
    122         QueryPerformanceCounter(&qpcnt);
    123         result._ticks = qpcnt.QuadPart;
    124     #else
    125         static volatile LONG lastTimeGetTime = 0;
    126         static volatile WebRtc_Word64 numWrapTimeGetTime = 0;
    127         volatile LONG* lastTimeGetTimePtr = &lastTimeGetTime;
    128         DWORD now = timeGetTime();
    129         // Atomically update the last gotten time
    130         DWORD old = InterlockedExchange(lastTimeGetTimePtr, now);
    131         if(now < old)
    132         {
    133             // If now is earlier than old, there may have been a race between
    134             // threads.
    135             // 0x0fffffff ~3.1 days, the code will not take that long to execute
    136             // so it must have been a wrap around.
    137             if(old > 0xf0000000 && now < 0x0fffffff)
    138             {
    139                 numWrapTimeGetTime++;
    140             }
    141         }
    142         result._ticks = now + (numWrapTimeGetTime<<32);
    143     #endif
    144 #elif defined(WEBRTC_LINUX)
    145     struct timespec ts;
    146     #ifdef WEBRTC_CLOCK_TYPE_REALTIME
    147         clock_gettime(CLOCK_REALTIME, &ts);
    148     #else
    149         clock_gettime(CLOCK_MONOTONIC, &ts);
    150     #endif
    151     result._ticks = 1000000000LL * static_cast<WebRtc_Word64>(ts.tv_sec) + static_cast<WebRtc_Word64>(ts.tv_nsec);
    152 #else
    153     struct timeval tv;
    154     gettimeofday(&tv, NULL);
    155     result._ticks = 1000000LL * static_cast<WebRtc_Word64>(tv.tv_sec) + static_cast<WebRtc_Word64>(tv.tv_usec);
    156 #endif
    157     return result;
    158 }
    159 
    160 inline WebRtc_Word64 TickTime::MillisecondTimestamp()
    161 {
    162     TickTime now = TickTime::Now();
    163 #if _WIN32
    164     #ifdef USE_QUERY_PERFORMANCE_COUNTER
    165         LARGE_INTEGER qpfreq;
    166         QueryPerformanceFrequency(&qpfreq);
    167         return (now._ticks * 1000) / qpfreq.QuadPart;
    168     #else
    169         return now._ticks;
    170     #endif
    171 #elif WEBRTC_LINUX
    172     return now._ticks / 1000000LL;
    173 #else
    174     return now._ticks / 1000LL;
    175 #endif
    176 }
    177 
    178 inline WebRtc_Word64 TickTime::MicrosecondTimestamp()
    179 {
    180     TickTime now = TickTime::Now();
    181 
    182 #if _WIN32
    183     #ifdef USE_QUERY_PERFORMANCE_COUNTER
    184         LARGE_INTEGER qpfreq;
    185         QueryPerformanceFrequency(&qpfreq);
    186         return (now._ticks * 1000) / (qpfreq.QuadPart/1000);
    187     #else
    188         return now._ticks *1000LL;
    189     #endif
    190 #elif WEBRTC_LINUX
    191     return now._ticks / 1000LL;
    192 #else
    193     return now._ticks;
    194 #endif
    195 }
    196 
    197 inline WebRtc_Word64 TickTime::Ticks() const
    198 {
    199     return _ticks;
    200 }
    201 
    202 inline WebRtc_Word64 TickTime::MillisecondsToTicks(const WebRtc_Word64 ms)
    203 {
    204 #if _WIN32
    205     #ifdef USE_QUERY_PERFORMANCE_COUNTER
    206         LARGE_INTEGER qpfreq;
    207         QueryPerformanceFrequency(&qpfreq);
    208         return (qpfreq.QuadPart * ms) / 1000;
    209     #else
    210         return ms;
    211     #endif
    212 #elif WEBRTC_LINUX
    213     return ms * 1000000LL;
    214 #else
    215     return ms * 1000LL;
    216 #endif
    217 }
    218 
    219 inline WebRtc_Word64 TickTime::TicksToMilliseconds(const WebRtc_Word64 ticks)
    220 {
    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 WEBRTC_LINUX
    230     return ticks / 1000000LL;
    231 #else
    232     return ticks / 1000LL;
    233 #endif
    234 }
    235 
    236 inline TickTime& TickTime::operator+=(const WebRtc_Word64& ticks)
    237 {
    238     _ticks += ticks;
    239     return *this;
    240 }
    241 
    242 inline TickInterval::TickInterval() : _interval(0)
    243 {
    244 }
    245 
    246 inline TickInterval::TickInterval(const WebRtc_Word64 interval)
    247     : _interval(interval)
    248 {
    249 }
    250 
    251 inline WebRtc_Word64 TickInterval::Milliseconds() const
    252 {
    253 #if _WIN32
    254     #ifdef USE_QUERY_PERFORMANCE_COUNTER
    255         LARGE_INTEGER qpfreq;
    256         QueryPerformanceFrequency(&qpfreq);
    257         return (_interval * 1000) / qpfreq.QuadPart;
    258     #else
    259 	// _interval is in ms
    260         return _interval;
    261     #endif
    262 #elif WEBRTC_LINUX
    263     // _interval is in ns
    264     return _interval / 1000000;
    265 #else
    266     // _interval is usecs
    267     return _interval / 1000;
    268 #endif
    269 }
    270 
    271 inline WebRtc_Word64 TickInterval::Microseconds() const
    272 {
    273 #if _WIN32
    274     #ifdef USE_QUERY_PERFORMANCE_COUNTER
    275         LARGE_INTEGER qpfreq;
    276         QueryPerformanceFrequency(&qpfreq);
    277         return (_interval * 1000000) / qpfreq.QuadPart;
    278     #else
    279 	// _interval is in ms
    280         return _interval *1000LL;
    281     #endif
    282 #elif WEBRTC_LINUX
    283     // _interval is in ns
    284     return _interval / 1000;
    285 #else
    286     // _interval is usecs
    287     return _interval;
    288 #endif
    289 }
    290 
    291 inline TickInterval& TickInterval::operator+=(const TickInterval& rhs)
    292 {
    293     _interval += rhs._interval;
    294     return *this;
    295 }
    296 
    297 inline TickInterval& TickInterval::operator-=(const TickInterval& rhs)
    298 {
    299     _interval -= rhs._interval;
    300     return *this;
    301 }
    302 } // namespace webrtc
    303 
    304 #endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_TICK_UTIL_H_
    305