-
Notifications
You must be signed in to change notification settings - Fork 0
/
timer.cpp
150 lines (133 loc) · 4.35 KB
/
timer.cpp
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
/***************************************************************************
* Copyright 2015 Michael Eischer, Philipp Nordhus *
* Robotics Erlangen e.V. *
* http://www.robotics-erlangen.de/ *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
***************************************************************************/
#include "timer.h"
#if _POSIX_TIMERS > 0
#define WITH_POSIX_TIMERS
#endif
#ifdef WITH_POSIX_TIMERS
#include <time.h>
#else
#include <sys/time.h>
#ifdef Q_OS_WIN
#include <windows.h>
#endif // Q_OS_WIN
#endif
/*!
* \class Timer
* \ingroup core
* \brief High precision timer
*/
/*!
* \brief Creates a new timer object
*/
Timer::Timer()
{
reset();
}
/*!
* \brief Sets time scaling. Time is guaranteed to be continous
* \param scaling New scaling factor
*/
void Timer::setScaling(double scaling)
{
Q_ASSERT(scaling >= 0);
setTime(currentTime(), scaling);
}
/*!
* \brief Reset timer to current time and reset Scaling
*/
void Timer::reset()
{
setTime(systemTime(), 1.0);
}
/*!
* \brief Query internal time
* \return The internal time in nanoseconds
*/
qint64 Timer::currentTime() const
{
const qint64 sys = systemTime();
return m_offset + (qint64)((sys - m_start) * m_scaling);
}
/*!
* \brief Set internal time and scaling
* \param time New internal time
* \param scaling New scaling factor
*/
void Timer::setTime(qint64 time, double scaling)
{
Q_ASSERT(scaling >= 0);
m_offset = time;
m_start = systemTime();
m_scaling = scaling;
}
/*!
* \brief Query system time
* \return The current system time in nanoseconds
*/
qint64 Timer::systemTime()
{
#ifdef WITH_POSIX_TIMERS
timespec ts;
if (clock_gettime(CLOCK_REALTIME, &ts) == -1)
return 0;
return qint64(ts.tv_sec) * 1000000000LL + qint64(ts.tv_nsec);
#else // WITH_POSIX_TIMERS
#ifdef Q_OS_WIN
static bool isInitialized = false;
static quint64 timerFrequency;
static quint64 startTick;
static quint64 startTime;
if (!isInitialized) {
isInitialized = true;
timerFrequency = 0; // !!! disable QueryPerformanceCounter for initialization
startTime = Timer::systemTime(); // get time via gettimeofday
// the timing provided by this code is far from optimal, but it should do
// as the time deltas are what we're interested in.
LARGE_INTEGER freq;
// set timerFrequency to zero if QueryPerformanceCounter can't be used
if (!QueryPerformanceFrequency(&freq)) {
timerFrequency = 0;
} else {
timerFrequency = freq.QuadPart;
}
if (timerFrequency > 0) {
LARGE_INTEGER ticks;
if (QueryPerformanceCounter(&ticks)) {
startTick = ticks.QuadPart;
} else {
timerFrequency = 0;
}
}
}
if (timerFrequency > 0) {
LARGE_INTEGER ticks;
if (QueryPerformanceCounter(&ticks)) {
return (ticks.QuadPart - startTick) * 1000000000LL / timerFrequency + startTime;
}
}
#endif // Q_OS_WIN
timeval tv;
if (gettimeofday(&tv, NULL) != 0) {
return 0;
}
return qint64(tv.tv_sec) * 1000000000LL + qint64(tv.tv_usec) * 1000LL;
#endif // WITH_POSIX_TIMERS
}