Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-30603

QObject::moveToThread is not harmless

    XMLWordPrintable

Details

    • Suggestion
    • Resolution: Done
    • P4: Low
    • None
    • 4.8.0
    • None

    Description

      Qt 4.8 and later documentation states, that the "good" practice is using QObject::moveToThread rather than QThread subclassing. Someone somewhere reinvented this wheel and all are very happy. OK, what's about such code snippet:

      #include <QCoreApplication>
      
      #include <QString>
      
      #include <QTimer>
      
      #include <QThread>
      
      #include <cstdio>
      
      
      class HiMyThreadIs: public QObject
      {
          Q_OBJECT
      public:
      
          HiMyThreadIs(const QString& name, QObject* parent=0):
              QObject(parent), _name(name)
          {
              QTimer* timer = new QTimer(this);
      
              connect(timer, SIGNAL(timeout()), this, SLOT(report()));
      
              timer->setSingleShot(false);
              timer->start(2000);
          }
      
      public slots:
      
          void report()
          {
              QString s =
                  QString("[%1] Hi, my thread is %2\n") // yes, I like it!
                      .arg(_name)
                      .arg((unsigned)(QThread::currentThread()));
      
              std::fwrite(s.toAscii().constData(), 1, s.toAscii().size(), stderr);
          }
      
      private:
          QString _name;
      };
      
      
      class Parent: public QObject
      {
          Q_OBJECT
      public:
      
          Parent(const QString& name, QObject* parent=0):
              QObject(parent), _orphan(name)
          {}
      
      private:
          HiMyThreadIs _orphan;
      };
      
      
      class BadPracticeThread: public QThread
      {
          Q_OBJECT
      public:
      
          BadPracticeThread(QObject* parent=0):
              QThread(parent)
          {}
      
          virtual void run()
          {
              Parent parent("bad practice");
      
              exec();
          }
      };
      
      
      int main(int argc, char* argv[])
      {
          QCoreApplication app(argc, argv);
      
          HiMyThreadIs control_instance("control instance");
      
          QThread good_practice_thread;
          BadPracticeThread bad_practice_thread;
      
          (new Parent("good practice"))->moveToThread(&good_practice_thread);
      
          good_practice_thread.start();
          bad_practice_thread.start();
      
          return app.exec();
      }
      
      
      #include "main.moc"
      
      

      The output is as expected:

      [control instance] Hi, my thread is 154473584
      [good practice] Hi, my thread is 154473584
      [bad practice] Hi, my thread is 3218021664
      [control instance] Hi, my thread is 154473584
      [good practice] Hi, my thread is 154473584
      [bad practice] Hi, my thread is 3218021664
      ^C
      

      You can see, that the "orphan" instance still lives in the same thread, as the "control" instance (i.e. in the main thread) when using QObject::moveToThread. In my home opinion, it's worth noting such a gotcha in the Qt documentation.

      Attachments

        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

        Activity

          People

            docteam Qt Documentation Team
            slava_phirsov phirsov
            Votes:
            0 Vote for this issue
            Watchers:
            5 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Gerrit Reviews

                There are no open Gerrit changes