Results 1 to 11 of 11

Thread: Correct Threading Technique

  1. #1
    Join Date
    Oct 2007
    Posts
    6
    Qt products
    Qt4
    Platforms
    Unix/X11
    Thanks
    2

    Default Correct Threading Technique

    Hi,

    I'm wondering if anyone can advise me on the best way to do the following:

    I have an object Runner which is periodically passed a list of Commands to run. The Runner should execute the Commands in a new thread so as not to block the GUI. Once a Command list has been run the thread should sleep until a new Command list is assigned. However, I'm having a little trouble working out how to do this.

    At the moment I'm thinking of having Runner::run() execute a semi-busy loop which periodically checks whether a 'newList' flag has been set. When Runner::execute(CommandList * cList) is called from the main thread the Command list will be assigned to the Runner and the newList flag set to true causing the Runner::run() thread to execute the Command list. This would look something like the following:

    Qt Code:
    1. void Runner::run() {
    2. forever {
    3. if(newList) {
    4. newList = false;
    5. // Execute test.
    6. emit runComplete();
    7. } else {
    8. sleep(1);
    9. }
    10. }
    11. }
    12.  
    13. void Runner::execute(CommandList * cList) {
    14. currentTest = cList;
    15. newTest = true;
    16. }
    To copy to clipboard, switch view to plain text mode 

    Is this a typical solution or is there a nicer more Qt (and possibly more CPU friendly) way of doing this?

  2. #2
    Join Date
    Jan 2006
    Location
    Bremen, Germany
    Posts
    554
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11 Windows
    Thanked 86 Times in 81 Posts

    Default Re: Correct Threading Technique

    I rather would use a QSemaphore to avoid busy waiting. Or enter the QThread eventloop and use signals/slots.

  3. #3
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    5,372
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11 Windows
    Thanks
    28
    Thanked 976 Times in 912 Posts

    Default Re: Correct Threading Technique

    The classical approach is to use a wait condition (or similar mechanism) to block the thread until there's a task ready, but as Christian has already said, you can also pass the tasks through queued connections or you can try out QtConcurrent.

  4. #4
    Join Date
    Oct 2007
    Posts
    6
    Qt products
    Qt4
    Platforms
    Unix/X11
    Thanks
    2

    Default Re: Correct Threading Technique

    Quote Originally Posted by jacek View Post
    The classical approach is to use a wait condition (or similar mechanism) to block the thread until there's a task ready, but as Christian has already said, you can also pass the tasks through queued connections or you can try out QtConcurrent.
    I've had a look over the QWaitCondition documentation and I must confess I'm still not sure how to use it, at least not how to apply it to my situation. Could you give a small example if it isn't too much trouble?

    In regards to using the QThreads event loop and the signals / slot approach, as I understand it Runner would still exist in the main thread, only the Runner::run() method would be in the new thread therefore any signal / slot connections would be processed in the main thread anyway.

  5. #5
    Join Date
    Feb 2006
    Location
    Romania
    Posts
    2,744
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows
    Thanks
    8
    Thanked 541 Times in 521 Posts

    Default Re: Correct Threading Technique

    In regards to using the QThreads event loop and the signals / slot approach, as I understand it Runner would still exist in the main thread, only the Runner::run() method would be in the new thread therefore any signal / slot connections would be processed in the main thread anyway.
    Not if you move the thread object to the worker thread, with moveToThread.

  6. #6
    Join Date
    Oct 2007
    Posts
    6
    Qt products
    Qt4
    Platforms
    Unix/X11
    Thanks
    2

    Default Re: Correct Threading Technique

    Quote Originally Posted by marcel View Post
    Not if you move the thread object to the worker thread, with moveToThread.
    Hmmm, I didn't realise you could move the actual QThread implementation itself to its own thread. This might be the way to go.

    Thanks

  7. #7
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    5,372
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11 Windows
    Thanks
    28
    Thanked 976 Times in 912 Posts

    Default Re: Correct Threading Technique

    Quote Originally Posted by themusicalguy View Post
    I've had a look over the QWaitCondition documentation and I must confess I'm still not sure how to use it, at least not how to apply it to my situation. Could you give a small example if it isn't too much trouble?
    Qt Code:
    1. // thread's part:
    2. forever {
    3. mutex.lock();
    4. while( queue.empty() ) {
    5. queueNotEmptyCondition.wait( & mutex );
    6. }
    7. Task * task = getTaskFromQueue();
    8. mutex.unlock();
    9.  
    10. task->process();
    11. delete task;
    12. };
    13.  
    14. // task scheduling:
    15. mutex.lock();
    16. queue.append( task );
    17. mutex.unlock();
    18. queueNotEmptyCondition.wakeOne();
    To copy to clipboard, switch view to plain text mode 
    Of course if you use queued connections, Qt does most of this for you.

    Quote Originally Posted by themusicalguy View Post
    as I understand it Runner would still exist in the main thread, only the Runner::run() method would be in the new thread therefore any signal / slot connections would be processed in the main thread anyway.
    Yes, it's a bit problematic in Qt, but you can use moveToThread() as Marcel has suggested or you can split implementation into Runner object and a RunnerThread that hosts it.

  8. The following user says thank you to jacek for this useful post:

    themusicalguy (29th October 2007)

  9. #8
    Join Date
    Oct 2007
    Posts
    6
    Qt products
    Qt4
    Platforms
    Unix/X11
    Thanks
    2

    Default Re: Correct Threading Technique

    So, just to clarify...

    It is possible to move a QThread subclass to it's own thread (i.e. the one that it created) using moveToThread() once it's QThread::run() has been invoked?

    I can't wait until QThread is made non-abstract, it will save so much missunderstanding about thread affinity.

  10. #9
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    5,372
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11 Windows
    Thanks
    28
    Thanked 976 Times in 912 Posts

    Default Re: Correct Threading Technique

    Quote Originally Posted by themusicalguy View Post
    It is possible to move a QThread subclass to it's own thread (i.e. the one that it created) using moveToThread() once it's QThread::run() has been invoked?
    Yes, but there might be problem after the thread stops, since it will belong to a non-existent thread. Other solution is to place some object inside the worker thread that will receive queued signals and forward them to QThread subclass through a direct connection.

    Quote Originally Posted by themusicalguy View Post
    I can't wait until QThread is made non-abstract, it will save so much missunderstanding about thread affinity.
    You don't have to wait --- just do it yourself.
    Qt Code:
    1. class Thread : public QThread
    2. {
    3. Q_OBJECT
    4. public:
    5. Thread( QObject * parent = 0 ) : QThread( parent ) {}
    6. protected:
    7. void run() { exec(); }
    8. };
    9. ...
    10. Thread *t = new Thread();
    11. t->start();
    12. Worker *w = new Worker();
    13. w->moveToThread( t );
    14. ...
    To copy to clipboard, switch view to plain text mode 

  11. #10
    Join Date
    Oct 2007
    Posts
    6
    Qt products
    Qt4
    Platforms
    Unix/X11
    Thanks
    2

    Default Re: Correct Threading Technique

    Great stuff thanks a lot, I think this will do the trick.

    One other question... If I use the above method, any objects that are created by Worker will have affinity to the created thread. Now if a pointer to an object created by Worker (say object A) was passed to an object in the main thread and then the created thread was to end, would that cause any problems with object A?

    My situation is as follows:

    Object structure in main thread creates Test objects.
    Runner in thread A runs Test objects and generates TestRun objects.
    TestRun objects are passed out to Object structure in main thread.

    I'm thinking that after each TestRun object is created the Runner thread (thread A) should then move it to the main thread before passing it out. Would this be the best solution?

  12. #11
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    5,372
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11 Windows
    Thanks
    28
    Thanked 976 Times in 912 Posts

    Default Re: Correct Threading Technique

    Quote Originally Posted by themusicalguy View Post
    if I use the above method, any objects that are created by Worker will have affinity to the created thread. Now if a pointer to an object created by Worker (say object A) was passed to an object in the main thread and then the created thread was to end, would that cause any problems with object A?
    Thread affinity is important only for QObjects, but you have to watch out for object ownership.

    Quote Originally Posted by themusicalguy View Post
    I'm thinking that after each TestRun object is created the Runner thread (thread A) should then move it to the main thread before passing it out.
    There might be a problem only if TestRun is a QObject.

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.