Unsolved How to create a watchdog timer in Qt
-
hi
What should the dog watch ?
Can you say a little bit more about the function you are after? -
I'm sorry, I thought that it was a common term. I guess not.
A watchdog timer is one that counts down from a preset value. Incoming events can reset it to its original value and thereby preventing it from timing out. If there is an absence of triggers for long enough it times out and triggers an action.
In my case, I have updates to some data that comes in bursts of indeterminate size. I would like to wait until there have been no updates for 10ms or so before updating the screen so they can all be handled in a batch. This would be much more efficient.
I originally thought that a QTimer in singleshot mode would do the trick, but you can only trigger it once and there is no way to restart it.
-
Hi,
QTimer is the right tool. Make one member of your class, configure it as single shot and you can then restart it as needed.
-
@mjsurette said:
there is no way to restart it
You can restart the timer by calling
[slot] void QTimer::start()
again. -
I must be missing something.
This simple test program should have two timeouts, at 6 and 16 seconds in. But only one registers, and that's at the close of the program.
#include <QCoreApplication> #include <QTimer> #include <QDebug> #include <QDateTime> #include <unistd.h> qint64 starttime; void timeout() { qDebug() << "timeout:" << QDateTime::currentMSecsSinceEpoch()-starttime; } int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); QTimer wd; wd.setSingleShot(true); QObject::connect(&wd,&QTimer::timeout,&timeout); starttime= QDateTime::currentMSecsSinceEpoch(); qDebug() << "start:" << QDateTime::currentMSecsSinceEpoch()-starttime; for (int i=0;i<20;++i) { qDebug() << i; if (i==1 || i==11) wd.start(5000); sleep(1); } qDebug() << "done:" << QDateTime::currentMSecsSinceEpoch()-starttime; return a.exec(); }
-
The event loop is not running while you're in that for loop so your timer will only run once.
-
I must be missing something.
Timer events are processed in the event loop (
exec()
call). You restart the timer 20 times before the loop even starts, so only the last one actually is processed (emits atimeout()
signal). -
Thanks for the explanation. I'll refactor my test program.
-
@mjsurette said:
In my case, I have updates to some data that comes in bursts of indeterminate size. I would like to wait until there have been no updates for 10ms or so before updating the screen so they can all be handled in a batch. This would be much more efficient.
If I understand correctly you want to block event processing for a given amount of time, which doesn't exactly play well with
QTimer
. You can have a timed wait on a locked synchronization primitive for that:QSemaphore lock(0); lock.tryAcquire(1, 1000); // Wait 1s for the semaphore to be released.
Note: If I've misunderstood, and you want not to block the event loop, then this is certainly not the solution.
PS. Another way for a blocking wait with event processing is by using a local event loop:
QObject * emitter; //< This is the object that will emit a signal when something happened and the wait should interrupt QEventLoop loop; QObject::connect(emitter, SIGNAL(interruptWait()), &loop, SLOT(quit())); loop.exec(); // Wait until interruptWait() has been called
Kind regards.
-
Just making sure you keep in mind the inherit limitations of qtimer. Qt is not a real time system. See the documentation http://doc.qt.io/qt-5/qtimer.html for more information.
An alternative to batching by time, is to simply batch by size. It will be easier to write and the behaviour will probably be more consistent.
-
@t3685 said:
Qt is not a real time system. See the documentation http://doc.qt.io/qt-5/qtimer.html for more information.
Nothing to do with Qt. It's the limitation of the underlying OS you have to take in mind.
-
@mjsurette
Just a note:
WatchDog -is- a common term, i just wanted to hear what your overall
goal was with it
as there are many way to program a watchdog. :)