I've been thinking about the worker class that can be used for parallel computing.
I wanted to avoid the situation when I have to move the worker to separate thread explicitly after creating the object i.e.:
Worker worker;
QThread thread;
worker.moveToThread(&thread);
thread.start();
worker.start();
This is the solution I came up with:
Header:
#include <QObject>
#include <QThread>
class ThreadedWorker : public QObject
{
Q_OBJECT
public:
explicit ThreadedWorker(QObject *parent = 0);
signals:
void finished(ThreadedWorker* worker);
public slots:
void start();
protected:
virtual void run();
QThread workerThread_;
bool isRunning_;
};
Source:
#include "threadedworker.h"
ThreadedWorker::ThreadedWorker(QObject *parent) : QObject(parent)
{
this->moveToThread(&this->workerThread_);
this->workerThread_.start();
this->isRunning_ = false;
}
void ThreadedWorker::start()
{
if(!this->isRunning_)
{
this->isRunning_ = true;
this->run();
}
}
void ThreadedWorker::run()
{
// HERE GOES THE ACTUAL WORK FOR THE WORKER
//
//
emit this->finished(this); // added to inform a controller object that the worker has finished
}
UPDATED after comment by Zailborg:
So now I just create:
ThreadedWorker worker1;
ThreadedWorker worker2;
invoke their start()
slots by some external signal and they run in parallel.
However my main concern is whether it is not a bad practice to put QThread workerThread_
as the member of ThreadedWorker
class and moving the object to that thread in constructor.
When an object is moved to its thread, the object and its children are moved. The children are the objects linked in the Qt parent child hierarchy when you pass a parent to a constructor of a QObject derived class, or call setParent.
In the case of a member pointer, such as a QThread pointer, it is not a "child" of the class. Therefore, when the ThreadedWorker object is moved to the new thread, this will work. However, problems can arise due to the confusion of thread affinity. The main object is moved to the the new thread, but holds a member pointer to an object whose thread affinity is different; the object pointed to by QThread*.
The code presented in the question doesn't refer to a QThread pointer, but a QThread instance. With this in mind, consider the documentation for QObject::moveToThread when it states: -
So, I suspect the design of QThread and QObject::moveToThread expects that the affinity of QThread is stable and will not be altered. By being a member of the object being moved, this is not going to be the case.
For this reason, I would say it is not a good idea to have a QThread instance as a member of a QObject and move the object to that thread.
If you're going to use QThread, then I suggest reading and following the method as outlined in How to Really, Truly Use QThread.
In addition, it is often overlooked that the functionality of moveToThread allows a 1 to many relationship of QThread to QObject, so it is perfectly acceptable to create a QThread object and move multiple QObject instances to the new thread. Also, there is usually little benefit in creating more threads than available processor cores.