Question:
Hello everyone! Can someone please clarify the mechanism of the qt timer. Does it form a message in the message queue or does it affect the processing of this queue?
For example: Let's say we have a function that creates a signal and puts it in the thread's queue. This calls the thread slot in which we call the same function. In theory, as soon as we finished processing the slot, we go to the processing queue, there we see a new signal, and again we go into the slot.
Now if there is a timer on the same thread. Will it queue timeout messages in parallel with the slot, as if from another thread? Will he be able to interrupt my eternal cycle above? Or does he just put a checkbox somewhere in the message queue handlers and the timer signal is called at the right time?
UPD: Thanks for both answers, I preferred the second answer, since it is still more complete and closer, as it seemed to me, to what I was asking.
To summarize the understanding of the timer device: The timeout signal is generated at the moment of returning to the parsing of the message queue, it is there that the necessary messages from the operating environment are obtained and it is determined that the timer has expired. Therefore, without returning to the parsing of the event queue, the timer will not appear, just as they cannot be blocked if there are returns to the message queue. It is important that the return forms precisely the birth of the signal, and not only its processing, the signal will not be born until the return.
Answer:
A bit out of the way … If a signal is connected to a slot with the Qt::AutoConnection
(default) or Qt::DirectConnection
flag, and the called slot belongs to an object in the same thread as the object from which the signal is emitted, then no the event queue handler is not called. The slot is called right on the spot. If this slot calls itself by means of a direct connection via a signal, then an infinite recursion will occur, up to a stack overflow, and of course the inevitable crash of the application.
In order for the signal-slot connection to be triggered through a queue within the same thread, you must always explicitly specify the Qt::QueuedConnection
. Only in this case, the corresponding inheritor of the event class is created, which is placed in the event queue.
The internal implementation of QTimer
uses methods for registering timers of the operating system on which the application is running (this allows you to specify additional flags to the timer, in case you need, for example, increased accuracy). Accordingly, it is she who generates events that the time of such and such a timer has expired again. The exact same events are received when the mouse cursor moves and the keys are pressed. These native events are added to the application's event queue one by one.
All events are processed strictly in turn. Here, as never before, the rule is true: "Whoever got up first, that and the slippers." This means that if the timer is created with an accuracy that allows a certain error in the interval, then timer events will be processed at an unpredictable (within the error, of course) interval and may be queued before or after any other event.
If the timer object exists in a separate thread, which has its own event queue, and at the same time tries to call a slot of an object located in another thread, then the event about the slot call will go to the event queue of the target thread. In this case, exactly the same rule about sneakers will apply: if there are already some events before the incoming event, then they will be executed first, and the timer event for calling the slot will wait for its turn.
However, there are pitfalls, the possibility of which should be borne in mind. Suppose you have the following scheme:
Event A : slot SLOT calls itself through the event queue;
Event B : the timer calls SLOT at a certain interval;
The result is the following:
Calls A will follow each other, as expected. Since each new event always ends up at the end of the queue, call B after some time will wedge into the order of calls to A without any problems. However, each call to the slot SLOT always generates a new call to A. Thus, after each B, not one new A will be generated, but the second, third (etc.) infinite cycles from A.