[Qt-interest] Question about the thread affinity of a QThread object

K. Frank kfrank29.c at gmail.com
Fri May 21 00:29:36 CEST 2010


Hi Everyone -

I have a question about what happens when a QThread object emits a signal.

Thiago made a couple of useful comments in an earlier discussion.  First:

   Note that QThread is a QObject class and it has no special-case support.
   Like any QObject, it's thread affinity is to the thread in which it
was created.
   Unless you change it.

That makes sense.  As I understand it, if the run() method of QThread t1
executes

   QThread *t2 = new QThread;

the thread affinity of t2 will be for t1 (rather than itself, t2).

And also:

   The only extra operation is the determination of AutoConnection: if
the target
   object's thread affinity is the current thread, the signal is
delivered directly
   (decays to DirectConnection). If it's another thread, it's queued (decays to
   QueuedConnection).

   The emitter object's thread affinity has no influence in this
process. It only
   depends on the current thread, that is, the thread in which the signal is
   emitted.

Now, I _think_ I have seen warnings, maybe in the documentation, or maybe
in a list discussion, that one should not emit signals from a QThread's run()
method.  The reasoning (if I remember correctly) was that mismatch between
the QThread's thread affinity and the thread of execution that executes run().
(The general design advice was to have the QThread create additional objects
that would naturally have the "correct" thread affinity to do the work.)

   class Emitter : public QThread {
   public:
      void run() {
         emit send();
      }
   public signals:
      void send();
   };

   class Receiver : public QThread {
   public:
      void run() {
         QThread *t2 = new Emitter;
         connect (t2, SIGNAL(send()), this, SLOT(receive());
         t2->start();
         exec();
      }
   public slots:
      void receive();
   };

Suppose a thread, t0, (perhaps the main gui thread) executes

   QThread *t1 = new Receiver;   // t1's thread affinity starts out for t0
   t1->moveToThread (t1);   // but now t1's thread affinity is for itself
   t1->start();   // t1's run() method creates and starts t2

Does this break anything?

As I understand it, t1's thread affinity is for itself, t1 (because we
moved it), and
t2's thread affinity is for t1 (not for itself, t2).

t2's run() method emits the send() signal, which is connected to t1's receive()
slot.  Which thread of execution actually calls t1->receive()?

My recollection about the warnings against having t2 emit a signal was that t2's
"confused" thread affinity (for t1 rather than itself) could cause the
signal to call
the slot incorrectly through a direct connection.

But according to Thiago's comment, t2's thread affinity has nothing to do with
how the slot gets called.

t2's thread of execution calls t2->run(), which calls emit send();.
As I understand
Thiago's comment, the thread of execution, t2, (not t2's affinity, which is t1)
determines how the signal / slot connection is resolved.  Because the emitter's
thread of execution, t2, and the receivers thread affinity, t1, are
different, the
signal is propagated to the slot through a queued connection, and therefore
t1->receiver() is called by t1's thread of execution.

First, is this analysis correct?

Second, if it is, what's the problem with having t2 emit a signal?  If
t2's thread
affinity is irrelevant to how the signal is propagated, and therefore
the signal / slot
connection is (properly) a queued connection, what are all the warnings about?

Thanks for any insight.


K. Frank



More information about the Qt-interest-old mailing list