I'm reading the french book "Maîtrisez Qt 5: guide de développement d'applications professionnelles" to learn Qt.
There is a small code in it to explain QThreadPool
:
#include "MaTache.h"
#include <QCoreApplication>
#include <QThreadPool>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QThreadPool::globalInstance()->setMaxThreadCount(3);
for(int i = 0 ; i < 10 ; i++) {
MaTache *t = new MaTache; // MaTache inherits from QRunnable
QThreadPool::globalInstance()->start(t);
}
QThreadPool::globalInstance()->waitForDone();
return 0;
}
However, I read this advice in the official QT documentation :
Calling QThreadPool::start() multiple times with the same QRunnable when autoDelete is enabled creates a race condition and is not recommended.
Also, I read in the official documentation about QThreadPool::waitForDone(QDeadlineTimer deadline = QDeadlineTimer::Forever)
:
Waits until deadline expires for all threads to exit and removes all threads from the thread pool. Returns true if all threads were removed; otherwise it returns false.
So, I have a few questions :
t->setAutoDelete(false);
(because it is true by default) just before the call to start, how do we manually delete the QRunnable
?QRunnable
, QThreadPool::waitForDone
will rather delete the threads, can I use it indifferently depending on the QRunnable
deletion mode?Here are the three answers, from the comments of the question and this part of the documentation :
Note that the thread pool takes ownership of the runnable if
runnable->autoDelete()
returns true, and the runnable will be deleted automatically by the thread pool after therunnable->run()
returns. Ifrunnable->autoDelete()
returns false, ownership of runnable remains with the caller.
The advice of the documentation, talking about a a race condition when calling QThreadPool::start()
multiple times with the same QRunnable
(when autoDelete
is enabled) is just about the possibility of a double-deletion of the same instance of a QRunnable
. In this example we never call QThreadPool::start
with the same instance so there is no race condition.
If we add t->setAutoDelete(false);
(which is true by default) just before the call to start, we can manually delete the QRunnable
after by keeping the adress and calling delete after QThreadPool::globalInstance()->waitForDone();
.
Since QThreadPool::waitForDone
will rather delete the threads than the QRunnable
, it can be used indifferently on the QRunnable
deletion mode (with/without auto-delete).