What happens if I start a QTimer firing at regular intervals but the slot reacting to the timeout signal blocks the main loop for longer than another timer interval. Will the timout signals then be stacked on the Qt main event loop and processed one after another as soon as the event loop runs again?
If yes, what happens if multiple timeout events are stacked on the event queue but the timer is deactivated before they can be processed?
If QTimer object and the signal receiver belong to one thread, no queuing happens. timeout() signal will not (and cannot) be sent again until control flow goes to the event loop, and that won't happen until the slot is completely executed (unless QApplication::processEvents is called in the slot, which can turn this into a mess). But if your slot was being executed longer than the timer's interval, timeout() will be sent once the event loop is free, so your slot will be immedately called again. But QTimer will not send two timeout() signals closer than its interval.
If QTimer is in another thread, and that thread is not busy with something else, it will send timeout() signals regularly regardless of how well slot in another thread goes. This is where Qt's signal-slot system comes in. And it will queue emitted signals. If your slot is slow, it will call it multiple times without delay. If you stop the timer, it won't undo already sent signals and the slot may be called multiple times after it. Additionally, if you stop the timer, there is always a possibility that another signal is being sent just in this moment and your slot will be called once again.
If you want strict intervals between slot invocations regardless of the slot's executing time, you should use single-shot timers. At the end of your slot, start a single-shot timer. When it's timed out, it will invoke your slot and deactivate, so you can start it again at the end of the slot.
If your program's logic depends on the timer's state, you should check that the timer is active at the start of your slot. It's not guaranteed that the timer is active when the slot is being executed.
Related
I discovered quite by accident that instead of the normal style of emitting a signal previously connected to a slot, another way to trigger the slot is:
emit(slotname());
I like that I can skip the step of creating a signal and connecting, but does this REALLY cause the slot to be handled through the event queue? Or is this just calling the slot method directly?
No. emit(slotname()) equals to (slotname()), which merely calls slotname() directly without queue. And it won't automagically call other slots connected to the signal.
emit is actually a macro that evaluates to nothing. It's just a syntactic sugar to show that the code is emitting a signal. Thus the following line
emit nameChanged()
is equivalent to
nameChanged()
It's nothing special, you are actually calling the nameChanged() signal method. The difference is that you don't implement the signal method yourself. You leave Qt's moc to generate the implementation. The generated implementation will call all connected slots, directly or through queue depending on how connections were made and the executing thread.
Therefore, emit(slotname()) defeats the purpose and confuses code readers.
If you are curious, emit is defined in QtCore\qobjectdefs.h:
# define emit
I am developing a consequent program which is very sensitive to time (based on delayed video streams), and since I'm not sure about how the signals and slots are implemented within Qt, I don't know when they are executed. Are they really executed in real time like callbacks would do, or are they processed before the next iteration of some kind of main loop?
My question would be about timers in particular: when a timer times out (which must be another thread), does it connect to the signal "instantaneously" (next instruction for example) nearly like an interrupt would do, or does it wait for the end of some loop?
Thanks for your insight,
Regards,
Mister Mystère
The last argument of QObject::connect is the connection type, which determines when slot will be executed. From the documentation:
Qt::AutoConnection - If the signal is emitted from a different thread than the receiving object, the signal is queued, behaving as
Qt::QueuedConnection. Otherwise, the slot is invoked directly,
behaving as Qt::DirectConnection. The type of connection is determined
when the signal is emitted.
Qt::DirectConnection - The slot is invoked immediately, when the signal is emitted.
Qt::QueuedConnection - The slot is invoked when control returns to the event loop of the receiver's thread. The slot is executed in
the receiver's thread.
Qt::BlockingQueuedConnection - Same as QueuedConnection, except the current thread blocks until the slot returns. This connection type
should only be used where the emitter and receiver are in different
threads.
http://woboq.com/blog/how-qt-signals-slots-work.html
This seems to be quite a good description, though I haven't read it in detail.
Main point: there's direct connections and deferred connections. Direct connections are executed immediately.
You can be quite sure the timer is not implemented in a different thread but instead is handled inside the event loop. Which means that when the timer fires, it is instantly connected. However the granularity for the timer to fire is your main problem.
If your timer were to emit the signal in a different thread, the slot would be called in the thread the receiving object belongs to. Which means that it would be deferred to the event loop. (As you can see it would not help to have the timer operate in a thread of its own.)
And additionally in Qt5 you can set QTimer's precision: Qt::TimerType
I am making an application in QT. I use QExtSerialPort to receive data from the serial port of my comp (whenever the readyread() signal is emitted). I also have some timers running doing other stuff at certain intervals. Now I noticed that when the timers are turned on, not all the data of the readyread signal is emitted a lot less, then when the timers are not turned on. Is there a way in QT to make sure that all the data of the serial port is received? Maybe by setting a high priority to the readyread event or something like that?
There is difference between signal-slot connections and event system. Signal emitting and slot triggering are not separate things — when signal is emitted, connected slots begin to work. So they (signals) can't be lost.
All events are sent through application, and also are received, but it can happen later. When control returns to the main event loop, all events that are stored in the queue, will be processed.
If you are posting events yourself, you can use
static void QCoreApplication::postEvent ( QObject* receiver, QEvent* event, int priority ); method.
Events are sorted in descending priority order, i.e. events with a high priority are queued before events with a lower priority. The priority can be any integer value, i.e. between INT_MAX and INT_MIN, inclusive; see Qt::EventPriority for more details. Events with equal priority will be processed in the order posted.
I always use QObject::connect() in all my applications but it is not clear to me its effect when my program is currently inside a function. Suppose I have the following code:
void main() {
//other stuffs here
QObject::connect(xxx,SIGNAL(yyy()),this,SLOT(zzz());
}
void aFunction()
{
//a bunch of codes here
//i am here when suddenly signal is emitted from QObject::connect();
//another bunch of codes here
}
I assume that when the signal is emitted, QObject::connect leaves the function "aFunction()" to execute "zzz()". What will happen to the remaining codes in the "aFunction()"
Thanks.
I can understand the confusion, coming from procedural to event based programming gives me same experience like you do now.
Short answer:
in non multi threaded environment, slot zzz() will be executed after aFunction() finishes. In fact, the signal probably gets emitted after aFunction finishes.
in multi threaded env., same thing but it is "after some time", not after.
Key to understanding this is Event Loop. QApplication::exec() runs a forever loop polling for event. New event is then handled, signals get emitted and depending on the fifth argument of QObject::connect which is a Qt::ConnectionType, ultimately runs the connected slot. You can read QObject documentation for more detail..
So your aFunction probably gets called after some signal, so after it is finished, it's back to event loop again, then your 'suddenly emitted' signal actually gets emitted and zzz is executed.
Even in multi threading environment, inter thread signals and slots work with Qt::QueuedConnection which basically just posts the emitted signal to corresponding thread so that when that thread's event loop come around to process it - it will be executed sequentially as well.
Ultimately what you will have to remember is that this Turing Machine called computers is executing sequences of codes, whether it's semi paralel (e.g time sharing, pipelining) or truly paralel (e.g multi cores, multi cpu) the part where codes get sent (or distributed? or fetched?) to its execution will always run in sequences or in one or more ways have to be simulated to be sequential so that no code is executed twice in multiple execution node.
There is no "suddenly"
I'm writing a simple port communication program. On the GUI side of the application I have a panel with 12 buttons that send signals to the parallel port interface. The communication with the port is done and working. What I need now is an automatic switching between buttons. The goal is to start kind of screensaver that will periodically activate the buttons and send signals to the port. In practice it would look like this: a timer is started for 2 minutes and if any event occurs it is restarted. Otherwise if timer reaches timeout() the qt signal is emitted, the switching begins and the buttons are automatically click()'ed with the interval of 5 seconds.
My questions are:
How to enable a starting timer that will be reseted if any key/mouse event occurs?
How to define a transition between the buttons with a sleep interval?
Use QTimer for the timing part.
For the "screen-saver"-like one, create a single-shot timer, connect it to a custom slot of yours, and set it's interval to two minutes.
activeTimer = new QTimer(this);
activeTimer->setInterval(2*60*1000);
activeTimer->setSingleShot(true);
connect(activeTimer, SIGNAL(timeout()), this, SLOT(activateAutoClick()));
activeTimer->start();
In that custom slot, start a second, non-single shot timer connected to a second custom slot
void YourThing::activateAutoClick() {
autoTimer->setInterval(5*1000);
autoTimer->setSingleShot(false);
connect(autoTimer, SIGNAL(timeout()), this, SLOT(autoClick()));
autoTimer->start();
}
And do whatever you want in terms of sending signals to your port in autoClick.
To cancel either timer, simply call their stop() method/slot.
To implement the "screen-saver" behavior, create a function that:
Calls autoTimer->stop() to disable auto clicks
Calls activeTimerr->start(2*60*1000) to restart that one
And call that function whenever needed. You can do that from already existing slots for your buttons, or reimplement event handlers like QWidget's mouseMoveEvent, keyPressedEvent and such. (Be sure to read the documentation for the handlers, some require specific preparation.)