diff options
Diffstat (limited to 'src/corelib/kernel/qcoreapplication.cpp')
-rw-r--r-- | src/corelib/kernel/qcoreapplication.cpp | 157 |
1 files changed, 70 insertions, 87 deletions
diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index e25049f821..34f54d8f94 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; } } @@ -553,10 +530,10 @@ void QCoreApplicationPrivate::eventDispatcherReady() { } -QBasicAtomicPointer<QThread> QCoreApplicationPrivate::theMainThread = Q_BASIC_ATOMIC_INITIALIZER(0); +QBasicAtomicPointer<QThread> QCoreApplicationPrivate::theMainThread = Q_BASIC_ATOMIC_INITIALIZER(nullptr); QThread *QCoreApplicationPrivate::mainThread() { - Q_ASSERT(theMainThread.loadRelaxed() != 0); + Q_ASSERT(theMainThread.loadRelaxed() != nullptr); return theMainThread.loadRelaxed(); } @@ -713,7 +690,7 @@ QCoreApplication::QCoreApplication(QCoreApplicationPrivate &p) #ifdef QT_NO_QOBJECT : d_ptr(&p) #else - : QObject(p, 0) + : QObject(p, nullptr) #endif { d_func()->q_ptr = this; @@ -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; @@ -1170,7 +1139,7 @@ bool QCoreApplication::notify(QObject *receiver, QEvent *event) static bool doNotify(QObject *receiver, QEvent *event) { - if (receiver == 0) { // serious error + if (receiver == nullptr) { // serious error qWarning("QCoreApplication::notify: Unexpected null receiver"); return true; } @@ -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,12 +1383,12 @@ int QCoreApplication::exec() void QCoreApplicationPrivate::execCleanup() { - threadData->quitNow = false; + threadData.loadRelaxed()->quitNow = false; in_exec = false; if (!aboutToQuitEmitted) emit q_func()->aboutToQuit(QCoreApplication::QPrivateSignal()); aboutToQuitEmitted = true; - QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); + QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete); } @@ -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 @@ -1530,38 +1531,20 @@ void QCoreApplication::postEvent(QObject *receiver, QEvent *event, int priority) { Q_TRACE_SCOPE(QCoreApplication_postEvent, receiver, event, event->type()); - if (receiver == 0) { + if (receiver == nullptr) { qWarning("QCoreApplication::postEvent: Unexpected null receiver"); delete event; 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 @@ -1652,7 +1635,7 @@ bool QCoreApplication::compressEvent(QEvent *event, QObject *receiver, QPostEven for (int i = 0; i < postedEvents->size(); ++i) { const QPostEvent &cur = postedEvents->at(i); if (cur.receiver != receiver - || cur.event == 0 + || cur.event == nullptr || cur.event->type() != event->type()) continue; // found an event for this receiver @@ -1801,7 +1784,7 @@ void QCoreApplicationPrivate::sendPostedEvents(QObject *receiver, int event_type // null out the event so if sendPostedEvents recurses, it // will ignore this one, as it's been re-posted. - const_cast<QPostEvent &>(pe).event = 0; + const_cast<QPostEvent &>(pe).event = nullptr; // re-post the copied event so it isn't lost data->postEventList.addEvent(pe_copy); @@ -1821,7 +1804,7 @@ void QCoreApplicationPrivate::sendPostedEvents(QObject *receiver, int event_type // next, update the data structure so that we're ready // for the next event. - const_cast<QPostEvent &>(pe).event = 0; + const_cast<QPostEvent &>(pe).event = nullptr; locker.unlock(); const auto relocker = qScopeGuard([&locker] { locker.lock(); }); @@ -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, @@ -1884,7 +1867,7 @@ void QCoreApplication::removePostedEvents(QObject *receiver, int eventType) --pe.receiver->d_func()->postedEvents; pe.event->posted = false; events.append(pe.event); - const_cast<QPostEvent &>(pe).event = 0; + const_cast<QPostEvent &>(pe).event = nullptr; } else if (!data->postEventList.recursion) { if (i != j) qSwap(data->postEventList[i], data->postEventList[j]); @@ -1946,7 +1929,7 @@ void QCoreApplicationPrivate::removePostedEvent(QEvent * event) --pe.receiver->d_func()->postedEvents; pe.event->posted = false; delete pe.event; - const_cast<QPostEvent &>(pe).event = 0; + const_cast<QPostEvent &>(pe).event = nullptr; return; } } @@ -2221,7 +2204,7 @@ QString QCoreApplication::translate(const char *context, const char *sourceText, // Declared in qglobal.h QString qtTrId(const char *id, int n) { - return QCoreApplication::translate(0, id, 0, n); + return QCoreApplication::translate(nullptr, id, nullptr, n); } bool QCoreApplicationPrivate::isTranslatorInstalled(QTranslator *translator) @@ -2973,7 +2956,7 @@ QAbstractEventDispatcher *QCoreApplication::eventDispatcher() { if (QCoreApplicationPrivate::theMainThread.loadAcquire()) return QCoreApplicationPrivate::theMainThread.loadRelaxed()->eventDispatcher(); - return 0; + return nullptr; } /*! |