Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Cleaning up after a thread correcly
Forum Updated to NodeBB v4.3 + New Features

Cleaning up after a thread correcly

Scheduled Pinned Locked Moved General and Desktop
42 Posts 7 Posters 31.5k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • G Offline
    G Offline
    giesbert
    wrote on last edited by
    #23

    This should work.
    wait uses the variables that are set by the finished method before the signal finished is emitted, but there is a mutex around both functions. So wait should return when the thread is really finished.

    Nokia Certified Qt Specialist.
    Programming Is Like Sex: One mistake and you have to support it for the rest of your life. (Michael Sinz)

    1 Reply Last reply
    0
    • A Offline
      A Offline
      andre
      wrote on last edited by
      #24

      I still think it is a bug in Qt then. Qt could use the same trick itself to make sure finished() is emitted after the thread has really terminated, could it not?

      1 Reply Last reply
      0
      • G Offline
        G Offline
        giesbert
        wrote on last edited by
        #25

        I can't. Otherwise it would need another thread to wait for this one :-)

        It can't use the main thread, or has to send an internal event to the QThread object which then would have to block the QThreads creator thread untill the real thread is destroyed and then emit the signal.... not very nice....

        but just calling wait in the slot for the finished signal would do the trick.

        Nokia Certified Qt Specialist.
        Programming Is Like Sex: One mistake and you have to support it for the rest of your life. (Michael Sinz)

        1 Reply Last reply
        0
        • A Offline
          A Offline
          andre
          wrote on last edited by
          #26

          The wait time would be very short, if there at all. After all, the thread is supposed to be done, right? Now, you have to wait in the main thread anyway. Why not give that task to QThread instead? The real thread could (in absense of a signal from the OS), as it's last act, indeed just send an event to the QThread and then terminate. The QThread object could in its handler for that event wait for the thread to be finished, and only then emit the signal. I like it more than having to code constructions like these:

          @
          connect(t, SIGNAL(finished()), this, SLOT(cleanupThread()));
          ...
          void This::cleanupThread()
          {
          thread->wait();
          thread->deleteLater();
          }
          @

          You have gained nothing (still waiting for the thread) and you have to write additional code.

          1 Reply Last reply
          0
          • F Offline
            F Offline
            Franzk
            wrote on last edited by
            #27

            [quote author="Andre" date="1307523633"]You have gained nothing (still waiting for the thread) and you have to write additional code. [/quote]
            That is not entirely true. What you have gained is a non-blocking solution to the thread cleanup, because the thread is cleaned up at a point where you know for sure that QThread::wait() isn't going to last for more than a few milliseconds.

            "Horse sense is the thing a horse has which keeps it from betting on people." -- W.C. Fields

            http://www.catb.org/~esr/faqs/smart-questions.html

            1 Reply Last reply
            0
            • A Offline
              A Offline
              andre
              wrote on last edited by
              #28

              Considder this class then:

              @
              FixedQThread: public QThread
              {
              Q_OBJECT

              public:

              FixedQThread(QObject* parent = 0)
              : QThread(parent) {
                  connect(this, SIGNAL(finished()), SLOT(waitForReallyFinished()));
              }
              

              signals:
              void reallyFinished();

              private slots:
              void waitForReallyFinished()
              {
              wait();
              emit reallyFinished();
              }
              };
              @

              After which you can do:
              @
              //thread of type FixedQThread now:
              connect(thread, SIGNAL(reallyFinished()), thread, SLOT(deleteLater()));
              @

              Right?

              1 Reply Last reply
              0
              • F Offline
                F Offline
                Franzk
                wrote on last edited by
                #29

                Aye, that ought to work. It's basically the approach mentioned earlier, just wrapped in a class, which is a good thing to do anyway.

                "Horse sense is the thing a horse has which keeps it from betting on people." -- W.C. Fields

                http://www.catb.org/~esr/faqs/smart-questions.html

                1 Reply Last reply
                0
                • A Offline
                  A Offline
                  andre
                  wrote on last edited by
                  #30

                  So... Why could that same approach not be inside QThread instead?

                  1 Reply Last reply
                  0
                  • F Offline
                    F Offline
                    Franzk
                    wrote on last edited by
                    #31

                    That would be too obvious, wouldn't it?

                    "Horse sense is the thing a horse has which keeps it from betting on people." -- W.C. Fields

                    http://www.catb.org/~esr/faqs/smart-questions.html

                    1 Reply Last reply
                    0
                    • A Offline
                      A Offline
                      andre
                      wrote on last edited by
                      #32

                      Which I why I stated that I think that QThread should be fixed to always emit the finished signal after the thread has actually finished. It is not like it would be very hard to do, as demonstrated above...

                      Edit:
                      Actually, I guess even wait is not going to save the day. See "this bug report":http://bugreports.qt.nokia.com/browse/QTBUG-684 . I have filed a "bugreport":http://bugreports.qt.nokia.com/browse/QTBUG-19783 on the issue.

                      1 Reply Last reply
                      0
                      • T Offline
                        T Offline
                        TheDestroyer
                        wrote on last edited by
                        #33

                        Thanks for the nice discussion guys. I think now I could implement the approach as best as possible. I'm gonna come back to tell you how it went :-)

                        1 Reply Last reply
                        0
                        • G Offline
                          G Offline
                          giesbert
                          wrote on last edited by
                          #34

                          I think it should work, as QThread::wait has a mutex inside, same as finished. In finished it depends on lockAnyway, whether it is locked or not. During normal thread exit, lockAnyway is true...

                          @
                          bool QThread::wait(unsigned long time)
                          {
                          Q_D(QThread);
                          QMutexLocker locker(&d->mutex);

                          // do the rest
                          

                          }

                          void QThreadPrivate::finish(void *arg, bool lockAnyway)
                          {
                          QThread *thr = reinterpret_cast<QThread *>(arg);
                          QThreadPrivate *d = thr->d_func();

                          if (lockAnyway)
                              d->mutex.lock();
                          
                          // do the rest
                          
                          if (lockAnyway)
                              d->mutex.unlock();
                          

                          }

                          @

                          Nokia Certified Qt Specialist.
                          Programming Is Like Sex: One mistake and you have to support it for the rest of your life. (Michael Sinz)

                          1 Reply Last reply
                          0
                          • T Offline
                            T Offline
                            TheDestroyer
                            wrote on last edited by
                            #35

                            Andre's last approach with "reallyFinished()" signal and slot worked perfectly! I like that approach because it's very clear and handles the problem professionally.

                            Thanks to all of you guys! I suppose problem solved :D

                            This was tested on Windows. I hope linux won't make nasty problems :D

                            1 Reply Last reply
                            0
                            • D Offline
                              D Offline
                              DeVeL-2010
                              wrote on last edited by
                              #36

                              It's always fascinating to see how complicated threads are. ;-)

                              But one more question:
                              Can or will the method FixedQThread::waitForReallyFinished() from Andre block the main thread? Because the instance of FixedQThread will live in the context of the main thread normally, just the run() method is executed in another context.

                              1 Reply Last reply
                              0
                              • T Offline
                                T Offline
                                TheDestroyer
                                wrote on last edited by
                                #37

                                Actually I tried it in my down-sampler program, and the progress bar in the main window was active with no problems.

                                The process of being finished or not will only be emitted after run() is done. The problem was, as far as I understood it, the accurate timing in firing the right finished signal, which happens normally (when not using this fix) after run() and before the end of call start().

                                So the objective in all this, is to wait for start() to return.

                                1 Reply Last reply
                                0
                                • F Offline
                                  F Offline
                                  Franzk
                                  wrote on last edited by
                                  #38

                                  [quote author="DeVeL-2010" date="1307617297"]
                                  Can or will the method FixedQThread::waitForReallyFinished() from Andre block the main thread?[/quote]
                                  Absolutely. The idea here however is to try and make the wait in the main thread be as short as possible.

                                  "Horse sense is the thing a horse has which keeps it from betting on people." -- W.C. Fields

                                  http://www.catb.org/~esr/faqs/smart-questions.html

                                  1 Reply Last reply
                                  0
                                  • A Offline
                                    A Offline
                                    andre
                                    wrote on last edited by
                                    #39

                                    Indeed, but it should only block for a very small time: the time it takes to switch to the almost finished thread to let it terminate, via perhaps some other running threads, and back to the thread where the FixedQThread object lives. Most of the time, it should not block at all, because the thread would already have terminated properly. That is, if all goes well and it works as I expect it to. Note that I wrote that example only to illustrate a point on that this should be fixed in QThread. I don't give any guarantees that it will work correctly 100% of the time in the real world :-)

                                    1 Reply Last reply
                                    0
                                    • O Offline
                                      O Offline
                                      ogoffart
                                      wrote on last edited by
                                      #40

                                      Notice that from Qt 4.8 it is no longer required to wait() in the destructor of the thread if you want to connect the finished() signal to the deleteLater() slot

                                      (this was fixed by commit 25c9b6ed)

                                      1 Reply Last reply
                                      0
                                      • A Offline
                                        A Offline
                                        andre
                                        wrote on last edited by
                                        #41

                                        Ah, nice!
                                        Thanks for reporting back in this topic. So my FixedThread hack is not needed anymore from Qt 4.8?

                                        1 Reply Last reply
                                        0
                                        • F Offline
                                          F Offline
                                          Franzk
                                          wrote on last edited by
                                          #42

                                          Looks like: https://qt.gitorious.org/qt/qt/commit/25c9b6ed

                                          "Horse sense is the thing a horse has which keeps it from betting on people." -- W.C. Fields

                                          http://www.catb.org/~esr/faqs/smart-questions.html

                                          1 Reply Last reply
                                          0

                                          • Login

                                          • Login or register to search.
                                          • First post
                                            Last post
                                          0
                                          • Categories
                                          • Recent
                                          • Tags
                                          • Popular
                                          • Users
                                          • Groups
                                          • Search
                                          • Get Qt Extensions
                                          • Unsolved