1

In the documentation of the QThread class one exemplary setup works like so:

public:
Controller() {
    Worker *worker = new Worker;
    worker->moveToThread(&workerThread);
    //some connects to thread and worker
    workerThread.start();
}
~Controller() {
    workerThread.quit();
    workerThread.wait();
}

Is Qt implementing actual move semantics with the moveToThread(...) function here? I.e. does the thread take care of de-allocating the Worker object once it finishes, as the Worker* allocated in Controller() is never deleted explicitly anywhere?

Sty
  • 760
  • 1
  • 9
  • 30
  • 3
    The connotation of Qt's `moveToThread` is not related in any way to C++11's move semantics. The former just changes the [*thread affinity*](https://doc.qt.io/qt-5/qobject.html#thread-affinity) of a `QObject` (and applies only on `QObject`s), while the latter is an optimization technique introduced in C++11 to avoid the overhead of copying an object when copying is not really needed (e.g. when, for instance, the object is an rvalue). **The only thing they have in common is the word *move*.** – Mike Oct 24 '17 at 15:53
  • Which, given that Qt's documentation is not quite clear on that distinction, might still make some people (e.g. me) wonder if that may implicitly be entailed. Thanks for clearing that up, though. – Sty Oct 24 '17 at 15:55
  • 2
    you have a point there. Qt docs might need to be updated([you can do that yourself!](https://wiki.qt.io/Contribute)). Qt has been there far before C++11 was invented. So, I can say, as a general guideline when reading the documentation, always assume that they are talking pre-C++11 unless there is something that explicitly states otherwise. In this case, however, there is nothing talking about transferring ownership, and the function is accepting a pointer to a `QThread` (it is not even passed by value), in my opinion, there is no reason to think about rvalues in this context... – Mike Oct 24 '17 at 16:02

3 Answers3

5

moveToThread will not transfer ownership.

In the linked example this line will make sure the worker is deleted after the thread finished:

connect(&workerThread, &QThread::finished, worker, &QObject::deleteLater);
simberto
  • 81
  • 3
  • Ooh, right! I guess that's what happens if you only read "connect()" and think "ah, just the worker signals and slots..." – Sty Oct 24 '17 at 15:25
1

It seems that QThreadPool would be a better fit for the example you give. As explained in the doc :

Worker *worker = new Worker();
// QThreadPool takes ownership and deletes 'worker' automatically
QThreadPool::globalInstance()->start(worker);

Your Worker class needs to inherit from QRunnable and implement the run() virtual function.

ymoreau
  • 3,402
  • 1
  • 22
  • 60
  • I don't recall stating that I *wanted* that, I was just wondering if this was potentially badly documented behaviour. Thanks for bringing up an example that actually shows an ownership change in Qt threading, though! – Sty Oct 24 '17 at 15:57
  • My bad, I meant *"what your example seems to desire to achieve"* :) – ymoreau Oct 25 '17 at 07:54
0

Is Qt implementing actual move semantics with the moveToThread(...) function here? I.e. does the thread take care of de-allocating the Worker object once it finishes, as the Worker* allocated in Controller() is never deleted explicitly anywhere?

What moveToThread means it that slots of myObject will execute in the context of that QThread's eventloop:

From Qt documentation:

By default, run() starts the event loop by calling exec() and runs a Qt event loop inside the thread.

As far as ownership is concerned, in this context moveToThread has nothing to do with ownership in terms of memory management, but rather with ownership in terms of thread executing slots. By default all slots are executed in the main Qt event loop. To move this to that of the thread, call moveToThread...

Werner Erasmus
  • 3,988
  • 17
  • 31