Mihail Naydenov | 2 Jan 12:01 2011

Re: Example of "moveToThread (this)" idiom -- legal?

Without going through the example, I just wanted to remind you 

Qt itself uses moveToThred(this)

(see QFilesystemWatcher implementation)

So, I am sure by definition moveToThred(this) is not illegal. 
If there are any dangers or gotchas they must be documented and
let the users decide what design approach is best suited for their needs. 

thanks
MihailNaydenov

----- Original Message ----
> From: K. Frank <kfrank29.c <at> gmail.com>
> To: Qt-interest <qt-interest <at> qt.nokia.com>
> Sent: Sun, January 2, 2011 4:38:45 AM
> Subject: [Qt-interest] Example of "moveToThread (this)" idiom -- legal?
> 
> Hello List!
> 
> According to my understanding of the Qt threading model,
> I  believe that our so-called "moveToThread (this)" idiom is
> technically  legal.  I'd like to get some feedback on whether
> this is  correct.
> 
> This is a follow-up to a number of questions about  threading
> that come up from time to time, most recently this:
> 
>     http://lists.qt.nokia.com/pipermail/qt-interest/2010-December/030053.html
> 
> To  help make things concrete, I''ve put together a minimal
> example (see  below).
> 
> The basic question is whether it is legal to derive a  worker
> class from QThread, and include the business logic and  any
> necessary signals and slots in the QThread-derived class
> 
> (I want  to set aside the separate question of whether such an
> approach is good  design,and focus on whether it is technically
> correct.)
> 
> In the  following example, I derive a worker-thread class from
> QThread, and include  in it signals and slots, and (trivial)
> business logic.  I use a call to  QThread::sleep() to emulate
> an expensive computation or blocking  call.
> 
> The basic point is that in order for the worker thread's  slots
> to be actually executed by the worker thread's thread of
> execution  (rather than by the main gui thread), the worker
> thread must be "moved" to  itself.  In the example, this is
> done in the worker thread's  constructor:
> 
>    class SquareThread : public QThread {
>       Q_OBJECT
>      public:
>         SquareThread() { moveToThread (this); }
>        //  ...
>    };
> 
> This is what I've called the "moveToThread (this)"  idiom.
> 
> As far as I can tell the example works just fine, the  "work"
> gets handed off to the worker thread for execution, and the
> gui  remains responsive while the worker thread is busy.
> 
> Any thought or  insight would be greatly appreciated.
> 
> (I do agree that there are some  design trade-offs using this
> approach, primarily the loss of the "separation  of concerns"
> that is one of the goals of object-oriented design.
> 
> If  you look at Hughes's "You’re doing it wrong…"  article,
> http://labs.qt.nokia.com/2010/06/17/youre-doing-it-wrong/
> I  believe that this design issue underlies Hughes's main
> complaint, although he  doesn't say so in so many words.
> Hughes also does not state outright that  there is anything
> technically wrong with the "moveToThread (this)"  approach.
> 
> My question is not whether this idiom is  object-orientedly
> impure, but rather whether it is technically correct and  works
> as desired and expected.  For me it seems to.)
> 
> 
> The  example consists of two files:  thread_example.h  and
> thread_example.cpp.
> 
> I build it by placing the two files in a clean  directory, and
> running:
> 
>    qmake -project
>     qmake
>    mingw32-make
> 
> (I am using 32-bit mingw g++ 4.4.1 and Qt  4.6 on 64-bit windows 7.)
> 
> 
> // thread_example.h
> 
> // illustrate  "moveToThread (this)" idiom
> 
> #include <QtGui>
> 
> class  SquareThread : public QThread {
>   Q_OBJECT
>   public:
>      SquareThread() { moveToThread (this); }
>   signals:
>      void send_result (int result);
>   public slots:
>      void receive_value (int value) {
>       sleep (3);
>        emit send_result (value * value);
>      }
> };
> 
> class SquareDialog : public QDialog {
>    Q_OBJECT
>   public:
>     SquareDialog (QWidget *parent = 0) :  QDialog (parent) {
>       value_box = new QSpinBox  (this);
>       value_box->move (40, 20);
> 
>        calc_button = new QPushButton ("calculate square",  this);
>       calc_button->setGeometry (110, 20, 90,  20);
> 
>       QLabel *value_label = new QLabel ("value:",  this);
>       value_label->move (40, 50);
> 
>        QLabel *result_label = new QLabel ("result:", this);
>        result_label->move (110, 50);
> 
>        value_edit = new QLineEdit (this);
>        value_edit->setGeometry (40, 70, 40, 20);
>        value_edit->setReadOnly (true);
> 
>       result_edit = new  QLineEdit (this);
>       result_edit->setGeometry (110, 70,  40, 20);
>       result_edit->setReadOnly  (true);
> 
>       resize(240, 110);
> 
>        SquareThread *square_thread = new SquareThread;
> 
>        connect (calc_button, SIGNAL(clicked()), this,  SLOT(calc_square()));
>       connect (this, SIGNAL(send_value  (int)), square_thread,
> SLOT(receive_value (int)));
>        connect (square_thread, SIGNAL(send_result (int)), this,
> SLOT(receive_result  (int)));
> 
>       square_thread->start();
>      }
>   signals:
>     void send_value (int value);
>    public slots:
>     void calc_square() {
>       int  v = value_box->value();
>       value_edit->setText  (QString::number (v));
>       calc_button->setEnabled  (false);
>       calc_button->setText  ("thinking...");
>       result_edit->setText ("- ???  -");
>       emit send_value (v);
>     }
>      void receive_result (int result) {
>        result_edit->setText (QString::number (result));;
>        calc_button->setText ("calculate square");
>        calc_button->setEnabled (true);
>     }
>    private:
>       QSpinBox *value_box;
>        QPushButton *calc_button;
>       QLineEdit  *value_edit;
>       QLineEdit *result_edit;
> };
> 
> 
> //  thread_example.cpp
> 
> // illustrate "moveToThread (this)"  idiom
> 
> #include <QtGui>
> 
> #include  "thread_example.h"
> 
> int main(int argc, char *argv[]) {
>    QApplication a(argc, argv);
> 
>   SquareDialog main_window;
>    main_window.show();
> 
>   return a.exec();
> }
> 
> 
> Thanks for  your thoughts, and Happy Hacking!
> 
> 
> K.  Frank
> _______________________________________________
> Qt-interest mailing  list
> Qt-interest <at> qt.nokia.com
> http://lists.qt.nokia.com/mailman/listinfo/qt-interest
> 

      
_______________________________________________
Qt-interest mailing list
Qt-interest <at> qt.nokia.com
http://lists.qt.nokia.com/mailman/listinfo/qt-interest

Gmane