QThread: make finish() and cleanup() non-static members

Looks cleaner.

Pick-to: 6.8
Change-Id: I77148a15c316ea0eaf63fffd9358d952c5b9e1d0
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
This commit is contained in:
Thiago Macieira 2024-10-15 09:41:05 -07:00
parent 4fabde349f
commit f94c9b0f3a
3 changed files with 21 additions and 23 deletions

View File

@ -208,13 +208,13 @@ public:
QWaitCondition thread_done; QWaitCondition thread_done;
static void *start(void *arg); static void *start(void *arg);
static void finish(void *); // happens early (before thread-local dtors) void finish(); // happens early (before thread-local dtors)
static void cleanup(void *); // happens late (as a thread-local dtor, if possible) void cleanup(); // happens late (as a thread-local dtor, if possible)
#endif // Q_OS_UNIX #endif // Q_OS_UNIX
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
static unsigned int __stdcall start(void *) noexcept; static unsigned int __stdcall start(void *) noexcept;
static void finish(void *, bool lockAnyway = true) noexcept; void finish(bool lockAnyway = true) noexcept;
Qt::HANDLE handle; Qt::HANDLE handle;
unsigned int id; unsigned int id;

View File

@ -112,15 +112,15 @@ static void destroy_current_thread_data(void *p)
// this is very likely the last reference. These pointers cannot be // this is very likely the last reference. These pointers cannot be
// null and there is no race. // null and there is no race.
QThreadPrivate *thread_p = static_cast<QThreadPrivate *>(QObjectPrivate::get(thread)); QThreadPrivate *thread_p = static_cast<QThreadPrivate *>(QObjectPrivate::get(thread));
thread_p->finish(thread); thread_p->finish();
if constexpr (!QT_CONFIG(broken_threadlocal_dtors)) if constexpr (!QT_CONFIG(broken_threadlocal_dtors))
thread_p->cleanup(thread); thread_p->cleanup();
} else if constexpr (!QT_CONFIG(broken_threadlocal_dtors)) { } else if constexpr (!QT_CONFIG(broken_threadlocal_dtors)) {
// We may be racing the QThread destructor in another thread. With // We may be racing the QThread destructor in another thread. With
// two-phase clean-up enabled, there's also no race because it will // two-phase clean-up enabled, there's also no race because it will
// stop in a call to QThread::wait() until we call cleanup(). // stop in a call to QThread::wait() until we call cleanup().
QThreadPrivate *thread_p = static_cast<QThreadPrivate *>(QObjectPrivate::get(thread)); QThreadPrivate *thread_p = static_cast<QThreadPrivate *>(QObjectPrivate::get(thread));
thread_p->cleanup(thread); thread_p->cleanup();
} else { } else {
// We may be racing the QThread destructor in another thread and it may // We may be racing the QThread destructor in another thread and it may
// have begun destruction; we must not dereference the QThread pointer. // have begun destruction; we must not dereference the QThread pointer.
@ -314,7 +314,7 @@ void *QThreadPrivate::start(void *arg)
// this ensures the thread-local is created as early as possible // this ensures the thread-local is created as early as possible
set_thread_data(data); set_thread_data(data);
pthread_cleanup_push(QThreadPrivate::finish, arg); pthread_cleanup_push([](void *arg) { static_cast<QThread *>(arg)->d_func()->finish(); }, arg);
terminate_on_exception([&] { terminate_on_exception([&] {
{ {
QMutexLocker locker(&thr->d_func()->mutex); QMutexLocker locker(&thr->d_func()->mutex);
@ -361,11 +361,11 @@ void *QThreadPrivate::start(void *arg)
return nullptr; return nullptr;
} }
void QThreadPrivate::finish(void *arg) void QThreadPrivate::finish()
{ {
terminate_on_exception([&] { terminate_on_exception([&] {
QThread *thr = reinterpret_cast<QThread *>(arg); QThreadPrivate *d = this;
QThreadPrivate *d = thr->d_func(); QThread *thr = q_func();
// Disable cancellation; we're already in the finishing touches of this // Disable cancellation; we're already in the finishing touches of this
// thread, and we don't want cleanup to be disturbed by // thread, and we don't want cleanup to be disturbed by
@ -387,14 +387,13 @@ void QThreadPrivate::finish(void *arg)
}); });
if constexpr (QT_CONFIG(broken_threadlocal_dtors)) if constexpr (QT_CONFIG(broken_threadlocal_dtors))
cleanup(arg); cleanup();
} }
void QThreadPrivate::cleanup(void *arg) void QThreadPrivate::cleanup()
{ {
terminate_on_exception([&] { terminate_on_exception([&] {
QThread *thr = reinterpret_cast<QThread *>(arg); QThreadPrivate *d = this;
QThreadPrivate *d = thr->d_func();
// Disable cancellation again: we did it above, but some user code // Disable cancellation again: we did it above, but some user code
// running between finish() and cleanup() may have turned them back on. // running between finish() and cleanup() may have turned them back on.

View File

@ -207,9 +207,8 @@ DWORD WINAPI qt_adopted_thread_watcher_function(LPVOID)
QThread *thread = data->thread; QThread *thread = data->thread;
Q_ASSERT(thread); Q_ASSERT(thread);
auto thread_p = static_cast<QThreadPrivate *>(QObjectPrivate::get(thread)); auto thread_p = static_cast<QThreadPrivate *>(QObjectPrivate::get(thread));
Q_UNUSED(thread_p);
Q_ASSERT(thread_p->threadState == QThreadPrivate::Running); Q_ASSERT(thread_p->threadState == QThreadPrivate::Running);
QThreadPrivate::finish(thread); thread_p->finish();
} }
data->deref(); data->deref();
@ -269,7 +268,7 @@ unsigned int __stdcall QT_ENSURE_STACK_ALIGNED_FOR_SSE QThreadPrivate::start(voi
QThread::setTerminationEnabled(true); QThread::setTerminationEnabled(true);
thr->run(); thr->run();
finish(arg); thr->d_func()->finish();
return 0; return 0;
} }
@ -284,10 +283,10 @@ unsigned int __stdcall QT_ENSURE_STACK_ALIGNED_FOR_SSE QThreadPrivate::start(voi
In those cases, \a arg will not be the current thread. In those cases, \a arg will not be the current thread.
*/ */
void QThreadPrivate::finish(void *arg, bool lockAnyway) noexcept void QThreadPrivate::finish(bool lockAnyway) noexcept
{ {
QThread *thr = reinterpret_cast<QThread *>(arg); QThreadPrivate *d = this;
QThreadPrivate *d = thr->d_func(); QThread *thr = q_func();
QMutexLocker locker(lockAnyway ? &d->mutex : nullptr); QMutexLocker locker(lockAnyway ? &d->mutex : nullptr);
d->threadState = QThreadPrivate::Finishing; d->threadState = QThreadPrivate::Finishing;
@ -477,7 +476,7 @@ void QThread::terminate()
} }
TerminateThread(d->handle, 0); TerminateThread(d->handle, 0);
QThreadPrivate::finish(this, false); d->finish(false);
} }
bool QThread::wait(QDeadlineTimer deadline) bool QThread::wait(QDeadlineTimer deadline)
@ -515,7 +514,7 @@ bool QThread::wait(QDeadlineTimer deadline)
if (ret && d->threadState < QThreadPrivate::Finished) { if (ret && d->threadState < QThreadPrivate::Finished) {
// thread was terminated by someone else // thread was terminated by someone else
QThreadPrivate::finish(this, false); d->finish(false);
} }
if (d->threadState == QThreadPrivate::Finished && !d->waiters) { if (d->threadState == QThreadPrivate::Finished && !d->waiters) {
@ -535,7 +534,7 @@ void QThread::setTerminationEnabled(bool enabled)
QMutexLocker locker(&d->mutex); QMutexLocker locker(&d->mutex);
d->terminationEnabled = enabled; d->terminationEnabled = enabled;
if (enabled && d->terminatePending) { if (enabled && d->terminatePending) {
QThreadPrivate::finish(thr, false); d->finish(false);
locker.unlock(); // don't leave the mutex locked! locker.unlock(); // don't leave the mutex locked!
_endthreadex(0); _endthreadex(0);
} }