[SOLVED]Safety of references as arguments to emitted signals
-
In a single-threaded application, is it safe to pass an argument by reference when emitting a signal? I'm guessing it isn't, but would like confirmation.
@DRoscoe said:
In a single-threaded application, is it safe to pass an argument by reference when emitting a signal? I'm guessing it isn't, but would like confirmation.
It's perfectly safe in both single- and multi-threaded applications. Notice that, for example, QLineEdit emits the textChanged() signal with a
const QString&
argument.In a single-threaded application, the default connection type is a Qt::DirectConnection. When the signal is emitted, the connected slots are immediately called one after the other, with the signal argument passed directly to each slot. In other words, the top-level function which emitted the signal is blocked until all the slots have returned.
When connections are made between different threads, the default connection type is a Qt::QueuedConnection. (You can manually choose this type for connections within the same thread, if you wish.) When the signal is emitted, the signal arguments are copied into an internal buffer, and the top-level function continues immediately. The slots are then called at some later time, when their threads' event loops are ready to process signals. The copied arguments are passed to each slot -- your original reference is not used anymore.
-
Whoa! I didn't realize that the call to slots block on a single-threaded app. That is not what I expected. Coming from the ACE world, I had assumed it followed more of a Reactor Pattern with an activation schedule. This simulates multi-threaded behavior in a single-threaded application. This could explain some of the sluggish responsiveness I've noticed. In case you can't tell, Qt is not my native language :-)
If I were to change the connection type to be more like what I expect, then I'd be incurring the cost of making copies? In ACE, it uses a reference-counted pointer to encapsulate message payloads.
Thanks!
-
Whoa! I didn't realize that the call to slots block on a single-threaded app. That is not what I expected. Coming from the ACE world, I had assumed it followed more of a Reactor Pattern with an activation schedule. This simulates multi-threaded behavior in a single-threaded application. This could explain some of the sluggish responsiveness I've noticed. In case you can't tell, Qt is not my native language :-)
If I were to change the connection type to be more like what I expect, then I'd be incurring the cost of making copies? In ACE, it uses a reference-counted pointer to encapsulate message payloads.
Thanks!
@DRoscoe said:
Whoa! I didn't realize that the call to slots block on a single-threaded app. That is not what I expected. Coming from the ACE world, I had assumed it followed more of a Reactor Pattern with an activation schedule. This simulates multi-threaded behavior in a single-threaded application.
Qt::QueuedConnection will give you the behaviour you expect.
This could explain some of the sluggish responsiveness I've noticed. In case you can't tell, Qt is not my native language :-)
I wouldn't expect sluggishness unless (i) the signal is emitting at a high frequency, and (ii) your slot takes a long time to return ("long" is relative here). If (ii) is true, you might want to consider delegating its task to a secondary thread.
We were all non-"native" at some point in our careers :)
If I were to change the connection type to be more like what I expect, then I'd be incurring the cost of making copies? In ACE, it uses a reference-counted pointer to encapsulate message payloads.
Qt uses reference-counting on many of its datatypes too (e.g. QString, QVector<T>), where "copy" == "shallow copy" == "increment reference counter". See Implicit Sharing for details.