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.
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.
You've somewhat changed your question! In general, The following connection means: MySignal
could be emitted in any threads (ie the thread in which you've called emit MySignal()
), but MySlot
is only called in the thread which objectA
belongs to (ie thread affinity). If those threads are the same, the slot is executed synchronously.
connect(&objectA, SIGNAL(MySignal()), &objectA, SLOT(MySlot()));
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.
Do I need mutex-locking to protect data of A a;?
In case you are accessing a
's data outside of the thread in which a
's event loop lives, yes you do need a lock.
There's something suspect in your design.
Normally, signals are protected
, and emitted only from code running in that object's thread. A more conventional design would have objects B and C emit their own signals, and you would connect those signals to the slots of objectA
.
Whilst what you have might work , it will be hard to reason about, and it's probably a good time to review your design before it becomes too tangled to understand what happens in which thread.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.