diff options
author | Qt Forward Merge Bot <qt_forward_merge_bot@qt-project.org> | 2019-11-25 01:00:25 +0100 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2019-11-25 11:30:04 +0100 |
commit | 58c69df4d38324644bc49ec5f42ee8343a454b2d (patch) | |
tree | de0a1ce603292dcaff134d4e1e8ab064295515a2 /src/corelib/kernel/qcoreapplication.cpp | |
parent | 03b1d2c44940322208c12c7bceee376b51d8e852 (diff) | |
parent | 59a705e3710b0ba93bb698e3223241cfac932948 (diff) |
Merge remote-tracking branch 'origin/5.15' into dev
Conflicts:
src/corelib/tools/qhash.h
src/gui/kernel/qevent.h
src/widgets/kernel/qshortcut.cpp
src/widgets/kernel/qshortcut.h
Change-Id: If61c206ee43ad1d97f5b07f58ac93c4583ce5620
Diffstat (limited to 'src/corelib/kernel/qcoreapplication.cpp')
-rw-r--r-- | src/corelib/kernel/qcoreapplication.cpp | 131 |
1 files changed, 57 insertions, 74 deletions
diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index 6531cd8e0c..a66c71cff6 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -121,7 +121,6 @@ #endif #ifdef Q_OS_WASM -#include <emscripten.h> #include <emscripten/val.h> #endif @@ -135,23 +134,6 @@ QT_BEGIN_NAMESPACE -#ifndef QT_NO_QOBJECT -class QMutexUnlocker -{ -public: - inline explicit QMutexUnlocker(QMutex *m) - : mtx(m) - { } - inline ~QMutexUnlocker() { unlock(); } - inline void unlock() { if (mtx) mtx->unlock(); mtx = 0; } - -private: - Q_DISABLE_COPY(QMutexUnlocker) - - QMutex *mtx; -}; -#endif - #if defined(Q_OS_WIN) || defined(Q_OS_MAC) extern QString qAppFileName(); #endif @@ -497,13 +479,6 @@ QCoreApplicationPrivate::QCoreApplicationPrivate(int &aargc, char **aargv, uint QCoreApplicationPrivate::~QCoreApplicationPrivate() { -#ifdef Q_OS_WASM - EM_ASM( - // unmount persistent directory as IDBFS - // see also QTBUG-70002 - FS.unmount('/home/web_user'); - ); -#endif #ifndef QT_NO_QOBJECT cleanupThreadData(); #endif @@ -517,25 +492,27 @@ QCoreApplicationPrivate::~QCoreApplicationPrivate() void QCoreApplicationPrivate::cleanupThreadData() { - if (threadData && !threadData_clean) { + auto thisThreadData = threadData.loadRelaxed(); + + if (thisThreadData && !threadData_clean) { #if QT_CONFIG(thread) - void *data = &threadData->tls; + void *data = &thisThreadData->tls; QThreadStorageData::finish((void **)data); #endif // need to clear the state of the mainData, just in case a new QCoreApplication comes along. - const auto locker = qt_scoped_lock(threadData->postEventList.mutex); - for (int i = 0; i < threadData->postEventList.size(); ++i) { - const QPostEvent &pe = threadData->postEventList.at(i); + const auto locker = qt_scoped_lock(thisThreadData->postEventList.mutex); + for (int i = 0; i < thisThreadData->postEventList.size(); ++i) { + const QPostEvent &pe = thisThreadData->postEventList.at(i); if (pe.event) { --pe.receiver->d_func()->postedEvents; pe.event->posted = false; delete pe.event; } } - threadData->postEventList.clear(); - threadData->postEventList.recursion = 0; - threadData->quitNow = false; + thisThreadData->postEventList.clear(); + thisThreadData->postEventList.recursion = 0; + thisThreadData->quitNow = false; threadData_clean = true; } } @@ -795,17 +772,8 @@ void QCoreApplicationPrivate::init() Q_ASSERT_X(!QCoreApplication::self, "QCoreApplication", "there should be only one application object"); QCoreApplication::self = q; -#ifdef Q_OS_WASM - EM_ASM( - // mount and sync persistent filesystem to sandbox - FS.mount(IDBFS, {}, '/home/web_user'); - FS.syncfs(true, function(err) { - if (err) - Module.print(err); - }); - ); - #if QT_CONFIG(thread) +#ifdef Q_OS_WASM QThreadPrivate::idealThreadCount = emscripten::val::global("navigator")["hardwareConcurrency"].as<int>(); #endif #endif @@ -858,7 +826,8 @@ void QCoreApplicationPrivate::init() #ifndef QT_NO_QOBJECT // use the event dispatcher created by the app programmer (if any) Q_ASSERT(!eventDispatcher); - eventDispatcher = threadData->eventDispatcher.loadRelaxed(); + auto thisThreadData = threadData.loadRelaxed(); + eventDispatcher = thisThreadData->eventDispatcher.loadRelaxed(); // otherwise we create one if (!eventDispatcher) @@ -866,11 +835,11 @@ void QCoreApplicationPrivate::init() Q_ASSERT(eventDispatcher); if (!eventDispatcher->parent()) { - eventDispatcher->moveToThread(threadData->thread.loadAcquire()); + eventDispatcher->moveToThread(thisThreadData->thread.loadAcquire()); eventDispatcher->setParent(q); } - threadData->eventDispatcher = eventDispatcher; + thisThreadData->eventDispatcher = eventDispatcher; eventDispatcherReady(); #endif @@ -914,7 +883,7 @@ QCoreApplication::~QCoreApplication() #endif #ifndef QT_NO_QOBJECT - d_func()->threadData->eventDispatcher = nullptr; + d_func()->threadData.loadRelaxed()->eventDispatcher = nullptr; if (QCoreApplicationPrivate::eventDispatcher) QCoreApplicationPrivate::eventDispatcher->closingDown(); QCoreApplicationPrivate::eventDispatcher = nullptr; @@ -1185,7 +1154,7 @@ static bool doNotify(QObject *receiver, QEvent *event) bool QCoreApplicationPrivate::sendThroughApplicationEventFilters(QObject *receiver, QEvent *event) { // We can't access the application event filters outside of the main thread (race conditions) - Q_ASSERT(receiver->d_func()->threadData->thread.loadAcquire() == mainThread()); + Q_ASSERT(receiver->d_func()->threadData.loadRelaxed()->thread.loadAcquire() == mainThread()); if (extraData) { // application event filters are only called for objects in the GUI thread @@ -1238,7 +1207,7 @@ bool QCoreApplicationPrivate::notify_helper(QObject *receiver, QEvent * event) // send to all application event filters (only does anything in the main thread) if (QCoreApplication::self - && receiver->d_func()->threadData->thread.loadAcquire() == mainThread() + && receiver->d_func()->threadData.loadRelaxed()->thread.loadAcquire() == mainThread() && QCoreApplication::self->d_func()->sendThroughApplicationEventFilters(receiver, event)) { filtered = true; return filtered; @@ -1414,7 +1383,7 @@ int QCoreApplication::exec() void QCoreApplicationPrivate::execCleanup() { - threadData->quitNow = false; + threadData.loadRelaxed()->quitNow = false; in_exec = false; if (!aboutToQuitEmitted) emit q_func()->aboutToQuit(QCoreApplication::QPrivateSignal()); @@ -1451,7 +1420,7 @@ void QCoreApplication::exit(int returnCode) { if (!self) return; - QThreadData *data = self->d_func()->threadData; + QThreadData *data = self->d_func()->threadData.loadRelaxed(); data->quitNow = true; for (int i = 0; i < data->eventLoops.size(); ++i) { QEventLoop *eventLoop = data->eventLoops.at(i); @@ -1501,6 +1470,38 @@ bool QCoreApplication::sendSpontaneousEvent(QObject *receiver, QEvent *event) #endif // QT_NO_QOBJECT +QCoreApplicationPrivate::QPostEventListLocker QCoreApplicationPrivate::lockThreadPostEventList(QObject *object) +{ + QPostEventListLocker locker; + + if (!object) { + locker.threadData = QThreadData::current(); + locker.locker = qt_unique_lock(locker.threadData->postEventList.mutex); + return locker; + } + + auto &threadData = QObjectPrivate::get(object)->threadData; + + // if object has moved to another thread, follow it + for (;;) { + // synchronizes with the storeRelease in QObject::moveToThread + locker.threadData = threadData.loadAcquire(); + if (!locker.threadData) { + // destruction in progress + return locker; + } + + auto temporaryLocker = qt_unique_lock(locker.threadData->postEventList.mutex); + if (locker.threadData == threadData.loadAcquire()) { + locker.locker = std::move(temporaryLocker); + break; + } + } + + Q_ASSERT(locker.threadData); + return locker; +} + /*! \since 4.3 @@ -1536,32 +1537,14 @@ void QCoreApplication::postEvent(QObject *receiver, QEvent *event, int priority) return; } - QThreadData * volatile * pdata = &receiver->d_func()->threadData; - QThreadData *data = *pdata; - if (!data) { + auto locker = QCoreApplicationPrivate::lockThreadPostEventList(receiver); + if (!locker.threadData) { // posting during destruction? just delete the event to prevent a leak delete event; return; } - // lock the post event mutex - data->postEventList.mutex.lock(); - - // if object has moved to another thread, follow it - while (data != *pdata) { - data->postEventList.mutex.unlock(); - - data = *pdata; - if (!data) { - // posting during destruction? just delete the event to prevent a leak - delete event; - return; - } - - data->postEventList.mutex.lock(); - } - - QMutexUnlocker locker(&data->postEventList.mutex); + QThreadData *data = locker.threadData; // if this is one of the compressible events, do compression if (receiver->d_func()->postedEvents @@ -1860,8 +1843,8 @@ void QCoreApplicationPrivate::sendPostedEvents(QObject *receiver, int event_type void QCoreApplication::removePostedEvents(QObject *receiver, int eventType) { - QThreadData *data = receiver ? receiver->d_func()->threadData : QThreadData::current(); - auto locker = qt_unique_lock(data->postEventList.mutex); + auto locker = QCoreApplicationPrivate::lockThreadPostEventList(receiver); + QThreadData *data = locker.threadData; // the QObject destructor calls this function directly. this can // happen while the event loop is in the middle of posting events, |