Merge remote-tracking branch 'origin/master' into api_changes
[profile/ivi/qtbase.git] / src / corelib / tools / qelapsedtimer_win.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the QtCore module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qelapsedtimer.h"
43 #include <qt_windows.h>
44
45 typedef ULONGLONG (WINAPI *PtrGetTickCount64)(void);
46 static PtrGetTickCount64 ptrGetTickCount64 = 0;
47
48 QT_BEGIN_NAMESPACE
49
50 // Result of QueryPerformanceFrequency, 0 indicates that the high resolution timer is unavailable
51 static quint64 counterFrequency = 0;
52
53 static void resolveLibs()
54 {
55     static bool done = false;
56     if (done)
57         return;
58
59     // try to get GetTickCount64 from the system
60     HMODULE kernel32 = GetModuleHandleW(L"kernel32");
61     if (!kernel32)
62         return;
63
64 #if defined(Q_OS_WINCE)
65     // does this function exist on WinCE, or will ever exist?
66     ptrGetTickCount64 = (PtrGetTickCount64)GetProcAddress(kernel32, L"GetTickCount64");
67 #else
68     ptrGetTickCount64 = (PtrGetTickCount64)GetProcAddress(kernel32, "GetTickCount64");
69 #endif
70
71     // Retrieve the number of high-resolution performance counter ticks per second
72     LARGE_INTEGER frequency;
73     if (!QueryPerformanceFrequency(&frequency)) {
74         counterFrequency = 0;
75     } else {
76         counterFrequency = frequency.QuadPart;
77     }
78
79     done = true;
80 }
81
82 static inline qint64 ticksToNanoseconds(qint64 ticks)
83 {
84     if (counterFrequency > 0) {
85         // QueryPerformanceCounter uses an arbitrary frequency
86         qint64 seconds = ticks / counterFrequency;
87         qint64 nanoSeconds = (ticks - seconds * counterFrequency) * 1000000000 / counterFrequency;
88         return seconds * 1000000000 + nanoSeconds;
89     } else {
90         // GetTickCount(64) return milliseconds
91         return ticks * 1000000;
92     }
93 }
94
95 static quint64 getTickCount()
96 {
97     resolveLibs();
98
99     // This avoids a division by zero and disables the high performance counter if it's not available
100     if (counterFrequency > 0) {
101         LARGE_INTEGER counter;
102
103         if (QueryPerformanceCounter(&counter)) {
104             return counter.QuadPart;
105         } else {
106             qWarning("QueryPerformanceCounter failed, although QueryPerformanceFrequency succeeded.");
107             return 0;
108         }
109     }
110
111     if (ptrGetTickCount64)
112         return ptrGetTickCount64();
113
114     static quint32 highdword = 0;
115     static quint32 lastval = 0;
116     quint32 val = GetTickCount();
117     if (val < lastval)
118         ++highdword;
119     lastval = val;
120     return val | (quint64(highdword) << 32);
121 }
122
123 int qt_msectime()
124 {
125     return ticksToNanoseconds(getTickCount()) / 1000000;
126 }
127
128 QElapsedTimer::ClockType QElapsedTimer::clockType()
129 {
130     resolveLibs();
131
132     if (counterFrequency > 0)
133         return PerformanceCounter;
134     else
135         return TickCounter;
136 }
137
138 bool QElapsedTimer::isMonotonic()
139 {
140     return true;
141 }
142
143 void QElapsedTimer::start()
144 {
145     t1 = getTickCount();
146     t2 = 0;
147 }
148
149 qint64 QElapsedTimer::restart()
150 {
151     qint64 oldt1 = t1;
152     t1 = getTickCount();
153     t2 = 0;
154     return ticksToNanoseconds(t1 - oldt1) / 1000000;
155 }
156
157 qint64 QElapsedTimer::nsecsElapsed() const
158 {
159     qint64 elapsed = getTickCount() - t1;
160     return ticksToNanoseconds(elapsed);
161 }
162
163 qint64 QElapsedTimer::elapsed() const
164 {
165     qint64 elapsed = getTickCount() - t1;
166     return ticksToNanoseconds(elapsed) / 1000000;
167 }
168
169 qint64 QElapsedTimer::msecsSinceReference() const
170 {
171     return ticksToNanoseconds(t1) / 1000000;
172 }
173
174 qint64 QElapsedTimer::msecsTo(const QElapsedTimer &other) const
175 {
176     qint64 difference = other.t1 - t1;
177     return ticksToNanoseconds(difference) / 1000000;
178 }
179
180 qint64 QElapsedTimer::secsTo(const QElapsedTimer &other) const
181 {
182     return msecsTo(other) / 1000;
183 }
184
185 bool operator<(const QElapsedTimer &v1, const QElapsedTimer &v2)
186 {
187     return (v1.t1 - v2.t1) < 0;
188 }
189
190 QT_END_NAMESPACE