source: ntrip/branches/BNC_2.12/qwt/qwt_system_clock.cpp@ 8450

Last change on this file since 8450 was 4271, checked in by mervart, 13 years ago
File size: 7.5 KB
Line 
1/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
2 * Qwt Widget Library
3 * Copyright (C) 1997 Josef Wilgen
4 * Copyright (C) 2002 Uwe Rathmann
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the Qwt License, Version 1.0
8 *****************************************************************************/
9
10#include "qwt_system_clock.h"
11#include <qdatetime.h>
12
13#if !defined(Q_OS_WIN)
14#include <unistd.h>
15#endif
16
17#if defined(Q_OS_MAC)
18#include <stdint.h>
19#include <mach/mach_time.h>
20#define QWT_HIGH_RESOLUTION_CLOCK
21#elif defined(_POSIX_TIMERS)
22#include <time.h>
23#define QWT_HIGH_RESOLUTION_CLOCK
24#elif defined(Q_OS_WIN)
25#define QWT_HIGH_RESOLUTION_CLOCK
26#include <qt_windows.h>
27#endif
28
29#if defined(QWT_HIGH_RESOLUTION_CLOCK)
30
31class QwtHighResolutionClock
32{
33public:
34 QwtHighResolutionClock();
35
36 void start();
37 double restart();
38 double elapsed() const;
39
40 bool isNull() const;
41
42 static double precision();
43
44private:
45
46#if defined(Q_OS_MAC)
47 static double msecsTo( uint64_t, uint64_t );
48
49 uint64_t d_timeStamp;
50#elif defined(_POSIX_TIMERS)
51
52 static double msecsTo( const struct timespec &,
53 const struct timespec & );
54
55 static bool isMonotonic();
56
57 struct timespec d_timeStamp;
58 clockid_t d_clockId;
59
60#elif defined(Q_OS_WIN)
61
62 LARGE_INTEGER d_startTicks;
63 LARGE_INTEGER d_ticksPerSecond;
64#endif
65};
66
67#if defined(Q_OS_MAC)
68QwtHighResolutionClock::QwtHighResolutionClock():
69 d_timeStamp( 0 )
70{
71}
72
73double QwtHighResolutionClock::precision()
74{
75 return 1e-6;
76}
77
78void QwtHighResolutionClock::start()
79{
80 d_timeStamp = mach_absolute_time();
81}
82
83double QwtHighResolutionClock::restart()
84{
85 const uint64_t timeStamp = mach_absolute_time();
86 const double elapsed = msecsTo( d_timeStamp, timeStamp );
87 d_timeStamp = timeStamp;
88
89 return elapsed;
90}
91
92double QwtHighResolutionClock::elapsed() const
93{
94 return msecsTo( d_timeStamp, mach_absolute_time() );
95}
96
97bool QwtHighResolutionClock::isNull() const
98{
99 return d_timeStamp == 0;
100}
101
102double QwtHighResolutionClock::msecsTo(
103 uint64_t from, uint64_t to )
104{
105 const uint64_t difference = to - from;
106
107 static double conversion = 0.0;
108 if ( conversion == 0.0 )
109 {
110 mach_timebase_info_data_t info;
111 kern_return_t err = mach_timebase_info( &info );
112
113 //Convert the timebase into ms
114 if ( err == 0 )
115 conversion = 1e-6 * ( double ) info.numer / ( double ) info.denom;
116 }
117
118 return conversion * ( double ) difference;
119}
120
121#elif defined(_POSIX_TIMERS)
122
123QwtHighResolutionClock::QwtHighResolutionClock()
124{
125 d_clockId = isMonotonic() ? CLOCK_MONOTONIC : CLOCK_REALTIME;
126 d_timeStamp.tv_sec = d_timeStamp.tv_nsec = 0;
127}
128
129double QwtHighResolutionClock::precision()
130{
131 struct timespec resolution;
132
133 int clockId = isMonotonic() ? CLOCK_MONOTONIC : CLOCK_REALTIME;
134 ::clock_getres( clockId, &resolution );
135
136 return resolution.tv_nsec / 1e3;
137}
138
139inline bool QwtHighResolutionClock::isNull() const
140{
141 return d_timeStamp.tv_sec <= 0 && d_timeStamp.tv_nsec <= 0;
142}
143
144inline void QwtHighResolutionClock::start()
145{
146 ::clock_gettime( d_clockId, &d_timeStamp );
147}
148
149double QwtHighResolutionClock::restart()
150{
151 struct timespec timeStamp;
152 ::clock_gettime( d_clockId, &timeStamp );
153
154 const double elapsed = msecsTo( d_timeStamp, timeStamp );
155
156 d_timeStamp = timeStamp;
157 return elapsed;
158}
159
160inline double QwtHighResolutionClock::elapsed() const
161{
162 struct timespec timeStamp;
163 ::clock_gettime( d_clockId, &timeStamp );
164
165 return msecsTo( d_timeStamp, timeStamp );
166}
167
168inline double QwtHighResolutionClock::msecsTo(
169 const struct timespec &t1, const struct timespec &t2 )
170{
171 return ( t2.tv_sec - t1.tv_sec ) * 1e3
172 + ( t2.tv_nsec - t1.tv_nsec ) * 1e-6;
173}
174
175bool QwtHighResolutionClock::isMonotonic()
176{
177 // code copied from qcore_unix.cpp
178
179#if (_POSIX_MONOTONIC_CLOCK-0 > 0)
180 return true;
181#else
182 static int returnValue = 0;
183
184 if ( returnValue == 0 )
185 {
186#if (_POSIX_MONOTONIC_CLOCK-0 < 0) || !defined(_SC_MONOTONIC_CLOCK)
187 returnValue = -1;
188#elif (_POSIX_MONOTONIC_CLOCK == 0)
189 // detect if the system support monotonic timers
190 const long x = sysconf( _SC_MONOTONIC_CLOCK );
191 returnValue = ( x >= 200112L ) ? 1 : -1;
192#endif
193 }
194
195 return returnValue != -1;
196#endif
197}
198
199#elif defined(Q_OS_WIN)
200
201QwtHighResolutionClock::QwtHighResolutionClock()
202{
203 d_startTicks.QuadPart = 0;
204 QueryPerformanceFrequency( &d_ticksPerSecond );
205}
206
207double QwtHighResolutionClock::precision()
208{
209 LARGE_INTEGER ticks;
210 if ( QueryPerformanceFrequency( &ticks ) && ticks.QuadPart > 0 )
211 return 1e3 / ticks.QuadPart;
212
213 return 0.0;
214}
215
216inline bool QwtHighResolutionClock::isNull() const
217{
218 return d_startTicks.QuadPart <= 0;
219}
220
221inline void QwtHighResolutionClock::start()
222{
223 QueryPerformanceCounter( &d_startTicks );
224}
225
226inline double QwtHighResolutionClock::restart()
227{
228 LARGE_INTEGER ticks;
229 QueryPerformanceCounter( &ticks );
230
231 const double dt = ticks.QuadPart - d_startTicks.QuadPart;
232 d_startTicks = ticks;
233
234 return dt / d_ticksPerSecond.QuadPart * 1e3;
235}
236
237inline double QwtHighResolutionClock::elapsed() const
238{
239 LARGE_INTEGER ticks;
240 QueryPerformanceCounter( &ticks );
241
242 const double dt = ticks.QuadPart - d_startTicks.QuadPart;
243 return dt / d_ticksPerSecond.QuadPart * 1e3;
244}
245
246#endif
247
248#endif // QWT_HIGH_RESOLUTION_CLOCK
249
250class QwtSystemClock::PrivateData
251{
252public:
253#if defined(QWT_HIGH_RESOLUTION_CLOCK)
254 QwtHighResolutionClock *clock;
255#endif
256 QTime time;
257};
258
259//! Constructs a null clock object.
260QwtSystemClock::QwtSystemClock()
261{
262 d_data = new PrivateData;
263
264#if defined(QWT_HIGH_RESOLUTION_CLOCK)
265 d_data->clock = NULL;
266 if ( QwtHighResolutionClock::precision() > 0.0 )
267 d_data->clock = new QwtHighResolutionClock;
268#endif
269}
270
271//! Destructor
272QwtSystemClock::~QwtSystemClock()
273{
274#if defined(QWT_HIGH_RESOLUTION_CLOCK)
275 delete d_data->clock;
276#endif
277 delete d_data;
278}
279
280/*!
281 \return true if the clock has never been started.
282*/
283bool QwtSystemClock::isNull() const
284{
285#if defined(QWT_HIGH_RESOLUTION_CLOCK)
286 if ( d_data->clock )
287 return d_data->clock->isNull();
288#endif
289
290 return d_data->time.isNull();
291}
292
293/*!
294 Sets the start time to the current time.
295*/
296void QwtSystemClock::start()
297{
298#if defined(QWT_HIGH_RESOLUTION_CLOCK)
299 if ( d_data->clock )
300 {
301 d_data->clock->start();
302 return;
303 }
304#endif
305
306 d_data->time.start();
307}
308
309/*!
310 The start time to the current time and
311 return the time, that is elapsed since the
312 previous start time.
313*/
314double QwtSystemClock::restart()
315{
316#if defined(QWT_HIGH_RESOLUTION_CLOCK)
317 if ( d_data->clock )
318 return d_data->clock->restart();
319#endif
320
321 return d_data->time.restart();
322}
323
324/*!
325 \return Number of milliseconds that have elapsed since the last time
326 start() or restart() was called or 0.0 for null clocks.
327*/
328double QwtSystemClock::elapsed() const
329{
330 double elapsed = 0.0;
331
332#if defined(QWT_HIGH_RESOLUTION_CLOCK)
333 if ( d_data->clock )
334 {
335 if ( !d_data->clock->isNull() )
336 elapsed = d_data->clock->elapsed();
337
338 return elapsed;
339 }
340#endif
341
342 if ( !d_data->time.isNull() )
343 elapsed = d_data->time.elapsed();
344
345 return elapsed;
346}
347
348/*!
349 \return Accuracy of the system clock in milliseconds.
350*/
351double QwtSystemClock::precision()
352{
353 static double prec = 0.0;
354 if ( prec <= 0.0 )
355 {
356#if defined(QWT_HIGH_RESOLUTION_CLOCK)
357 prec = QwtHighResolutionClock::precision();
358#endif
359 if ( prec <= 0.0 )
360 prec = 1.0; // QTime offers 1 ms
361 }
362
363 return prec;
364}
Note: See TracBrowser for help on using the repository browser.