High Resolution Timer
-
Does anyone know of any 'reliable' high resolution timers for Windows / Linux that can be used within Qt? My target platforms currently are Windows / Linux.
Basically, the functionality I am looking for (for accurate / consistant looping in a thread), is a timer with resolution of 1mS or better that I can:
SetType(int type, int mS) // periodic / or one shot
Start() // start the timer
Clear() // stop the timer
Wait() // wait for the remaining amount of time left on the timer (blocking call)
Poll() // poll the timer to see if the timer has elapsedI can do this on Linux using a non-qt solution with posix timerfd / poll() and get microseconds resolution, but for what I am reading about windows, it is all dependent on the system hardware (I can always wrap the linux stuff in an ifdef PLATFORM, but theres still windows).
QElapsed timer can be manipulated to what I need minus the wait() for time to finish, but can anyone say that the resolution of QElapsed timer is indeed 1mS or less independent of the system hardware with windows?
I know there is a lot that comes into play with timing but I was hoping someone might have a solution... Thank you!
-
I am not an expert on the subject, but I see in "QElapsedTimer documentation":http://qt-project.org/doc/qt-4.8/qelapsedtimer.html#details that there is a high resolution clock special for Windows.
QElapsedTimer::PerformanceCounter
The high-resolution performance counter provided by Windows. This clock is monotonic and does not overflow.Why don't you try it?
-
Well, I have looked at the source code for QElapsedTimer already and it uses QueryPerformanceFrequency / QueryPerformanceCounter which from the looks of all of the forum posts online, both of those are limited because of hardware.
This is what I am working with so far:
@
#ifndef HIGHPRECISIONTIMER_H
#define HIGHPRECISIONTIMER_H#include "utility_global.h"
#include <QObject>
#include <QElapsedTimer>
#include <QMutex>
#include <QWaitCondition>// high precision timer class
class UTILITYSHARED_EXPORT HighPrecisionTimer : public QObject
{
Q_OBJECTQMutex _waitMutex; QWaitCondition _waitSleep;
public:
HighPrecisionTimer(QObject *parent = 0);
bool setInterval(int ms);
int msInterval();
void start();
void wait();
bool poll();
void restart();
QElapsedTimer timer();private:
void blockingSleep(unsigned long ms);QElapsedTimer _timer; qint64 _interval; qint64 _reference;
};
#endif // HIGHPRECISIONTIMER_H
#include "highprecisiontimer.h"
#include <QDebug>/*
// class constructor
*/
HighPrecisionTimer::HighPrecisionTimer(QObject *parent) :
QObject(parent)
{
_interval = 0;
_waitMutex.lock();
}/*
// set interval (public function)
*/
bool HighPrecisionTimer::setInterval(int ms)
{
if (!_timer.isValid()){
_interval = ms;
return true;
}
else
return false;
}/*
// millisecond interval (public function)
*/
int HighPrecisionTimer::msInterval()
{
return _interval;
}/*
// start high precision timer (public function)
*/
void HighPrecisionTimer::start()
{
_timer.start();
_reference = _timer.elapsed();
}/*
// wait until elapsed time has been triggered (public function)
*/
void HighPrecisionTimer::wait()
{
// calculate the remaining time left
qint64 elapsedTime = _timer.elapsed();
qint64 leftOver = _interval - (elapsedTime - _reference);// if the difference is positive, then sleep for remaining time if (leftOver > 0) blockingSleep(leftOver); // new reference _reference = _timer.elapsed();
}
/*
// restart timer (public function)
*/
void HighPrecisionTimer::restart()
{
_timer.restart();
}/*
// blocking sleep (private function)
*/
void HighPrecisionTimer::blockingSleep(unsigned long ms)
{
_waitSleep.wait(&_waitMutex, ms);
}/*
// poll the timer to see if it has expired (public function)
*/
bool HighPrecisionTimer::poll()
{
// calculate the remaining time left
qint64 leftOver = _interval - (_timer.elapsed() - _reference);// if the difference is positive, then sleep for remaining time if (leftOver > 0) return false; else return true;
}
/*
// return the timer (public function)
*/
QElapsedTimer HighPrecisionTimer::timer()
{
return _timer;
}
@ -
But the question is WHY do you need the high resolution timer? In basic the OS will only call your application ones every 1..15msec depending on the "free" time of the CPU. Therefor every Event set (timerEvent) is only handled then. So a "slow" 5msec timer is also too quick for a normal working Windows machine. All timers below 10msec are usually not running on time.
Maybe If we understand what you need to achieve we are able to better assist you and give alternatives. Sometimes the solution will come with a different approach ;-) -
I apologize for the confusion and my vagueness.
Basically, I created a Qt Console application that contains 3 Qt Dll's. When everything starts up, I gather some information from the inifile to see what Dll's are going to be used.
Each Dll has one main function that gets run in a thread (I could use QThread and use the Run() method, but I wanted custom input arguments). I am basically creating a sub process, but one I can keep track of using Qt Concurrent.
The threads will run / loop for the life of the application.
For example
@
/*
// spawned by Qt Concurrent
*/
int some_process_in_dll( ... input arguments)
{
// this is where I thought I would setup my high precision timer
// set its desired time
timer->setTime(5);
timer->start();while (1){
// main process occurs here
// for example, send tcp data
// receive tcp data....etc.
//
// say this takes...2 mS to do// wait if there is any leftover time, in this example it would wait/block for 3 mS timer->wait();
}
}
@The wait is very important, so I can delay for the remaining time left over. If there isn't any time leftover and the process took more than 5mS then It will not block and just loop again.
-
Again, everything below 10 msec is FAST if using a Win machine. It might operate properly if timers below this are used, but for realtime operation this is a rule of thumb. If using embedded Linux etc you could go much faster because the overhead of the OS is limited. But I lost your first question here. If the 5msec timer is set it will trigger the timeout signal, no problem. When the timer expires twice before the thread is complete it will run again, so you won't miss a data transmission to your external device. Not really a problem there, unless your external device already fails because of the delay between sending data?
Your solution will never work, you state in your comment that you execute a "main" in the thread that takes 2 msec or about that, but you have 3 thread + your main thread running, so how is the OS every going to do it all in time? Your execution of code already exceeds 6 msec!
Maybe a solution might be to have all the "main" codes in a single thread. In here you parse the data from/to the data thread via signals/slots. In the data thread only have a timer and a send/receive data to parse the data. This will minimize the cpu load of the threads, but might cause "older" data to be send to the external device. -
I found this nice "summary...":http://www.boost.org/doc/libs/1_54_0/libs/timer/doc/cpu_timers.html#Timer-accuracy