[Solved] Are signals handled in the order sent (C++ to Qml)?
-
I am sending signals from a C++ class to the Qml (javascript) code of a QtQuick2 application. What I need to know is whether these signals that I emit are processed in the same order as I send them?
I understand the sending is asynchronous, but I do not know whether the processing is in order. The docs I have read emphasize the asynchronous nature of sending a signal, but I could not find docs specifying the order of processing.
Can anyone indicate which is the case? Also, if it is not in order, is there a way to guarantee that the signals are processed in the order sent?
-
A queue is used internally, but you should not count on that. Signals are handled in the order they were connected, not sent.
If you send a signal directly (Qt::DirectConnection), it will be executed immediately, so you can theoretically assume that. If you send using Qt::QueuedConnection, all bets are off: the slot can be invoked any time.
To sum up: it is best and safest not to assume anything about the order of execution of slots. However, in some situations, a repeatable order can be observed.
-
I just wanted to clarify one thing here.
sierdzio said that signals are handled in the order they were connected, not sent. This only applies to multiple slots connected to single signal. In that case when a signal is emitted slots are indeed executed in connection order.
This does not apply however to a situation with multiple signals with a single slot connected to each. In this case the order of slot execution is independent of connection order. As also pointed by sierdzio - if the connection type was direct then the slots are invoked in order of signal emission and it's ok to assume that. Order of queued connection delivery is unspecified (to my knowledge) and should not be relied on.
-
So that means that if order is important I should group signals into one signal, so the processing code (in this case qml) can make sure it is processed in order.
Not sure about Qt::DirectConnection or Qt::QueuedConnection, I just use signals and catch them from Qml. Never used any of those, so I looked them up and found these docs (5.4. Threads and objects):
Qt supports these signal-slot connection types:
- Auto Connection (default) If the signal is emitted in the thread which the receiving object has affinity then the behavior is the same as the Direct Connection. Otherwise, the behavior is the same as the Queued Connection."
- Direct Connection The slot is invoked immediately, when the signal is emitted. The slot is executed in the emitter's thread, which is not necessarily the receiver's thread.
- Queued Connection 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.
This actually means that depending on the thread I am using direct or queued connection. Accross threads I could use Direct Connection, provided I specify it in connect(). Without specification I am using Auto Connection.
Ok, thanks. That helps.
-
bq. Accross threads I could use Direct Connection, provided I specify it in connect()
This is (almost always) not a good idea because of this part: " The slot is executed in the emitter’s thread, which is not necessarily the receiver’s thread." This means that if the signal is emitted, a slot modifying an object living in another thread can race with the code that happens to execute in that thread.
For example if some code calls a slot foo() in the worker thread and the same slot is connected to signal emitted from the thread you can have two simultaneous executions of foo() in two threads, which, if not correctly synchronized will lead to trouble. -
Yes, I did not realize that. The way I read it, the documentation suggests it is "ok" to execute DirectConnection from different threads. It might benefit from a remark concerning race conditions and/or synchronization mechanisms.
Thanks for pointing that out.
-
Well it is ok if you know what you're doing and the slot is not racing with anything (but then what's the point of such slot). It's just not something that you normally want, hence the auto connection type that chooses the safe thing by default.