Watching for event loop's iterations and discarded QTimerEvents
-
Hi,
I'm coding some QObject's subclasses that watch for event loop's iterations in order to wrap functionalities of third-party libraries and still have fun with Qt's signals and slots. Since I want to try every possibilities offered by Qt, I've already found several solutions:
- using an other subclass of QObject in order to watch these iterations with queued connections,
- using a QTimer instance with a null interval,
- and using QObject::timerEvent with either QObject::startTimer or QBasicTimer (both of them also with a null interval).
If you have some other solutions, I'll be glad to hear them... I mean, to read them.
By the way, I've read in the documentation of QObject::startTimer that QTimerEvents may be silently discarded, if they are too many for Qt and the system. Is there any threshold beyond which QTimerEvents start to be dropped? On the other hand, may Qt's signals also be discarded if they are numerous?
Thank you in advance for your help.
-
The topic is quite broad. What exactly do you want to monitor? When the loop pass starts/ends?
Timer events are dropped if there's more of them waiting in a queue. If you have a a timer that should fire every 1s and the loop is blocked by some operation for 5s you don't want to get 5 of them in a burst. The same is with update events. You don't want 5 paintEvents delivered in a burst.
Timer with 0 interval can't really be dropped because it means "deliver as soon as possible". As soon as possible is when the event queue is next processed, so there's no possibility that they will stack.In general events are not "dropped". If anything they can be compressed (or merged). For example if two mouse move events stay too long in a queue they can be delivered as a single larger move. Same goes for resize events and the like. There's also a opt-in setting for keyboard compression via
Qt::WA_KeyCompression
attribute.If you want more control over what is processed when you can take a look at manually calling processEvents instead of running a built-in loop or go even deeper with your custom implementation of QAbstractEventDispatcher.
-
The topic is quite broad. What exactly do you want to monitor? When the loop pass starts/ends?
Timer events are dropped if there's more of them waiting in a queue. If you have a a timer that should fire every 1s and the loop is blocked by some operation for 5s you don't want to get 5 of them in a burst. The same is with update events. You don't want 5 paintEvents delivered in a burst.
Timer with 0 interval can't really be dropped because it means "deliver as soon as possible". As soon as possible is when the event queue is next processed, so there's no possibility that they will stack.In general events are not "dropped". If anything they can be compressed (or merged). For example if two mouse move events stay too long in a queue they can be delivered as a single larger move. Same goes for resize events and the like. There's also a opt-in setting for keyboard compression via
Qt::WA_KeyCompression
attribute.If you want more control over what is processed when you can take a look at manually calling processEvents instead of running a built-in loop or go even deeper with your custom implementation of QAbstractEventDispatcher.
@Chris-Kawa said:
The topic is quite broad. What exactly do you want to monitor? When the loop pass starts/ends?
[...]
Actually, I just want to code some abstract class whose children will encapsulate features of third-party libraries that are meant for standard C/C++ (e.g. ffmpeg). Watching for event loop iterations will allow my future classes to notify any state changement, almost as soon as they occur, using fancy signals.
@Chris-Kawa said:
[...]
Timer events are dropped if there's more of them waiting in a queue. If you have a a timer that should fire every 1s and the loop is blocked by some operation for 5s you don't want to get 5 of them in a burst. The same is with update events. You don't want 5 paintEvents delivered in a burst.
Timer with 0 interval can't really be dropped because it means "deliver as soon as possible". As soon as possible is when the event queue is next processed, so there's no possibility that they will stack.In general events are not "dropped". If anything they can be compressed (or merged). For example if two mouse move events stay too long in a queue they can be delivered as a single larger move. Same goes for resize events and the like. There's also a opt-in setting for keyboard compression via
Qt::WA_KeyCompression
attribute.[...]
That means that I'll actually never lose any event but they can eventually get merged if many of the same kind bloat the event loop or are about to. Good to know, indeed.
@Chris-Kawa said:
[...]
If you want more control over what is processed when you can take a look at manually calling processEvents instead of running a built-in loop or go even deeper with your custom implementation of QAbstractEventDispatcher.
I haven't reached that point, yet. ;)
Thank you for your help.
-
libraries that are meant for standard C/C++
Qt is standard C++ too.
Watching for event loop iterations will allow my future classes to notify any state changement
I don't think you're on the right track. You don't need to watch event loop for that. I would certainly not use timers for that. Usually when you want to use another library in Qt app you just wrap around it with a QObject derived class and emit signals. For example:
class Foo : public QObject { Q_OBJECT public slots: void doStuff() { callSome3rdpartyAPI(m_someState); emit stuffIsDone(); } signals: void stuffIsDone() const; private: Some3rdPartyState m_someState; };
Then you just connect to the signal in a usual Qt way.
If you want to run external processes (e.g. ffmpeg) and watch for its input/output you can use QProcess and connect to various signals it provides.
-
libraries that are meant for standard C/C++
Qt is standard C++ too.
Watching for event loop iterations will allow my future classes to notify any state changement
I don't think you're on the right track. You don't need to watch event loop for that. I would certainly not use timers for that. Usually when you want to use another library in Qt app you just wrap around it with a QObject derived class and emit signals. For example:
class Foo : public QObject { Q_OBJECT public slots: void doStuff() { callSome3rdpartyAPI(m_someState); emit stuffIsDone(); } signals: void stuffIsDone() const; private: Some3rdPartyState m_someState; };
Then you just connect to the signal in a usual Qt way.
If you want to run external processes (e.g. ffmpeg) and watch for its input/output you can use QProcess and connect to various signals it provides.
@Chris-Kawa said:
libraries that are meant for standard C/C++
Qt is standard C++ too.
[...]
Indeed. I actually meant "pure standard C++", i.e. third-party library that only use STL's features. Nonetheless, I think it also concerns every library that does not use any Qt's features.
@Chris-Kawa said:
[...]
Watching for event loop iterations will allow my future classes to notify any state changement
I don't think you're on the right track. You don't need to watch event loop for that. I would certainly not use timers for that. Usually when you want to use another library in Qt app you just wrap around it with a QObject derived class and emit signals. For example:
class Foo : public QObject { Q_OBJECT public slots: void doStuff() { callSome3rdpartyAPI(m_someState); emit stuffIsDone(); } signals: void stuffIsDone() const; private: Some3rdPartyState m_someState; };
Then you just connect to the signal in a usual Qt way.
[...]
I've observed so far, that state of some third-party components, especially IO components, may change while none of their functions/methods have been eventually called and must therefore be frequently tested.
On the other hand, it can also be quite handy to use what I want to code, when a simple task has to be repeated a huge number of times, whereas multithreading is just not possible. By "huge number of times", I mean a number big enough for the task iteration to last a long time and make that the system think the program has frozen or even crashed.@Chris-Kawa said:
[...]
If you want to run external processes (e.g. ffmpeg) and watch for its input/output you can use QProcess and connect to various signals it provides.
An other interesting topic, actually. I should take a closer look to it when I work on a program/library that automatically produces LaTeX documents and has them "compiled" using external programs.
-
I've observed so far, that state of some third-party components, especially IO components, may change while none of their functions/methods have been eventually called and must therefore be frequently tested.
If there's no other way you can probe it with QTimer, that should be fine. You don't need to do anything fancy with events or the loop. If the other API provides anything - like a callback or any other ways of signaling state change you should prefer that and wrap it in signals. It will feel more natural with Qt for sure. There are also Qt facilities like QSerialPort or QLocalSocket that might be of some use in such scenarios.
On the other hand, it can also be quite handy to use what I want to code, when a simple task has to be repeated a huge number of times, whereas multithreading is just not possible.
Sounds like a perfect candidate for multithreading. There's a minimalistic QtConcurrent interface for small tasks. What kind of scenarios do you have in mind that aren't feasible for threading?