Is Qt's event loop thread safe or atomic? How is it synchronised when dealing with `QueuedConnection`?

1k views Asked by At

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.

2

There are 2 answers

0
iammilind On

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.

0
UmNyobe On

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.