PDA

View Full Version : QTimer, what happens if QTimers times out before the calling function is ready?



Teuniz
5th March 2007, 15:27
I have a question about QTimer and I couldn't find an answer in the Qt doc.

I connect a QTimer to foo();

What will happen if foo() takes more time than the timeout of QTimer?

Will foo() be called again even when the former call to foo() hasn't ended yet?

If the timeout of QTimer (no-singleshot) is for example 100milliSeconds,
and foo() takes one second to return, what will QTimer do?

guilugi
5th March 2007, 16:30
That's a really good question, and I'd like to know the answer too...My guess would be that foo() will be called a second time..
You just have to test it :)

kiker99
5th March 2007, 17:50
After having studied Qt Code, I think it's like this:

1. You only have one thread (default)
Only one part of code can be executed at the same time. So the slot can't be executed two times in parallel. As long as the called function is running, it isn't possible for Qt to return to the event loop. So also no QTimerEvents (internal Implementation used by QTimer) will be sent to the Object. This, again, leads to no timeout before the event loop is reached. In the event loop, times are checked for all activated timers. There, Qt will notice that the Timer has timed out, send a QTimerEvent, which is caught by the QTimer. QTimer, again, emits timeout(), which is executed immediately if you haven't state which sort of connection you want (Qt::AutoConnection). So the game starts again with the called function being executed.
If you create a SharedConnection, the function will be executed in the event loop - not immediately. But this doesn't change the situation, because the event loop must do one thing after another and it doesn't check the timers while the function is being executed.

2. You have the QTimer in one thread and the called function in another thread
I haven't verified this, but this is what I think will happen: The Thread containing the timer - having its own event loop - will be able to queue the timeout-Connections immediately when the timer times out.
The other thread will execute all invocations received, no matter how long this takes. So I think it would be possible to send 1 million invocations in a few seconds from thread one to make thread two work for a whole day (theoretical ;) ).

wysota
5th March 2007, 18:59
2. You have the QTimer in one thread and the called function in another thread
I haven't verified this, but this is what I think will happen: The Thread containing the timer - having its own event loop - will be able to queue the timeout-Connections immediately when the timer times out.
Not quite. It will be queued when control returns to the event loop of the sending thread. This is very important. Why? Read on below.

he other thread will execute all invocations received, no matter how long this takes. So I think it would be possible to send 1 million invocations in a few seconds from thread one to make thread two work for a whole day (theoretical ;) ).
AFAIK timeouts are compressed therefore if you have a timer that times out every... say... 2 seconds, but you are currently in a function that takes 10 seconds to exectute, there will only be one timeout instead of 5 as you might suspect. So the "other thread" (also it's the same for single threaded applications) will truly execute all timeouts it receives, but it may receive less timeouts than you might suspect based on the time passed between starting the timer and posting the event.

kiker99
5th March 2007, 22:01
ok, this is more logical from the user point of view. +1 for Trolltech.

Brandybuck
6th March 2007, 06:34
AFAIK timeouts are compressed therefore if you have a timer that times out every... say... 2 seconds, but you are currently in a function that takes 10 seconds to exectute, there will only be one timeout instead of 5 as you might suspect.
In terms of the behavior, that is essentially correct, though the implementation is somewhat different. At the end of the event loop, the application checks to see if any timers have timed out. If so, signals are emitted. The key is that the signal is not emitted on the exact millisecond that the timeout occurs, but rather checked for at the end of the event loop. This makes it possible to "starve" the timers, which is what the 10 second foo() method above is doing to the poor 5 second timer.

This also leads to an interesting trick you can do with Qt: idle processing. A QTimer with a zero second timeout will have its connected slot called whenever there are no pending events to handle.