Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is mutex required in Qt, if different threads are invoking same signal of another different thread?

Let class A is having only one object named as objectA and it's being on a separate thread (say "TCP"):

connect(&objectA, SIGNAL(MySignal()), &objectA, SLOT(MySlot()));    

Note: I assume that Qt::AutoConnection will take care of whether it's QueuedConnection or DirectConnection. I am OK with any type, which makes it safer.

Now if B (say "Processor") & C (say "Utility") are different threads, which are invoking MySignal() with their own convenience.
In the MySlot(), some data of objectA is getting written.

Question:
Do I need mutex-locking to protect data of A a;?
OR
The MySignal() will be queued automatically and hence the MySlot() will get sequentially invoked?

Use case: Currently I am having a TCP thread which send/receive data to/from server. At times, 2 threads may send the data at same time. It's likely to run 2 threads in perfect parallel now a days due to multi-processor architecture.

like image 380
iammilind Avatar asked Oct 30 '25 20:10

iammilind


2 Answers

If the object the slot is executed on is in a different thread than the object that does the emit, then the call is not sequential. The emit will not block. Thus if you access data that the emitting object might be writing to after the emit, you need to either synchronize that access with a mutex, or use a blocking connection (which means you're forcing sequential execution, meaning emit will block until the slot has returned.)

So, if the emit happens on a different thread, and you want it to block, use a blocking connection. If you don't want the emit to block, use a mutex to protect the data. If the emit happens on the same thread, it's going to be a blocking connection anyway.

However, if the emit happens in several threads, then you always need a mutex.

like image 116
Nikos C. Avatar answered Nov 01 '25 09:11

Nikos C.


Assume those threads have been created on the main thread and since connect by default uses Qt::AutoConnection and docs say:

(Default) If the receiver lives in the thread that emits the signal, Qt::DirectConnection is used. Otherwise, Qt::QueuedConnection is used. The connection type is determined when the signal is emitted.

By the time a thread emits a signal, since sender (the code running in QThread::run()) and receiver (the thread who has created the QThread object itself) are different threads, Qt::QueuedConnection is used. That is:

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.

So all MySlot will be sequentially executed on the main thread.


Update

You've somewhat changed your question! In general, The following connection means: MySignal could be emitted in any threads (i.e. the thread in which you've called emit MySignal()), but MySlot is only called in the thread which objectA belongs to (i.e. thread affinity). If those threads are the same, the slot is executed synchronously.

connect(&objectA, SIGNAL(MySignal()), &objectA, SLOT(MySlot())); 
like image 45
frogatto Avatar answered Nov 01 '25 10:11

frogatto