Let\'s say I call QtConcurrent::run() which runs a function in a worker thread, and in that function I dynamically allocate several QObjects (for later use). Since
Does Qt automatically move the QObjects into the parent thread, or are we responsible in moving them to a valid thread before the worker thread terminates?
No, Qt doesn't automatically move QObject into the parent thread.
This behavior doesn't explicitly documented, so I've done a small investigation of the Qt framework source code, master branch.
QThread starts in QThreadPrivate::start:
unsigned int __stdcall QT_ENSURE_STACK_ALIGNED_FOR_SSE QThreadPrivate::start(void *arg)
{
...
thr->run();
finish(arg);
return 0;
}
QThread::terminate() implementation:
void QThread::terminate()
{
Q_D(QThread);
QMutexLocker locker(&d->mutex);
if (!d->running)
return;
if (!d->terminationEnabled) {
d->terminatePending = true;
return;
}
TerminateThread(d->handle, 0);
d->terminated = true;
QThreadPrivate::finish(this, false);
}
In both cases thread finalization is done in QThreadPrivate::finish:
void QThreadPrivate::finish(void *arg, bool lockAnyway)
{
QThread *thr = reinterpret_cast(arg);
QThreadPrivate *d = thr->d_func();
QMutexLocker locker(lockAnyway ? &d->mutex : 0);
d->isInFinish = true;
d->priority = QThread::InheritPriority;
bool terminated = d->terminated;
void **tls_data = reinterpret_cast(&d->data->tls);
locker.unlock();
if (terminated)
emit thr->terminated();
emit thr->finished();
QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
QThreadStorageData::finish(tls_data);
locker.relock();
d->terminated = false;
QAbstractEventDispatcher *eventDispatcher = d->data->eventDispatcher;
if (eventDispatcher) {
d->data->eventDispatcher = 0;
locker.unlock();
eventDispatcher->closingDown();
delete eventDispatcher;
locker.relock();
}
d->running = false;
d->finished = true;
d->isInFinish = false;
if (!d->waiters) {
CloseHandle(d->handle);
d->handle = 0;
}
d->id = 0;
}
It posts QEvent::DeferredDelete event to cleanup QObject::deleteLater, than TLS data cleaned up with QThreadStorageData::finish(tls_data) and eventDispatcher deleted. After that QObject will receive no events from this thread, but QObject's thread affinity stays the same. It's interesting to see implementation of void QObject::moveToThread(QThread *targetThread) to understand how thread affinity changes.
Implementation of void QThreadPrivate::finish(void *arg, bool lockAnyway) makes clear that QObject's thread affinity is not changed by QThread.