From 10c529b08de7cd55b4c3e3654464119246498273 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 16 Apr 2015 17:21:37 -0700 Subject: Add a way for auxiliary threads to handle events without CoreApp Long-lived threads started by Qt itself can now receive events even if QCoreApplication hasn't been created. This is required in all threads we start that will handle events, unless we're sure that the thread will exit before the global application object begins destruction. Otherwise, those threads will have race conditions dealing with the event delivery system trying to call the QCoreApplication::notify() virtual while the object is being destroyed. Change-Id: I27eaacb532114dd188c4ffff13d4ad2a4bb443e6 Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/thread/qthread.cpp | 27 ++++++++++++++++++++++++++- src/corelib/thread/qthread_p.h | 10 +++++++++- 2 files changed, 35 insertions(+), 2 deletions(-) (limited to 'src/corelib/thread') diff --git a/src/corelib/thread/qthread.cpp b/src/corelib/thread/qthread.cpp index 0c009db930..590479d68c 100644 --- a/src/corelib/thread/qthread.cpp +++ b/src/corelib/thread/qthread.cpp @@ -50,7 +50,8 @@ QT_BEGIN_NAMESPACE QThreadData::QThreadData(int initialRefCount) : _ref(initialRefCount), loopLevel(0), thread(0), threadId(0), - eventDispatcher(0), quitNow(false), canWait(true), isAdopted(false) + eventDispatcher(0), + quitNow(false), canWait(true), isAdopted(false), requiresCoreApplication(true) { // fprintf(stderr, "QThreadData %p created\n", this); } @@ -867,4 +868,28 @@ bool QThread::isInterruptionRequested() const return d->interruptionRequested; } +/*! + \class QDaemonThread + \since 5.5 + \brief The QDaemonThread provides a class to manage threads that outlive QCoreApplication + \internal + + Note: don't try to deliver events from the started() signal. +*/ +static void setThreadDoesNotRequireCoreApplication() +{ + QThreadData::current()->requiresCoreApplication = false; +} + +QDaemonThread::QDaemonThread(QObject *parent) + : QThread(parent) +{ + // QThread::started() is emitted from the thread we start + connect(this, &QThread::started, setThreadDoesNotRequireCoreApplication); +} + +QDaemonThread::~QDaemonThread() +{ +} + QT_END_NAMESPACE diff --git a/src/corelib/thread/qthread_p.h b/src/corelib/thread/qthread_p.h index 1ecd682ad1..ffefe0b1d1 100644 --- a/src/corelib/thread/qthread_p.h +++ b/src/corelib/thread/qthread_p.h @@ -135,6 +135,13 @@ private: #ifndef QT_NO_THREAD +class Q_CORE_EXPORT QDaemonThread : public QThread +{ +public: + QDaemonThread(QObject *parent = 0); + ~QDaemonThread(); +}; + class QThreadPrivate : public QObjectPrivate { Q_DECLARE_PUBLIC(QThread) @@ -224,7 +231,7 @@ public: QThreadData(int initialRefCount = 1); ~QThreadData(); - static QThreadData *current(bool createIfNecessary = true); + static Q_AUTOTEST_EXPORT QThreadData *current(bool createIfNecessary = true); static void clearCurrentThreadData(); static QThreadData *get2(QThread *thread) { Q_ASSERT_X(thread != 0, "QThread", "internal error"); return thread->d_func()->data; } @@ -278,6 +285,7 @@ public: bool quitNow; bool canWait; bool isAdopted; + bool requiresCoreApplication; }; class QScopedLoopLevelCounter -- cgit v1.2.3