aboutsummaryrefslogtreecommitdiff
path: root/src/system_wrappers/interface/tick_util.h
blob: 4c280677b50d7c27c4c9c5d94e8537656b3895d7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
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_