Results 1 to 16 of 16

Thread: Abstract threading

Hybrid View

Previous Post Previous Post   Next Post Next Post
  1. #1
    Join Date
    Feb 2010
    Location
    Pennsylvania, USA
    Posts
    36
    Thanks
    9
    Thanked 3 Times in 1 Post
    Qt products
    Qt4 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Default Abstract threading

    I'm trying to write a wrapper so threaded classes have a common interface--so I can write threaded classes expecting certain available functionality, and I and others can write clients, expecting some common functionality.

    So, I wrote an abstract class to act as my "middle man."
    Qt Code:
    1. #ifndef THREADBASE_H
    2. #define THREADBASE_H
    3.  
    4. #include <QThread>
    5.  
    6. class ThreadBase : public QThread
    7. {
    8. public:
    9. ThreadBase();
    10. signals:
    11. void progressChanged(int);
    12. void exceptionOccurred(int);
    13. protected:
    14. void run();
    15. virtual void runThread() = 0;
    16. };
    17.  
    18. ThreadBase::ThreadBase() : QThread(0)
    19. {
    20. }
    21.  
    22. void ThreadBase::run()
    23. {
    24. runThread();
    25. }
    26.  
    27. #endif // THREADBASE_H
    To copy to clipboard, switch view to plain text mode 
    This compiled fine. I then tried writing a derived class.
    Qt Code:
    1. // testsubclass.h
    2. #ifndef TESTSUBCLASS_H
    3. #define TESTSUBCLASS_H
    4.  
    5. #include "threadbase.h"
    6.  
    7. class TestSubClass : public ThreadBase
    8. {
    9. public:
    10. TestSubClass();
    11. protected:
    12. void runThread();
    13. };
    14.  
    15. #endif // TESTSUBCLASS_H
    To copy to clipboard, switch view to plain text mode 
    Qt Code:
    1. // testsubclass.cpp
    2. #include "testsubclass.h"
    3.  
    4. TestSubClass::TestSubClass() : ThreadBase()
    5. {
    6. }
    7.  
    8. void TestSubClass::runThread()
    9. {
    10. for(int i = 0; i < 100; i++)
    11. {
    12. emit progressChanged(i);
    13. wait(100);
    14. }
    15. emit progressChanged(100);
    16. }
    To copy to clipboard, switch view to plain text mode 
    I'm receiving a compiler error on lines 12 and 15 in testsubclass.cpp:
    Qt Code:
    1. undefined reference to `ThreadBase::progressChanged(int)'
    To copy to clipboard, switch view to plain text mode 
    I think I'm having a mind-block, because I have done this before in other classes, and it works. As a derived class, shouldn't TestSubClass have access to the public members of ThreadBase? This might be a C++ question, but I didn't know if there were special rules for using signals in abstract classes that I missed.

    P.S. I'm in Windows, using MinGW, with gcc version 3.4.5.

  2. #2
    Join Date
    Mar 2008
    Location
    France
    Posts
    149
    Thanks
    2
    Thanked 21 Times in 21 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Abstract threading

    Have you forgot to add Q_OBJECT macro to the header files?

  3. #3
    Join Date
    Feb 2010
    Location
    Pennsylvania, USA
    Posts
    36
    Thanks
    9
    Thanked 3 Times in 1 Post
    Qt products
    Qt4 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Default Re: Abstract threading

    Oddly, no. I had Q_OBJECT in both of my classes, but I received compiler warnings regarding the vtable for each class. Usually those errors mean I forgot to define a pure virtual function, but I should only need to redefine QThread::run() for the abstract class. I removed the Q_OBJECT lines, and the vtable errors went away and were replaced with the undefined errors. If I comment out the offending lines, it compiles with no errors.

  4. #4
    Join Date
    Mar 2008
    Location
    France
    Posts
    149
    Thanks
    2
    Thanked 21 Times in 21 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Abstract threading

    You need the Q_OBJECT macro for signals and slots (The undefined reference comes from the fact that you haven't put it in your ThreadBase class declaration).
    Regarding the vtable,run make clean, and then qmake follow by make. ( Basically, you have to rebuild your project in order to get rid of the compiler errors for the vtable)
    Last edited by toutarrive; 9th April 2010 at 22:09.

  5. The following user says thank you to toutarrive for this useful post:

    TheJim01 (14th April 2010)

  6. #5
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,372
    Thanks
    3
    Thanked 5,019 Times in 4,795 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Abstract threading

    Please check if you are not reinventing the wheel - QRunnable, QFuture, QFutureWatcher, etc.

  7. #6
    Join Date
    Feb 2010
    Location
    Pennsylvania, USA
    Posts
    36
    Thanks
    9
    Thanked 3 Times in 1 Post
    Qt products
    Qt4 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Default Re: Abstract threading

    Quote Originally Posted by toutarrive
    You need the Q_OBJECT macro for signals and slots (The undefined reference comes from the fact that you haven't put it in your ThreadBase class declaration).
    Regarding the vtable,run make clean, and then qmake follow by make. ( Basically, you have to rebuild your project in order to get rid of the compiler errors for the vtable)
    One would think (hope) that Creator is smart enough to do that when I select the Build->Clean All followed by Build->Build All. Regardless, I add the Q_OBJECT macro, and used the command line to make clean, qmake, and make. I then got the following errors:
    Qt Code:
    1. debug/moc_threadbase.o: In function `ZN10ThreadBaseC2Ev':
    2. C:/QtWorkspace/ThreadTester/debug/../threadbase.h:19: multiple definition of `ThreadBase::ThreadBase()'
    3. debug/testsubclass.o:C:/QtWorkspace/ThreadTester/threadbase.h:19: first defined here
    4. debug/moc_threadbase.o: In function `ZN10ThreadBaseC1Ev':
    5. C:/QtWorkspace/ThreadTester/debug/../threadbase.h:19: multiple definition of `ThreadBase::ThreadBase()'
    6. debug/testsubclass.o:C:/QtWorkspace/ThreadTester/threadbase.h:19: first defined here
    7. debug/moc_threadbase.o: In function `ZN10ThreadBase3runEv':
    8. C:/QtWorkspace/ThreadTester/debug/../threadbase.h:24: multiple definition of `ThreadBase::run()'
    9. debug/testsubclass.o:C:/QtWorkspace/ThreadTester/threadbase.h:24: first defined here
    10. debug/moc_testsubclass.o: In function `ZN10ThreadBaseC2Ev':
    11. C:/QtWorkspace/ThreadTester/debug/../threadbase.h:19: multiple definition of `ThreadBase::ThreadBase()'
    12. debug/testsubclass.o:C:/QtWorkspace/ThreadTester/threadbase.h:19: first defined here
    13. debug/moc_testsubclass.o: In function `ZN10ThreadBaseC1Ev':
    14. C:/QtWorkspace/ThreadTester/debug/../threadbase.h:19: multiple definition of `ThreadBase::ThreadBase()'
    15. debug/testsubclass.o:C:/QtWorkspace/ThreadTester/threadbase.h:19: first defined here
    16. debug/moc_testsubclass.o: In function `ZN10ThreadBase3runEv':
    17. C:/QtWorkspace/ThreadTester/debug/../threadbase.h:24: multiple definition of `ThreadBase::run()'
    18. debug/testsubclass.o:C:/QtWorkspace/ThreadTester/threadbase.h:24: first defined here
    19. c:/Qt/2010.01/qt/lib/libqtmaind.a(qtmain_win.o): In function `WinMain@16':
    20. C:\qt-greenhouse\Trolltech\Code_less_create_more\Trolltech\Code_less_create_more\Troll\4.6\qt\src\winmain/qtmain_win.cpp:93: undefined reference to `_Unwind_Resume'
    21. C:\qt-greenhouse\Trolltech\Code_less_create_more\Trolltech\Code_less_create_more\Troll\4.6\qt\src\winmain/qtmain_win.cpp:135: undefined reference to `_Unwind_Resume'
    22. c:/Qt/2010.01/qt/lib/libqtmaind.a(qtmain_win.o):C:\qt-greenhouse\Trolltech\Code_less_create_more\Trolltech\Code_less_create_more\Troll\4.6\qt\src\winmain/../../include/QtCore/../../src/corelib/tools/qvector.h:482: undefined reference to `_Unwind_Resume'
    23. c:/Qt/2010.01/qt/lib/libqtmaind.a(qtmain_win.o):C:\qt-greenhouse\Trolltech\Code_less_create_more\Trolltech\Code_less_create_more\Troll\4.6\qt\src\winmain/../../include/QtCore/../../src/corelib/tools/qvector.h:483: undefined reference to `_Unwind_Resume'
    24. c:/Qt/2010.01/qt/lib/libqtmaind.a(qtmain_win.o):qtmain_win.cpp:(.eh_frame+0x12): undefined reference to `__gxx_personality_v0'
    25. collect2: ld returned 1 exit status
    26. make[1]: *** [debug/ThreadTester.exe] Error 1
    27. make[1]: Leaving directory `/c/QtWorkspace/ThreadTester'
    28. make: *** [debug] Error 2
    To copy to clipboard, switch view to plain text mode 
    Creator gives the first error as:
    Qt Code:
    1. c:/Qt/2010.01/qt/include/QtCore/../../src/corelib/global/qglobal.h:1368: multiple definition of `ThreadBase::ThreadBase()'
    To copy to clipboard, switch view to plain text mode 
    These make no sense to me because...

    I removed my sub-class and recompiled, successfully. So my abstract base class is correct (I left the Q_OBJECT macro in the code, and I agree I should need it there). I then re-added my "testsubclass" to my project, and recompiled successfully! If I clean the project again, and recompile, I return to the multiple definition errors. The makefile shouldn't be causing this kind of issue, but I suppose it can't hurt to check it. I really don't want to deal with 2-part compiling for this...

    Quote Originally Posted by wysota View Post
    Please check if you are not reinventing the wheel - QRunnable, QFuture, QFutureWatcher, etc.
    I fully agree that re-invention is a burden, and I actually wanted to use the QFuture/QFutureWatcher classes to monitor my thread, but I chose to not use QtConcurrent/QThreadPool for a few reasons, mainly because I don't need to run a function over a set of data--it only runs once--and I need to handle exceptions coming back from the thread.

  8. #7
    Join Date
    Oct 2006
    Posts
    279
    Thanks
    6
    Thanked 40 Times in 39 Posts
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: Abstract threading

    You need to declare ThreadBase::ThreadBase() and ThreadBase::run() as inline. Since more than one file includes "threadbase.h", there actually are multiple definitions of those functions.

  9. The following user says thank you to spud for this useful post:

    TheJim01 (14th April 2010)

  10. #8
    Join Date
    Feb 2010
    Location
    Pennsylvania, USA
    Posts
    36
    Thanks
    9
    Thanked 3 Times in 1 Post
    Qt products
    Qt4 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Default Re: Abstract threading

    Quote Originally Posted by spud View Post
    You need to declare ThreadBase::ThreadBase() and ThreadBase::run() as inline. Since more than one file includes "threadbase.h", there actually are multiple definitions of those functions.
    I always feel silly when these basic solutions pop up. Thank you, I now see where I went wrong, and fixed my code with your suggestion.

  11. #9
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,372
    Thanks
    3
    Thanked 5,019 Times in 4,795 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Abstract threading

    Quote Originally Posted by TheJim01 View Post
    I fully agree that re-invention is a burden, and I actually wanted to use the QFuture/QFutureWatcher classes to monitor my thread, but I chose to not use QtConcurrent/QThreadPool for a few reasons, mainly because I don't need to run a function over a set of data--it only runs once--and I need to handle exceptions coming back from the thread.
    QRunnable doesn't run a function over a set of data. It just runs a function in a thread.

  12. #10
    Join Date
    Feb 2010
    Location
    Pennsylvania, USA
    Posts
    36
    Thanks
    9
    Thanked 3 Times in 1 Post
    Qt products
    Qt4 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Default Re: Abstract threading

    Quote Originally Posted by wysota View Post
    QRunnable doesn't run a function over a set of data. It just runs a function in a thread.
    Maybe I'm just confused regarding the use of QRunnable vs. QThread. QThread seems like a more robust interface for threading, where QRunnable is very basic (and I can certainly see applications for it).

    I'm not trying to be argumentative--I'm still learning, and just want to understand the differences.
    Last edited by TheJim01; 14th April 2010 at 16:14.

  13. #11
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,372
    Thanks
    3
    Thanked 5,019 Times in 4,795 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Abstract threading

    Quote Originally Posted by TheJim01 View Post
    QThread seems like a more robust interface for threading, where QRunnable is very basic (and I can certainly see applications for it).
    QThread loses most of its robustness when you remember that the QThread object lives in a different thread than its run() method. To me the only differences between QThread and QRunnable is that QThread is derived from QObject and QRunnable is not and that QThread can run an event loop.

  14. The following user says thank you to wysota for this useful post:

    TheJim01 (14th April 2010)

  15. #12
    Join Date
    Feb 2010
    Location
    Pennsylvania, USA
    Posts
    36
    Thanks
    9
    Thanked 3 Times in 1 Post
    Qt products
    Qt4 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Default Re: Abstract threading

    Quote Originally Posted by wysota View Post
    QThread loses most of its robustness when you remember that the QThread object lives in a different thread than its run() method.
    Which is useful, because one does not have to create a instance pointer to interact directly with the thread. But I see your point. As long as I'm creating and connecting my own signals, the reference doesn't need to exist.

    To me the only differences between QThread and QRunnable is that QThread is derived from QObject and QRunnable is not and that QThread can run an event loop.
    The latter is not relevant to my current needs, and I can certainly replicate or find alternatives the other signals and functions.

    If I create a class that inherits from QRunnable, then create (and "new") a pointer of the class in my main (GUI) thread, then try to "start" the thread using QThreadPool::start(myObject), doesn't that conflict with the original idea that an object "lives" in the thread in which it is created? Or does this functionality similar to QObject::moveToThread(QThread *)?

    Thanks for your insights!

  16. #13
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,372
    Thanks
    3
    Thanked 5,019 Times in 4,795 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Abstract threading

    Quote Originally Posted by TheJim01 View Post
    Which is useful, because one does not have to create a instance pointer to interact directly with the thread.
    You can't interact with the thread directly. With QThread you only interact with its controller.

    If I create a class that inherits from QRunnable, then create (and "new") a pointer of the class in my main (GUI) thread, then try to "start" the thread using QThreadPool::start(myObject), doesn't that conflict with the original idea that an object "lives" in the thread in which it is created?
    No, because QRunnable is not a descendant of QObject so it doesn't "live" anywhere (there are no events delivered to it).

  17. #14
    Join Date
    Feb 2010
    Location
    Pennsylvania, USA
    Posts
    36
    Thanks
    9
    Thanked 3 Times in 1 Post
    Qt products
    Qt4 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Default Re: Abstract threading

    Quote Originally Posted by wysota View Post
    You can't interact with the thread directly. With QThread you only interact with its controller.
    Right, sorry, I mis-spoke.

    No, because QRunnable is not a descendant of QObject so it doesn't "live" anywhere (there are no events delivered to it).
    I need the ability to communicate with the object running in the thread (sending it signals, or receiving signals from it), but by the documentation, QRunnable doesn't seem to support this type of interaction. If it doesn't derive from QObject, then I can't use signals/slots. I could inherit from both QObject and QRunnable, but does that not then defeat the purpose of using QRunnable by making a "homeless" object attach to the parent of the QObject?

    I apologise for my confusion, but I'm very interested to ensure I am using the right tools for the job.

  18. #15
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,372
    Thanks
    3
    Thanked 5,019 Times in 4,795 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Abstract threading

    Quote Originally Posted by TheJim01 View Post
    I need the ability to communicate with the object running in the thread (sending it signals, or receiving signals from it), but by the documentation, QRunnable doesn't seem to support this type of interaction.
    For that you need an event loop. So your previous statement about not needing an event loop could have been premature

    If it doesn't derive from QObject, then I can't use signals/slots.
    No, you can't declare signals and slots. You can have objects that declare them. But signals won't be delivered to them without an event loop (you can still emit signals though)

    I could inherit from both QObject and QRunnable
    That wouldn't make much sense. You'd be effectively duplicating QThread.

  19. #16
    Join Date
    Feb 2010
    Location
    Pennsylvania, USA
    Posts
    36
    Thanks
    9
    Thanked 3 Times in 1 Post
    Qt products
    Qt4 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Default Re: Abstract threading

    Quote Originally Posted by wysota View Post
    That wouldn't make much sense. You'd be effectively duplicating QThread.
    Hence my confusion. I saw the relationship, and didn't want to reinvent the wheel to avoid reinventing the wheel!

    For that you need an event loop. So your previous statement about not needing an event loop could have been premature
    No, you can't declare signals and slots. You can have objects that declare them. But signals won't be delivered to them without an event loop (you can still emit signals though)
    Confusion returns. It looks like I missed some critical documentation. I'll have another read, give it another try, and come back if I have more issues.

    Thanks again for your time and help!

Similar Threads

  1. Abstract signals?
    By TorAn in forum Qt Programming
    Replies: 2
    Last Post: 22nd February 2010, 19:31
  2. Choice between Standard- and Abstract Item Model
    By hunsrus in forum Qt Programming
    Replies: 2
    Last Post: 16th March 2009, 15:14
  3. MVC - Abstract Widget Base Class - setupUI
    By SenSej in forum Newbie
    Replies: 0
    Last Post: 13th October 2008, 10:44
  4. Quick question regarding abstract classes and DLLs
    By durbrak in forum Qt Programming
    Replies: 1
    Last Post: 8th February 2007, 21:32
  5. abstract scroll area
    By moowy in forum Qt Programming
    Replies: 2
    Last Post: 2nd October 2006, 09:15

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Qt is a trademark of The Qt Company.