1

Suppose 2 QThreads are running with following relation:

connect(&Object1OfThread1, &Object1::Signal, 
        &Object2OfThread2, &Object2::Slot, Qt::QueuedConnection);

So when an object from one thread raises a signal, the other thread's slot is invoked. As discussed in Qt signals (QueuedConnection and DirectConnection), due to Qt::QueuedConnection, the Signal() is posted/appended into the event loop of the Thread2. When it turn comes, the Slot() is invoked.

Question: Is the event loop itself thread-safe?
viz. what if Thread1 and Thread3 both post a signal simultaneously to Thread2's event loop.

iammilind
  • 68,093
  • 33
  • 169
  • 336
  • 3
    As far as I am aware, inter-thread signal-slot communication with Qt::QueuedConnection is completely safe, no matter how many threads you have. It would be a glaring hole in Qt thread handling otherwise, wouldn't it? – PlinyTheElder Apr 10 '19 at 14:49
  • 2
    The per-thread event queue follows the general producer-consumer pattern. The queue's thread can be either a consumer (when it picks up events and handles them by sending them to the responsible `QObject`) or a producer (e.g. when it posts an event to its own queue). The other threads are usually producers (since they can post events for that thread to handle). I would suggest reading [this excellent article](https://woboq.com/blog/how-qt-signals-slots-work-part3-queuedconnection.html) if you are interested in the internals of Qt cross-thread signal/slot connections. – Mike Apr 10 '19 at 20:13

2 Answers2

2

The article mentioned in this comment, says that the event queue is protected by a mutex.

How Qt Signals and Slots Work - Part 3 - Queued and Inter Thread Connections

A QueuedConnection will post an event to the event loop to eventually be handled.

When posting an event (in QCoreApplication::postEvent), the event will be pushed in a per-thread queue (QThreadData::postEventList). The event queue is protected by a mutex, so there is no race conditions when threads push events to another thread's event queue.

Once the event has been added to the queue, and if the receiver is living in another thread, we notify the event dispatcher of that thread by calling QAbstractEventDispatcher::wakeUp. This will wake up the dispatcher if it was sleeping while waiting for more events. If the receiver is in the same thread, the event will be processed later, as the event loop iterates.

Community
  • 1
  • 1
iammilind
  • 68,093
  • 33
  • 169
  • 336
2

Qt event loop is thread safe but not atomic.

Thread safety

As long as Object2OfThread2 state is always modified by the thread associated with Thread2, there won't be any race conditions. At most one slot will be executed at any time.

Atomicity

The order of execution of slots is governed by :

  • usual thread preemption
  • The order in which the connections were made to this slot.
  • The other slots connected to the signal.

So I would not advise to assume a specific order of execution for a given slot.

what if Thread1 and Thread3 both post a signal simultaneously to Thread2's event loop

  • First, it is different signals : two threads cannot emit the same signal of the same object as this object resides in only one QObject
  • The signal connected first wins, assuming these signals are only connected to Object2OfThread2 even if they are "posted" simultaneously.
  • If for instance Thread1 signals are connected to other signals\slots, and those connections are made before Object2OfThread2, &Object2::Slot, they will be processed before being posted on Object2OfThread2 event loop. If the signals emitted simultaneously, Thread3 signal will be the first queued, so the first to execute.
UmNyobe
  • 22,539
  • 9
  • 61
  • 90