Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does emit copy its arguments?

Tags:

qt

I want to know about emit. Does it duplicate data?

If I have to pass a 1MB byte array through it, how many copies of that byte array will exist in memory?

like image 820
Anupam Srivastava Avatar asked Sep 10 '13 11:09

Anupam Srivastava


2 Answers

That depends on how your signals are connected to slots.

If you use the default connection, Qt::DirectConnection, and the two QObjects are in the same thread, then the parameters are treated as if you were calling function in the usual way according to how you defined the parameters(pass-by-reference or pass-by-value).

If you connect using Qt::QueuedConnection or you are connected between threads, then the parameter arguments are copied and handed over to a special QEvent and added to the receiving thread's event queue. This will then be processed by the receiving thread when it gets the chance.

like image 173
RobbieE Avatar answered Sep 23 '22 14:09

RobbieE


It depends on how the connections are made, and how you pass the parameters.

  1. Pass by value (i.e. signals: void foo(Bar);)

    • A normal C++ function call would generate one copy (to copy the Bar from caller to callee).
    • A direct-connected signal/slot invocation will generate two copies: the emit function generated by moc is called (one copy, same as the one above), "packages" the parameter and calls QMetaObject::activate which ends up calling your class's qt_static_metacall, which invokes the slot (as a normal function call), incurring a second copy.
    • A queue-connected signal/slot invocation will generate three copies. In the calling context, the emit function call itself as above, and a copy of the parameter into an event. In the receiver context, the same qt_static_metacall invocation of the slot.
  2. Pass by const reference (i.e. signals: void foo(Bar const&);)

    • Normal C++ function call: no copy.
    • Direct-connected signal/slot invocation: no copy.
    • Queue-connected signal/slot invocation: one copy, the one into the event object described above
  3. Pass by (non-const) reference (i.e. signals: void foo(Bar&);)

    • Normal C++ function call: no copy.
    • Direct-connected signal/slot invocation: no copy.
    • Queue-connected signal/slot invocation: not possible (AFAIK).

The copy into an event is mentioned in the docs:

With queued connections, the parameters must be of types that are known to Qt's meta-object system, because Qt needs to copy the arguments to store them in an event behind the scenes.

Now the real question is: does this matter?

If you're using a Qt container class that uses implicit sharing, it won't really matter in usual cases - the payload won't be copied unless required. So the copies shouldn't have a significant impact on overall performance in general.

If you're not using implicit sharing, then passing massive objects by value probably isn't the right choice in the first place, but a slot invocation would be more expensive than a plain function call. Direct-connected slots and pass-by-const-ref will behave the same as normal function calls, but queued slots will be more expensive.

like image 41
Mat Avatar answered Sep 22 '22 14:09

Mat