Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "qwt_system_clock.h"
00011
00012 #if QT_VERSION >= 0x040800
00013 #define USE_ELAPSED_TIMER 1
00014 #endif
00015
00016 #if USE_ELAPSED_TIMER
00017
00018 #include <qelapsedtimer.h>
00019
00020 class QwtSystemClock::PrivateData
00021 {
00022 public:
00023 QElapsedTimer timer;
00024 };
00025
00026 QwtSystemClock::QwtSystemClock()
00027 {
00028 d_data = new PrivateData();
00029 }
00030
00031 QwtSystemClock::~QwtSystemClock()
00032 {
00033 delete d_data;
00034 }
00035
00036 bool QwtSystemClock::isNull() const
00037 {
00038 return d_data->timer.isValid();
00039 }
00040
00041 void QwtSystemClock::start()
00042 {
00043 d_data->timer.start();
00044 }
00045
00046 double QwtSystemClock::restart()
00047 {
00048 const qint64 nsecs = d_data->timer.restart();
00049 return nsecs / 1e6;
00050 }
00051
00052 double QwtSystemClock::elapsed() const
00053 {
00054 const qint64 nsecs = d_data->timer.nsecsElapsed();
00055 return nsecs / 1e6;
00056 }
00057
00058 #else // !USE_ELAPSED_TIMER
00059
00060 #include <qdatetime.h>
00061
00062 #if !defined(Q_OS_WIN)
00063 #include <unistd.h>
00064 #endif
00065
00066 #if defined(Q_OS_MAC)
00067 #include <stdint.h>
00068 #include <mach/mach_time.h>
00069 #define QWT_HIGH_RESOLUTION_CLOCK
00070 #elif defined(_POSIX_TIMERS)
00071 #include <time.h>
00072 #define QWT_HIGH_RESOLUTION_CLOCK
00073 #elif defined(Q_OS_WIN)
00074 #define QWT_HIGH_RESOLUTION_CLOCK
00075 #include <qt_windows.h>
00076 #endif
00077
00078 #if defined(QWT_HIGH_RESOLUTION_CLOCK)
00079
00080 class QwtHighResolutionClock
00081 {
00082 public:
00083 QwtHighResolutionClock();
00084
00085 void start();
00086 double restart();
00087 double elapsed() const;
00088
00089 bool isNull() const;
00090
00091 static double precision();
00092
00093 private:
00094
00095 #if defined(Q_OS_MAC)
00096 static double msecsTo( uint64_t, uint64_t );
00097
00098 uint64_t d_timeStamp;
00099 #elif defined(_POSIX_TIMERS)
00100
00101 static double msecsTo( const struct timespec &,
00102 const struct timespec & );
00103
00104 static bool isMonotonic();
00105
00106 struct timespec d_timeStamp;
00107 clockid_t d_clockId;
00108
00109 #elif defined(Q_OS_WIN)
00110
00111 LARGE_INTEGER d_startTicks;
00112 LARGE_INTEGER d_ticksPerSecond;
00113 #endif
00114 };
00115
00116 #if defined(Q_OS_MAC)
00117 QwtHighResolutionClock::QwtHighResolutionClock():
00118 d_timeStamp( 0 )
00119 {
00120 }
00121
00122 double QwtHighResolutionClock::precision()
00123 {
00124 return 1e-6;
00125 }
00126
00127 void QwtHighResolutionClock::start()
00128 {
00129 d_timeStamp = mach_absolute_time();
00130 }
00131
00132 double QwtHighResolutionClock::restart()
00133 {
00134 const uint64_t timeStamp = mach_absolute_time();
00135 const double elapsed = msecsTo( d_timeStamp, timeStamp );
00136 d_timeStamp = timeStamp;
00137
00138 return elapsed;
00139 }
00140
00141 double QwtHighResolutionClock::elapsed() const
00142 {
00143 return msecsTo( d_timeStamp, mach_absolute_time() );
00144 }
00145
00146 bool QwtHighResolutionClock::isNull() const
00147 {
00148 return d_timeStamp == 0;
00149 }
00150
00151 double QwtHighResolutionClock::msecsTo(
00152 uint64_t from, uint64_t to )
00153 {
00154 const uint64_t difference = to - from;
00155
00156 static double conversion = 0.0;
00157 if ( conversion == 0.0 )
00158 {
00159 mach_timebase_info_data_t info;
00160 kern_return_t err = mach_timebase_info( &info );
00161
00162
00163 if ( err == 0 )
00164 conversion = 1e-6 * ( double ) info.numer / ( double ) info.denom;
00165 }
00166
00167 return conversion * ( double ) difference;
00168 }
00169
00170 #elif defined(_POSIX_TIMERS)
00171
00172 QwtHighResolutionClock::QwtHighResolutionClock()
00173 {
00174 d_clockId = isMonotonic() ? CLOCK_MONOTONIC : CLOCK_REALTIME;
00175 d_timeStamp.tv_sec = d_timeStamp.tv_nsec = 0;
00176 }
00177
00178 double QwtHighResolutionClock::precision()
00179 {
00180 struct timespec resolution;
00181
00182 int clockId = isMonotonic() ? CLOCK_MONOTONIC : CLOCK_REALTIME;
00183 ::clock_getres( clockId, &resolution );
00184
00185 return resolution.tv_nsec / 1e3;
00186 }
00187
00188 inline bool QwtHighResolutionClock::isNull() const
00189 {
00190 return d_timeStamp.tv_sec <= 0 && d_timeStamp.tv_nsec <= 0;
00191 }
00192
00193 inline void QwtHighResolutionClock::start()
00194 {
00195 ::clock_gettime( d_clockId, &d_timeStamp );
00196 }
00197
00198 double QwtHighResolutionClock::restart()
00199 {
00200 struct timespec timeStamp;
00201 ::clock_gettime( d_clockId, &timeStamp );
00202
00203 const double elapsed = msecsTo( d_timeStamp, timeStamp );
00204
00205 d_timeStamp = timeStamp;
00206 return elapsed;
00207 }
00208
00209 inline double QwtHighResolutionClock::elapsed() const
00210 {
00211 struct timespec timeStamp;
00212 ::clock_gettime( d_clockId, &timeStamp );
00213
00214 return msecsTo( d_timeStamp, timeStamp );
00215 }
00216
00217 inline double QwtHighResolutionClock::msecsTo(
00218 const struct timespec &t1, const struct timespec &t2 )
00219 {
00220 return ( t2.tv_sec - t1.tv_sec ) * 1e3
00221 + ( t2.tv_nsec - t1.tv_nsec ) * 1e-6;
00222 }
00223
00224 bool QwtHighResolutionClock::isMonotonic()
00225 {
00226
00227
00228 #if (_POSIX_MONOTONIC_CLOCK-0 > 0)
00229 return true;
00230 #else
00231 static int returnValue = 0;
00232
00233 if ( returnValue == 0 )
00234 {
00235 #if (_POSIX_MONOTONIC_CLOCK-0 < 0) || !defined(_SC_MONOTONIC_CLOCK)
00236 returnValue = -1;
00237 #elif (_POSIX_MONOTONIC_CLOCK == 0)
00238
00239 const long x = sysconf( _SC_MONOTONIC_CLOCK );
00240 returnValue = ( x >= 200112L ) ? 1 : -1;
00241 #endif
00242 }
00243
00244 return returnValue != -1;
00245 #endif
00246 }
00247
00248 #elif defined(Q_OS_WIN)
00249
00250 QwtHighResolutionClock::QwtHighResolutionClock()
00251 {
00252 d_startTicks.QuadPart = 0;
00253 QueryPerformanceFrequency( &d_ticksPerSecond );
00254 }
00255
00256 double QwtHighResolutionClock::precision()
00257 {
00258 LARGE_INTEGER ticks;
00259 if ( QueryPerformanceFrequency( &ticks ) && ticks.QuadPart > 0 )
00260 return 1e3 / ticks.QuadPart;
00261
00262 return 0.0;
00263 }
00264
00265 inline bool QwtHighResolutionClock::isNull() const
00266 {
00267 return d_startTicks.QuadPart <= 0;
00268 }
00269
00270 inline void QwtHighResolutionClock::start()
00271 {
00272 QueryPerformanceCounter( &d_startTicks );
00273 }
00274
00275 inline double QwtHighResolutionClock::restart()
00276 {
00277 LARGE_INTEGER ticks;
00278 QueryPerformanceCounter( &ticks );
00279
00280 const double dt = ticks.QuadPart - d_startTicks.QuadPart;
00281 d_startTicks = ticks;
00282
00283 return dt / d_ticksPerSecond.QuadPart * 1e3;
00284 }
00285
00286 inline double QwtHighResolutionClock::elapsed() const
00287 {
00288 LARGE_INTEGER ticks;
00289 QueryPerformanceCounter( &ticks );
00290
00291 const double dt = ticks.QuadPart - d_startTicks.QuadPart;
00292 return dt / d_ticksPerSecond.QuadPart * 1e3;
00293 }
00294
00295 #endif
00296
00297 #endif // QWT_HIGH_RESOLUTION_CLOCK
00298
00299 class QwtSystemClock::PrivateData
00300 {
00301 public:
00302 #if defined(QWT_HIGH_RESOLUTION_CLOCK)
00303 QwtHighResolutionClock *clock;
00304 #endif
00305 QTime time;
00306 };
00307
00309 QwtSystemClock::QwtSystemClock()
00310 {
00311 d_data = new PrivateData;
00312
00313 #if defined(QWT_HIGH_RESOLUTION_CLOCK)
00314 d_data->clock = NULL;
00315 if ( QwtHighResolutionClock::precision() > 0.0 )
00316 d_data->clock = new QwtHighResolutionClock;
00317 #endif
00318 }
00319
00321 QwtSystemClock::~QwtSystemClock()
00322 {
00323 #if defined(QWT_HIGH_RESOLUTION_CLOCK)
00324 delete d_data->clock;
00325 #endif
00326 delete d_data;
00327 }
00328
00332 bool QwtSystemClock::isNull() const
00333 {
00334 #if defined(QWT_HIGH_RESOLUTION_CLOCK)
00335 if ( d_data->clock )
00336 return d_data->clock->isNull();
00337 #endif
00338
00339 return d_data->time.isNull();
00340 }
00341
00345 void QwtSystemClock::start()
00346 {
00347 #if defined(QWT_HIGH_RESOLUTION_CLOCK)
00348 if ( d_data->clock )
00349 {
00350 d_data->clock->start();
00351 return;
00352 }
00353 #endif
00354
00355 d_data->time.start();
00356 }
00357
00362 double QwtSystemClock::restart()
00363 {
00364 #if defined(QWT_HIGH_RESOLUTION_CLOCK)
00365 if ( d_data->clock )
00366 return d_data->clock->restart();
00367 #endif
00368
00369 return d_data->time.restart();
00370 }
00371
00376 double QwtSystemClock::elapsed() const
00377 {
00378 double elapsed = 0.0;
00379
00380 #if defined(QWT_HIGH_RESOLUTION_CLOCK)
00381 if ( d_data->clock )
00382 {
00383 if ( !d_data->clock->isNull() )
00384 elapsed = d_data->clock->elapsed();
00385
00386 return elapsed;
00387 }
00388 #endif
00389
00390 if ( !d_data->time.isNull() )
00391 elapsed = d_data->time.elapsed();
00392
00393 return elapsed;
00394 }
00395
00396 #endif