diff options
Diffstat (limited to 'src/corelib')
-rw-r--r-- | src/corelib/kernel/qcoreapplication.cpp | 28 | ||||
-rw-r--r-- | src/corelib/kernel/qcoreapplication_p.h | 2 | ||||
-rw-r--r-- | src/corelib/kernel/qeventloop.cpp | 2 | ||||
-rw-r--r-- | src/corelib/thread/qthread.cpp | 27 | ||||
-rw-r--r-- | src/corelib/thread/qthread_p.h | 10 |
5 files changed, 63 insertions, 6 deletions
diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index e47dc0dff2..9ad7970807 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -538,6 +538,14 @@ QThread *QCoreApplicationPrivate::mainThread() return theMainThread; } +bool QCoreApplicationPrivate::threadRequiresCoreApplication() +{ + QThreadData *data = QThreadData::current(false); + if (!data) + return true; // default setting + return data->requiresCoreApplication; +} + void QCoreApplicationPrivate::checkReceiverThread(QObject *receiver) { QThread *currentThread = QThread::currentThread(); @@ -926,6 +934,8 @@ bool QCoreApplication::isQuitLockEnabled() return quitLockRefEnabled; } +static bool doNotify(QObject *, QEvent *); + /*! Enables the ability of the QEventLoopLocker feature to quit the application. @@ -960,7 +970,8 @@ bool QCoreApplication::notifyInternal(QObject *receiver, QEvent *event) */ bool QCoreApplication::notifyInternal2(QObject *receiver, QEvent *event) { - if (!self) + bool selfRequired = QCoreApplicationPrivate::threadRequiresCoreApplication(); + if (!self && selfRequired) return false; // Make it possible for Qt Script to hook into events even @@ -978,6 +989,8 @@ bool QCoreApplication::notifyInternal2(QObject *receiver, QEvent *event) QObjectPrivate *d = receiver->d_func(); QThreadData *threadData = d->threadData; QScopedLoopLevelCounter loopLevelCounter(threadData); + if (!selfRequired) + return doNotify(receiver, event); return self->notify(receiver, event); } @@ -1039,7 +1052,11 @@ bool QCoreApplication::notify(QObject *receiver, QEvent *event) // no events are delivered after ~QCoreApplication() has started if (QCoreApplicationPrivate::is_app_closing) return true; + return doNotify(receiver, event); +} +static bool doNotify(QObject *receiver, QEvent *event) +{ if (receiver == 0) { // serious error qWarning("QCoreApplication::notify: Unexpected null receiver"); return true; @@ -1054,7 +1071,10 @@ bool QCoreApplication::notify(QObject *receiver, QEvent *event) bool QCoreApplicationPrivate::sendThroughApplicationEventFilters(QObject *receiver, QEvent *event) { - if (receiver->d_func()->threadData == this->threadData && extraData) { + // We can't access the application event filters outside of the main thread (race conditions) + Q_ASSERT(receiver->d_func()->threadData->thread == mainThread()); + + if (extraData) { // application event filters are only called for objects in the GUI thread for (int i = 0; i < extraData->eventFilters.size(); ++i) { QObject *obj = extraData->eventFilters.at(i); @@ -1097,7 +1117,9 @@ bool QCoreApplicationPrivate::sendThroughObjectEventFilters(QObject *receiver, Q bool QCoreApplicationPrivate::notify_helper(QObject *receiver, QEvent * event) { // send to all application event filters (only does anything in the main thread) - if (QCoreApplication::self->d_func()->sendThroughApplicationEventFilters(receiver, event)) + if (QCoreApplication::self + && receiver->d_func()->threadData->thread == mainThread() + && QCoreApplication::self->d_func()->sendThroughApplicationEventFilters(receiver, event)) return true; // send to all receiver event filters if (sendThroughObjectEventFilters(receiver, event)) diff --git a/src/corelib/kernel/qcoreapplication_p.h b/src/corelib/kernel/qcoreapplication_p.h index 5fed850c2b..21f59d8197 100644 --- a/src/corelib/kernel/qcoreapplication_p.h +++ b/src/corelib/kernel/qcoreapplication_p.h @@ -107,6 +107,8 @@ public: static QThread *theMainThread; static QThread *mainThread(); + static bool threadRequiresCoreApplication(); + static void sendPostedEvents(QObject *receiver, int event_type, QThreadData *data); static void checkReceiverThread(QObject *receiver); diff --git a/src/corelib/kernel/qeventloop.cpp b/src/corelib/kernel/qeventloop.cpp index 1723db0ab9..dca25ce968 100644 --- a/src/corelib/kernel/qeventloop.cpp +++ b/src/corelib/kernel/qeventloop.cpp @@ -93,7 +93,7 @@ QEventLoop::QEventLoop(QObject *parent) : QObject(*new QEventLoopPrivate, parent) { Q_D(QEventLoop); - if (!QCoreApplication::instance()) { + if (!QCoreApplication::instance() && QCoreApplicationPrivate::threadRequiresCoreApplication()) { qWarning("QEventLoop: Cannot be used without QApplication"); } else if (!d->threadData->eventDispatcher.load()) { QThreadPrivate::createEventDispatcher(d->threadData); 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 |