CTK  0.1.0
The Common Toolkit is a community effort to provide support code for medical image analysis, surgical navigation, and related projects.
ctkHighPrecisionTimer.h
Go to the documentation of this file.
1 /*=============================================================================
2 
3  Library: CTK
4 
5  Copyright (c) German Cancer Research Center,
6  Division of Medical and Biological Informatics
7 
8  Licensed under the Apache License, Version 2.0 (the "License");
9  you may not use this file except in compliance with the License.
10  You may obtain a copy of the License at
11 
12  http://www.apache.org/licenses/LICENSE-2.0
13 
14  Unless required by applicable law or agreed to in writing, software
15  distributed under the License is distributed on an "AS IS" BASIS,
16  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  See the License for the specific language governing permissions and
18  limitations under the License.
19 
20 =============================================================================*/
21 
22 #ifndef CTKHIGHPRECISIONTIMER_H
23 #define CTKHIGHPRECISIONTIMER_H
24 
25 
26 #include <qglobal.h>
27 
28 #undef _ctk_use_high_precision_timer_fallback
29 
30 #ifdef Q_OS_MAC
31 #include <mach/mach_time.h>
32 #elif defined(Q_OS_UNIX)
33 #include <time.h>
34 #include <unistd.h>
35 #ifndef _POSIX_MONOTONIC_CLOCK
36 #warning Monotonic clock support missing on this POSIX platform
37 #define _ctk_use_high_precision_timer_fallback
38 #endif
39 #elif defined(Q_OS_WIN)
40 #include <windows.h>
41 #else
42 #define _ctk_use_high_precision_timer_fallback
43 #endif
44 
45 #ifdef _ctk_use_high_precision_timer_fallback
46 #warning ctkHighPrecisionTimer is using the slower QTime fallback
47 #include <QTime>
48 #endif
49 
50 
62 
63 public:
64 
65  inline ctkHighPrecisionTimer();
66 
67  inline void start();
68 
69  inline qint64 elapsedMilli();
70 
71  inline qint64 elapsedMicro();
72 
73 private:
74 
75  // only used on MacOS, but needs to be defined in the .cpp file
76  static double timeConvert;
77 
78 #ifdef _ctk_use_high_precision_timer_fallback
79  QTime startTime;
80 #elif defined(Q_OS_MAC)
81  quint64 startTime;
82 #elif defined(Q_OS_UNIX)
83  timespec startTime;
84 #elif defined(Q_OS_WIN)
85  LARGE_INTEGER timerFrequency;
86  LARGE_INTEGER startTime;
87 #endif
88 };
89 
90 #ifdef _ctk_use_high_precision_timer_fallback
91 
93  : startTime(QTime::currentTime())
94 {
95 }
96 
98 {
99  startTime = QTime::currentTime();
100 }
101 
103 {
104  return startTime.elapsed();
105 }
106 
108 {
109  return startTime.elapsed() * 1000;
110 }
111 
112 #elif defined(Q_OS_MAC)
113 
115 : startTime(0)
116 {
117  if (timeConvert == 0)
118  {
119  mach_timebase_info_data_t timeBase;
120  mach_timebase_info(&timeBase);
121  timeConvert = static_cast<double>(timeBase.numer) / static_cast<double>(timeBase.denom) / 1000.0;
122  }
123 }
124 
125 inline void ctkHighPrecisionTimer::start()
126 {
127  startTime = mach_absolute_time();
128 }
129 
131 {
132  quint64 current = mach_absolute_time();
133  return static_cast<double>(current - startTime) * timeConvert / 1000.0;
134 }
135 
137 {
138  quint64 current = mach_absolute_time();
139  return static_cast<double>(current - startTime) * timeConvert;
140 }
141 
142 #elif defined(Q_OS_UNIX)
143 
145 {
146  startTime.tv_nsec = 0;
147  startTime.tv_sec = 0;
148 }
149 
150 inline void ctkHighPrecisionTimer::start()
151 {
152  clock_gettime(CLOCK_MONOTONIC, &startTime);
153 }
154 
156 {
157  timespec current;
158  clock_gettime(CLOCK_MONOTONIC, &current);
159  return (static_cast<qint64>(current.tv_sec)*1000 + current.tv_nsec/1000/1000) -
160  (static_cast<qint64>(startTime.tv_sec)*1000 + startTime.tv_nsec/1000/1000);
161 }
162 
164 {
165  timespec current;
166  clock_gettime(CLOCK_MONOTONIC, &current);
167  return (static_cast<qint64>(current.tv_sec)*1000*1000 + current.tv_nsec/1000) -
168  (static_cast<qint64>(startTime.tv_sec)*1000*1000 + startTime.tv_nsec/1000);
169 }
170 
171 #elif defined(Q_OS_WIN)
172 
173 #include "ctkException.h"
174 
176 {
177  if (!QueryPerformanceFrequency(&timerFrequency))
178  throw ctkRuntimeException("QueryPerformanceFrequency() failed");
179 }
180 
181 inline void ctkHighPrecisionTimer::start()
182 {
183  //DWORD_PTR oldmask = SetThreadAffinityMask(GetCurrentThread(), 0);
184  QueryPerformanceCounter(&startTime);
185  //SetThreadAffinityMask(GetCurrentThread(), oldmask);
186 }
187 
189 {
190  LARGE_INTEGER current;
191  QueryPerformanceCounter(&current);
192  return (current.QuadPart - startTime.QuadPart) / (timerFrequency.QuadPart / 1000);
193 }
194 
196 {
197  LARGE_INTEGER current;
198  QueryPerformanceCounter(&current);
199  return (current.QuadPart - startTime.QuadPart) / (timerFrequency.QuadPart / (1000*1000));
200 }
201 
202 #endif
203 
204 #endif // CTKHIGHPRECISIONTIMER_H
A fast and high precision timer.