git-svn-id: http://webrtc.googlecode.com/svn/trunk@6 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/system_wrappers/interface/tick_util.h b/system_wrappers/interface/tick_util.h
new file mode 100644
index 0000000..4c28067
--- /dev/null
+++ b/system_wrappers/interface/tick_util.h
@@ -0,0 +1,304 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+// System independant wrapper for polling elapsed time in ms and us.
+// The implementation works in the tick domain which can be mapped over to the
+// time domain.
+#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_TICK_UTIL_H_
+#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_TICK_UTIL_H_
+
+#if _WIN32
+#include <windows.h>
+#include <mmsystem.h>
+#elif WEBRTC_LINUX
+#include <ctime>
+#else
+#include <sys/time.h>
+#include <time.h>
+#endif
+
+#include "typedefs.h"
+
+namespace webrtc {
+class TickInterval;
+
+class TickTime
+{
+public:
+    // Current time in the tick domain.
+    static TickTime Now();
+
+    // Now in the time domain in ms.
+    static WebRtc_Word64 MillisecondTimestamp();
+
+    // Now in the time domain in us.
+    static WebRtc_Word64 MicrosecondTimestamp();
+
+    WebRtc_Word64 Ticks() const;
+
+    static WebRtc_Word64 MillisecondsToTicks(const WebRtc_Word64 ms);
+
+    static WebRtc_Word64 TicksToMilliseconds(const WebRtc_Word64 ticks);
+
+    // Returns a TickTime that is ticks later than the passed TickTime
+    friend TickTime operator+(const TickTime lhs, const WebRtc_Word64 ticks);
+    TickTime& operator+=(const WebRtc_Word64& rhs);
+
+
+    // Returns a TickInterval that is the difference in ticks beween rhs and lhs
+    friend TickInterval operator-(const TickTime& lhs, const TickTime& rhs);
+private:
+    WebRtc_Word64 _ticks;
+};
+
+class TickInterval
+{
+public:
+    TickInterval();
+
+    WebRtc_Word64 Milliseconds() const;
+    WebRtc_Word64 Microseconds() const;
+
+    // Returns the sum of two TickIntervals as a TickInterval
+    friend TickInterval operator+(const TickInterval& lhs,
+                                  const TickInterval& rhs);
+    TickInterval& operator-=(const TickInterval& rhs);
+
+    // Returns a TickInterval corresponding to rhs - lhs
+    friend TickInterval operator-(const TickInterval& lhs,
+                                  const TickInterval& rhs);
+    TickInterval& operator+=(const TickInterval& rhs);
+
+private:
+    TickInterval(WebRtc_Word64 interval);
+
+    friend class TickTime;
+    friend TickInterval operator-(const TickTime& lhs, const TickTime& rhs);
+
+private:
+    WebRtc_Word64 _interval;
+};
+
+inline TickInterval operator+(const TickInterval& lhs, const TickInterval& rhs)
+{
+    return TickInterval(lhs._interval + rhs._interval);
+}
+
+inline TickInterval operator-(const TickInterval& lhs, const TickInterval& rhs)
+{
+    return TickInterval(lhs._interval - rhs._interval);
+}
+
+inline TickInterval operator-(const TickTime& lhs,const TickTime& rhs)
+{
+    return TickInterval(lhs._ticks - rhs._ticks);
+}
+
+inline TickTime operator+(const TickTime lhs, const WebRtc_Word64 ticks)
+{
+    TickTime time = lhs;
+    time._ticks += ticks;
+    return time;
+}
+
+inline TickTime TickTime::Now()
+{
+    TickTime result;
+#if _WIN32
+    #ifdef USE_QUERY_PERFORMANCE_COUNTER
+        // QueryPerformanceCounter returns the value from the TSC which is
+        // incremented at the CPU frequency. The algorithm used requires
+        // the CPU frequency to be constant. Technology like speed stepping
+        // which has variable CPU frequency will therefore yield unpredictable,
+        // incorrect time estimations.
+        LARGE_INTEGER qpcnt;
+        QueryPerformanceCounter(&qpcnt);
+        result._ticks = qpcnt.QuadPart;
+    #else
+        static volatile LONG lastTimeGetTime = 0;
+        static volatile WebRtc_Word64 numWrapTimeGetTime = 0;
+        volatile LONG* lastTimeGetTimePtr = &lastTimeGetTime;
+        DWORD now = timeGetTime();
+        // Atomically update the last gotten time
+        DWORD old = InterlockedExchange(lastTimeGetTimePtr, now);
+        if(now < old)
+        {
+            // If now is earlier than old, there may have been a race between
+            // threads.
+            // 0x0fffffff ~3.1 days, the code will not take that long to execute
+            // so it must have been a wrap around.
+            if(old > 0xf0000000 && now < 0x0fffffff) 
+            {
+                numWrapTimeGetTime++;
+            }
+        }
+        result._ticks = now + (numWrapTimeGetTime<<32);
+    #endif
+#elif defined(WEBRTC_LINUX)
+    struct timespec ts;
+    #ifdef WEBRTC_CLOCK_TYPE_REALTIME
+        clock_gettime(CLOCK_REALTIME, &ts);
+    #else
+        clock_gettime(CLOCK_MONOTONIC, &ts);
+    #endif
+    result._ticks = 1000000000LL * static_cast<WebRtc_Word64>(ts.tv_sec) + static_cast<WebRtc_Word64>(ts.tv_nsec);
+#else
+    struct timeval tv;
+    gettimeofday(&tv, NULL);
+    result._ticks = 1000000LL * static_cast<WebRtc_Word64>(tv.tv_sec) + static_cast<WebRtc_Word64>(tv.tv_usec);
+#endif
+    return result;
+}
+
+inline WebRtc_Word64 TickTime::MillisecondTimestamp()
+{
+    TickTime now = TickTime::Now();
+#if _WIN32
+    #ifdef USE_QUERY_PERFORMANCE_COUNTER
+        LARGE_INTEGER qpfreq;
+        QueryPerformanceFrequency(&qpfreq);
+        return (now._ticks * 1000) / qpfreq.QuadPart;
+    #else
+        return now._ticks;
+    #endif
+#elif WEBRTC_LINUX
+    return now._ticks / 1000000LL;
+#else
+    return now._ticks / 1000LL;
+#endif
+}
+
+inline WebRtc_Word64 TickTime::MicrosecondTimestamp()
+{
+    TickTime now = TickTime::Now();
+
+#if _WIN32
+    #ifdef USE_QUERY_PERFORMANCE_COUNTER
+        LARGE_INTEGER qpfreq;
+        QueryPerformanceFrequency(&qpfreq);
+        return (now._ticks * 1000) / (qpfreq.QuadPart/1000);
+    #else
+        return now._ticks *1000LL;
+    #endif
+#elif WEBRTC_LINUX
+    return now._ticks / 1000LL;
+#else
+    return now._ticks;
+#endif
+}
+
+inline WebRtc_Word64 TickTime::Ticks() const
+{
+    return _ticks;
+}
+
+inline WebRtc_Word64 TickTime::MillisecondsToTicks(const WebRtc_Word64 ms)
+{
+#if _WIN32
+    #ifdef USE_QUERY_PERFORMANCE_COUNTER
+        LARGE_INTEGER qpfreq;
+        QueryPerformanceFrequency(&qpfreq);
+        return (qpfreq.QuadPart * ms) / 1000;
+    #else
+        return ms;
+    #endif
+#elif WEBRTC_LINUX
+    return ms * 1000000LL;
+#else
+    return ms * 1000LL;
+#endif
+}
+
+inline WebRtc_Word64 TickTime::TicksToMilliseconds(const WebRtc_Word64 ticks)
+{
+#if _WIN32
+    #ifdef USE_QUERY_PERFORMANCE_COUNTER
+        LARGE_INTEGER qpfreq;
+        QueryPerformanceFrequency(&qpfreq);
+        return (ticks * 1000) / qpfreq.QuadPart;
+    #else
+        return ticks;
+    #endif
+#elif WEBRTC_LINUX
+    return ticks / 1000000LL;
+#else
+    return ticks / 1000LL;
+#endif
+}
+
+inline TickTime& TickTime::operator+=(const WebRtc_Word64& ticks)
+{
+    _ticks += ticks;
+    return *this;
+}
+
+inline TickInterval::TickInterval() : _interval(0)
+{
+}
+
+inline TickInterval::TickInterval(const WebRtc_Word64 interval)
+    : _interval(interval)
+{
+}
+
+inline WebRtc_Word64 TickInterval::Milliseconds() const
+{
+#if _WIN32
+    #ifdef USE_QUERY_PERFORMANCE_COUNTER
+        LARGE_INTEGER qpfreq;
+        QueryPerformanceFrequency(&qpfreq);
+        return (_interval * 1000) / qpfreq.QuadPart;
+    #else
+	// _interval is in ms
+        return _interval;
+    #endif
+#elif WEBRTC_LINUX
+    // _interval is in ns
+    return _interval / 1000000;
+#else
+    // _interval is usecs
+    return _interval / 1000;
+#endif
+}
+
+inline WebRtc_Word64 TickInterval::Microseconds() const
+{
+#if _WIN32
+    #ifdef USE_QUERY_PERFORMANCE_COUNTER
+        LARGE_INTEGER qpfreq;
+        QueryPerformanceFrequency(&qpfreq);
+        return (_interval * 1000000) / qpfreq.QuadPart;
+    #else
+	// _interval is in ms
+        return _interval *1000LL;
+    #endif
+#elif WEBRTC_LINUX
+    // _interval is in ns
+    return _interval / 1000;
+#else
+    // _interval is usecs
+    return _interval;
+#endif
+}
+
+inline TickInterval& TickInterval::operator+=(const TickInterval& rhs)
+{
+    _interval += rhs._interval;
+    return *this;
+}
+
+inline TickInterval& TickInterval::operator-=(const TickInterval& rhs)
+{
+    _interval -= rhs._interval;
+    return *this;
+}
+} // namespace webrtc
+
+#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_TICK_UTIL_H_