diff options
Diffstat (limited to 'src/corelib/kernel')
28 files changed, 455 insertions, 382 deletions
diff --git a/src/corelib/kernel/qbasictimer.cpp b/src/corelib/kernel/qbasictimer.cpp index ea8f8e2c77..623ecb9b8b 100644 --- a/src/corelib/kernel/qbasictimer.cpp +++ b/src/corelib/kernel/qbasictimer.cpp @@ -216,13 +216,11 @@ void QBasicTimer::stop() { if (id) { QAbstractEventDispatcher *eventDispatcher = QAbstractEventDispatcher::instance(); - if (eventDispatcher) { - if (Q_UNLIKELY(!eventDispatcher->unregisterTimer(id))) { - qWarning("QBasicTimer::stop: Failed. Possibly trying to stop from a different thread"); - return; - } - QAbstractEventDispatcherPrivate::releaseTimerId(id); + if (eventDispatcher && !eventDispatcher->unregisterTimer(id)) { + qWarning("QBasicTimer::stop: Failed. Possibly trying to stop from a different thread"); + return; } + QAbstractEventDispatcherPrivate::releaseTimerId(id); } id = 0; } 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; } /*! diff --git a/src/corelib/kernel/qcoreapplication_p.h b/src/corelib/kernel/qcoreapplication_p.h index 3bad42d076..9d2fde619c 100644 --- a/src/corelib/kernel/qcoreapplication_p.h +++ b/src/corelib/kernel/qcoreapplication_p.h @@ -61,6 +61,7 @@ #endif #ifndef QT_NO_QOBJECT #include "private/qobject_p.h" +#include "private/qlocking_p.h" #endif #ifdef Q_OS_MACOS @@ -140,6 +141,15 @@ public: static void checkReceiverThread(QObject *receiver); void cleanupThreadData(); + + struct QPostEventListLocker + { + QThreadData *threadData; + std::unique_lock<QMutex> locker; + + void unlock() { locker.unlock(); } + }; + static QPostEventListLocker lockThreadPostEventList(QObject *object); #endif // QT_NO_QOBJECT int &argc; diff --git a/src/corelib/kernel/qcoreapplication_win.cpp b/src/corelib/kernel/qcoreapplication_win.cpp index 961b96710e..765f129758 100644 --- a/src/corelib/kernel/qcoreapplication_win.cpp +++ b/src/corelib/kernel/qcoreapplication_win.cpp @@ -918,7 +918,7 @@ QDebug operator<<(QDebug dbg, const MSG &msg) #ifndef QT_NO_QOBJECT void QCoreApplicationPrivate::removePostedTimerEvent(QObject *object, int timerId) { - QThreadData *data = object->d_func()->threadData; + QThreadData *data = object->d_func()->threadData.loadRelaxed(); const auto locker = qt_scoped_lock(data->postEventList.mutex); if (data->postEventList.size() == 0) diff --git a/src/corelib/kernel/qcoreevent.cpp b/src/corelib/kernel/qcoreevent.cpp index 4cfc749386..e3326f00d7 100644 --- a/src/corelib/kernel/qcoreevent.cpp +++ b/src/corelib/kernel/qcoreevent.cpp @@ -295,7 +295,7 @@ QT_BEGIN_NAMESPACE Contructs an event object of type \a type. */ QEvent::QEvent(Type type) - : d(0), t(type), posted(false), spont(false), m_accept(true) + : d(nullptr), t(type), posted(false), spont(false), m_accept(true) { Q_TRACE(QEvent_ctor, this, t); } diff --git a/src/corelib/kernel/qeventdispatcher_glib.cpp b/src/corelib/kernel/qeventdispatcher_glib.cpp index d9746ef6e2..92f3553247 100644 --- a/src/corelib/kernel/qeventdispatcher_glib.cpp +++ b/src/corelib/kernel/qeventdispatcher_glib.cpp @@ -114,9 +114,9 @@ static GSourceFuncs socketNotifierSourceFuncs = { socketNotifierSourcePrepare, socketNotifierSourceCheck, socketNotifierSourceDispatch, - NULL, - NULL, - NULL + nullptr, + nullptr, + nullptr }; struct GTimerSource @@ -188,9 +188,9 @@ static GSourceFuncs timerSourceFuncs = { timerSourcePrepare, timerSourceCheck, timerSourceDispatch, - NULL, - NULL, - NULL + nullptr, + nullptr, + nullptr }; struct GIdleTimerSource @@ -227,7 +227,7 @@ static gboolean idleTimerSourceCheck(GSource *source) static gboolean idleTimerSourceDispatch(GSource *source, GSourceFunc, gpointer) { GTimerSource *timerSource = reinterpret_cast<GIdleTimerSource *>(source)->timerSource; - (void) timerSourceDispatch(&timerSource->source, 0, 0); + (void) timerSourceDispatch(&timerSource->source, nullptr, nullptr); return true; } @@ -235,9 +235,9 @@ static GSourceFuncs idleTimerSourceFuncs = { idleTimerSourcePrepare, idleTimerSourceCheck, idleTimerSourceDispatch, - NULL, - NULL, - NULL + nullptr, + nullptr, + nullptr }; struct GPostEventSource @@ -267,7 +267,7 @@ static gboolean postEventSourcePrepare(GSource *s, gint *timeout) static gboolean postEventSourceCheck(GSource *source) { - return postEventSourcePrepare(source, 0); + return postEventSourcePrepare(source, nullptr); } static gboolean postEventSourceDispatch(GSource *s, GSourceFunc, gpointer) @@ -283,9 +283,9 @@ static GSourceFuncs postEventSourceFuncs = { postEventSourcePrepare, postEventSourceCheck, postEventSourceDispatch, - NULL, - NULL, - NULL + nullptr, + nullptr, + nullptr }; @@ -372,10 +372,10 @@ QEventDispatcherGlib::~QEventDispatcherGlib() d->timerSource->timerList.~QTimerInfoList(); g_source_destroy(&d->timerSource->source); g_source_unref(&d->timerSource->source); - d->timerSource = 0; + d->timerSource = nullptr; g_source_destroy(&d->idleTimerSource->source); g_source_unref(&d->idleTimerSource->source); - d->idleTimerSource = 0; + d->idleTimerSource = nullptr; // destroy socket notifier source for (int i = 0; i < d->socketNotifierSource->pollfds.count(); ++i) { @@ -386,19 +386,19 @@ QEventDispatcherGlib::~QEventDispatcherGlib() d->socketNotifierSource->pollfds.~QList<GPollFDWithQSocketNotifier *>(); g_source_destroy(&d->socketNotifierSource->source); g_source_unref(&d->socketNotifierSource->source); - d->socketNotifierSource = 0; + d->socketNotifierSource = nullptr; // destroy post event source g_source_destroy(&d->postEventSource->source); g_source_unref(&d->postEventSource->source); - d->postEventSource = 0; + d->postEventSource = nullptr; - Q_ASSERT(d->mainContext != 0); + Q_ASSERT(d->mainContext != nullptr); #if GLIB_CHECK_VERSION (2, 22, 0) g_main_context_pop_thread_default (d->mainContext); #endif g_main_context_unref(d->mainContext); - d->mainContext = 0; + d->mainContext = nullptr; } bool QEventDispatcherGlib::processEvents(QEventLoop::ProcessEventsFlags flags) diff --git a/src/corelib/kernel/qeventdispatcher_unix.cpp b/src/corelib/kernel/qeventdispatcher_unix.cpp index 5bc65b7110..0165ce9075 100644 --- a/src/corelib/kernel/qeventdispatcher_unix.cpp +++ b/src/corelib/kernel/qeventdispatcher_unix.cpp @@ -463,13 +463,15 @@ bool QEventDispatcherUNIX::processEvents(QEventLoop::ProcessEventsFlags flags) // we are awake, broadcast it emit awake(); - QCoreApplicationPrivate::sendPostedEvents(0, 0, d->threadData); + + auto threadData = d->threadData.loadRelaxed(); + QCoreApplicationPrivate::sendPostedEvents(nullptr, 0, threadData); const bool include_timers = (flags & QEventLoop::X11ExcludeTimers) == 0; const bool include_notifiers = (flags & QEventLoop::ExcludeSocketNotifiers) == 0; const bool wait_for_events = flags & QEventLoop::WaitForMoreEvents; - const bool canWait = (d->threadData->canWaitLocked() + const bool canWait = (threadData->canWaitLocked() && !d->interrupt.loadRelaxed() && wait_for_events); diff --git a/src/corelib/kernel/qeventdispatcher_win.cpp b/src/corelib/kernel/qeventdispatcher_win.cpp index 87623f304a..8616631603 100644 --- a/src/corelib/kernel/qeventdispatcher_win.cpp +++ b/src/corelib/kernel/qeventdispatcher_win.cpp @@ -636,11 +636,11 @@ void QEventDispatcherWin32::registerSocketNotifier(QSocketNotifier *notifier) int type = notifier->type(); #ifndef QT_NO_DEBUG if (sockfd < 0) { - qWarning("QSocketNotifier: Internal error"); + qWarning("QEventDispatcherWin32::registerSocketNotifier: invalid socket identifier"); return; } if (notifier->thread() != thread() || thread() != QThread::currentThread()) { - qWarning("QSocketNotifier: socket notifiers cannot be enabled from another thread"); + qWarning("QEventDispatcherWin32: socket notifiers cannot be enabled from another thread"); return; } #endif @@ -697,11 +697,11 @@ void QEventDispatcherWin32::unregisterSocketNotifier(QSocketNotifier *notifier) #ifndef QT_NO_DEBUG int sockfd = notifier->socket(); if (sockfd < 0) { - qWarning("QSocketNotifier: Internal error"); + qWarning("QEventDispatcherWin32::unregisterSocketNotifier: invalid socket identifier"); return; } if (notifier->thread() != thread() || thread() != QThread::currentThread()) { - qWarning("QSocketNotifier: socket notifiers cannot be disabled from another thread"); + qWarning("QEventDispatcherWin32: socket notifiers cannot be disabled from another thread"); return; } #endif @@ -783,8 +783,7 @@ bool QEventDispatcherWin32::unregisterTimer(int timerId) qWarning("QEventDispatcherWin32::unregisterTimer: invalid argument"); return false; } - QThread *currentThread = QThread::currentThread(); - if (thread() != currentThread) { + if (thread() != QThread::currentThread()) { qWarning("QEventDispatcherWin32::unregisterTimer: timers cannot be stopped from another thread"); return false; } @@ -811,8 +810,7 @@ bool QEventDispatcherWin32::unregisterTimers(QObject *object) qWarning("QEventDispatcherWin32::unregisterTimers: invalid argument"); return false; } - QThread *currentThread = QThread::currentThread(); - if (object->thread() != thread() || thread() != currentThread) { + if (object->thread() != thread() || thread() != QThread::currentThread()) { qWarning("QEventDispatcherWin32::unregisterTimers: timers cannot be stopped from another thread"); return false; } @@ -837,10 +835,12 @@ bool QEventDispatcherWin32::unregisterTimers(QObject *object) QList<QEventDispatcherWin32::TimerInfo> QEventDispatcherWin32::registeredTimers(QObject *object) const { +#ifndef QT_NO_DEBUG if (!object) { qWarning("QEventDispatcherWin32:registeredTimers: invalid argument"); return QList<TimerInfo>(); } +#endif Q_D(const QEventDispatcherWin32); QList<TimerInfo> list; @@ -853,13 +853,13 @@ QEventDispatcherWin32::registeredTimers(QObject *object) const bool QEventDispatcherWin32::registerEventNotifier(QWinEventNotifier *notifier) { - if (!notifier) { - qWarning("QWinEventNotifier: Internal error"); - return false; - } else if (notifier->thread() != thread() || thread() != QThread::currentThread()) { - qWarning("QWinEventNotifier: event notifiers cannot be enabled from another thread"); + Q_ASSERT(notifier); +#ifndef QT_NO_DEBUG + if (notifier->thread() != thread() || thread() != QThread::currentThread()) { + qWarning("QEventDispatcherWin32: event notifiers cannot be enabled from another thread"); return false; } +#endif Q_D(QEventDispatcherWin32); @@ -877,13 +877,13 @@ bool QEventDispatcherWin32::registerEventNotifier(QWinEventNotifier *notifier) void QEventDispatcherWin32::unregisterEventNotifier(QWinEventNotifier *notifier) { - if (!notifier) { - qWarning("QWinEventNotifier: Internal error"); - return; - } else if (notifier->thread() != thread() || thread() != QThread::currentThread()) { - qWarning("QWinEventNotifier: event notifiers cannot be disabled from another thread"); + Q_ASSERT(notifier); +#ifndef QT_NO_DEBUG + if (notifier->thread() != thread() || thread() != QThread::currentThread()) { + qWarning("QEventDispatcherWin32: event notifiers cannot be disabled from another thread"); return; } +#endif Q_D(QEventDispatcherWin32); @@ -1048,7 +1048,7 @@ bool QEventDispatcherWin32::event(QEvent *e) void QEventDispatcherWin32::sendPostedEvents() { Q_D(QEventDispatcherWin32); - QCoreApplicationPrivate::sendPostedEvents(0, 0, d->threadData); + QCoreApplicationPrivate::sendPostedEvents(0, 0, d->threadData.loadRelaxed()); } HWND QEventDispatcherWin32::internalHwnd() diff --git a/src/corelib/kernel/qeventloop.cpp b/src/corelib/kernel/qeventloop.cpp index eacd0c4e73..5a5dfb06aa 100644 --- a/src/corelib/kernel/qeventloop.cpp +++ b/src/corelib/kernel/qeventloop.cpp @@ -106,7 +106,7 @@ QEventLoop::QEventLoop(QObject *parent) if (!QCoreApplication::instance() && QCoreApplicationPrivate::threadRequiresCoreApplication()) { qWarning("QEventLoop: Cannot be used without QApplication"); } else { - d->threadData->ensureEventDispatcher(); + d->threadData.loadRelaxed()->ensureEventDispatcher(); } } @@ -133,9 +133,10 @@ QEventLoop::~QEventLoop() bool QEventLoop::processEvents(ProcessEventsFlags flags) { Q_D(QEventLoop); - if (!d->threadData->hasEventDispatcher()) + auto threadData = d->threadData.loadRelaxed(); + if (!threadData->hasEventDispatcher()) return false; - return d->threadData->eventDispatcher.loadRelaxed()->processEvents(flags); + return threadData->eventDispatcher.loadRelaxed()->processEvents(flags); } /*! @@ -164,9 +165,11 @@ bool QEventLoop::processEvents(ProcessEventsFlags flags) int QEventLoop::exec(ProcessEventsFlags flags) { Q_D(QEventLoop); + auto threadData = d->threadData.loadRelaxed(); + //we need to protect from race condition with QThread::exit - QMutexLocker locker(&static_cast<QThreadPrivate *>(QObjectPrivate::get(d->threadData->thread.loadAcquire()))->mutex); - if (d->threadData->quitNow) + QMutexLocker locker(&static_cast<QThreadPrivate *>(QObjectPrivate::get(threadData->thread.loadAcquire()))->mutex); + if (threadData->quitNow) return -1; if (d->inExec) { @@ -183,8 +186,11 @@ int QEventLoop::exec(ProcessEventsFlags flags) { d->inExec = true; d->exit.storeRelease(false); - ++d->threadData->loopLevel; - d->threadData->eventLoops.push(d->q_func()); + + auto threadData = d->threadData.loadRelaxed(); + ++threadData->loopLevel; + threadData->eventLoops.push(d->q_func()); + locker.unlock(); } @@ -198,11 +204,12 @@ int QEventLoop::exec(ProcessEventsFlags flags) "QCoreApplication::notify() and catch all exceptions there.\n"); } locker.relock(); - QEventLoop *eventLoop = d->threadData->eventLoops.pop(); + auto threadData = d->threadData.loadRelaxed(); + QEventLoop *eventLoop = threadData->eventLoops.pop(); Q_ASSERT_X(eventLoop == d->q_func(), "QEventLoop::exec()", "internal error"); Q_UNUSED(eventLoop); // --release warning d->inExec = false; - --d->threadData->loopLevel; + --threadData->loopLevel; } }; LoopReference ref(d, locker); @@ -217,7 +224,7 @@ int QEventLoop::exec(ProcessEventsFlags flags) // exception, which returns control to the browser while preserving the C++ stack. // Event processing then continues as normal. The sleep call below never returns. // QTBUG-70185 - if (d->threadData->loopLevel > 1) + if (threadData->loopLevel > 1) emscripten_sleep(1); #endif @@ -247,7 +254,7 @@ int QEventLoop::exec(ProcessEventsFlags flags) void QEventLoop::processEvents(ProcessEventsFlags flags, int maxTime) { Q_D(QEventLoop); - if (!d->threadData->hasEventDispatcher()) + if (!d->threadData.loadRelaxed()->hasEventDispatcher()) return; QElapsedTimer start; @@ -276,21 +283,22 @@ void QEventLoop::processEvents(ProcessEventsFlags flags, int maxTime) void QEventLoop::exit(int returnCode) { Q_D(QEventLoop); - if (!d->threadData->hasEventDispatcher()) + auto threadData = d->threadData.loadAcquire(); + if (!threadData->hasEventDispatcher()) return; d->returnCode.storeRelaxed(returnCode); d->exit.storeRelease(true); - d->threadData->eventDispatcher.loadRelaxed()->interrupt(); + threadData->eventDispatcher.loadRelaxed()->interrupt(); #ifdef Q_OS_WASM // QEventLoop::exec() never returns in emscripten. We implement approximate behavior here. // QTBUG-70185 - if (d->threadData->loopLevel == 1) { + if (threadData->loopLevel == 1) { emscripten_force_exit(returnCode); } else { d->inExec = false; - --d->threadData->loopLevel; + --threadData->loopLevel; } #endif } @@ -316,9 +324,10 @@ bool QEventLoop::isRunning() const void QEventLoop::wakeUp() { Q_D(QEventLoop); - if (!d->threadData->hasEventDispatcher()) + auto threadData = d->threadData.loadAcquire(); + if (!threadData->hasEventDispatcher()) return; - d->threadData->eventDispatcher.loadRelaxed()->wakeUp(); + threadData->eventDispatcher.loadRelaxed()->wakeUp(); } diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp index 5cb30a74ac..fad47eee13 100644 --- a/src/corelib/kernel/qmetaobject.cpp +++ b/src/corelib/kernel/qmetaobject.cpp @@ -282,14 +282,14 @@ QObject *QMetaObject::newInstance(QGenericArgument val0, idx = indexOfConstructor(norm.constData()); } if (idx < 0) - return 0; + return nullptr; - QObject *returnValue = 0; + QObject *returnValue = nullptr; void *param[] = {&returnValue, val0.data(), val1.data(), val2.data(), val3.data(), val4.data(), val5.data(), val6.data(), val7.data(), val8.data(), val9.data()}; if (static_metacall(CreateInstance, idx, param) >= 0) - return 0; + return nullptr; return returnValue; } @@ -301,7 +301,7 @@ int QMetaObject::static_metacall(Call cl, int idx, void **argv) const Q_ASSERT(priv(d.data)->revision >= 6); if (!d.static_metacall) return 0; - d.static_metacall(0, cl, idx, argv); + d.static_metacall(nullptr, cl, idx, argv); return -1; } @@ -691,7 +691,7 @@ static void argumentTypesFromString(const char *str, const char *end, QByteArray QMetaObjectPrivate::decodeMethodSignature( const char *signature, QArgumentTypeArray &types) { - Q_ASSERT(signature != 0); + Q_ASSERT(signature != nullptr); const char *lparens = strchr(signature, '('); if (!lparens) return QByteArray(); @@ -844,7 +844,7 @@ int QMetaObjectPrivate::indexOfConstructor(const QMetaObject *m, const QByteArra */ int QMetaObjectPrivate::absoluteSignalCount(const QMetaObject *m) { - Q_ASSERT(m != 0); + Q_ASSERT(m != nullptr); int n = priv(m->d.data)->signalCount; for (m = m->d.superdata; m; m = m->d.superdata) n += priv(m->d.data)->signalCount; @@ -881,7 +881,7 @@ QMetaMethod QMetaObjectPrivate::signal(const QMetaObject *m, int signal_index) QMetaMethod result; if (signal_index < 0) return result; - Q_ASSERT(m != 0); + Q_ASSERT(m != nullptr); int i = signal_index; i -= signalOffset(m); if (i < 0 && m->d.superdata) @@ -1031,7 +1031,7 @@ int QMetaObject::indexOfProperty(const char *name) const QAbstractDynamicMetaObject *me = const_cast<QAbstractDynamicMetaObject *>(static_cast<const QAbstractDynamicMetaObject *>(this)); - return me->createProperty(name, 0); + return me->createProperty(name, nullptr); } return -1; @@ -1145,7 +1145,7 @@ QMetaProperty QMetaObject::property(int index) const if (!result.menum.isValid()) { const char *enum_name = type; const char *scope_name = objectClassName(this); - char *scope_buffer = 0; + char *scope_buffer = nullptr; const char *colon = strrchr(enum_name, ':'); // ':' will always appear in pairs @@ -1159,7 +1159,7 @@ QMetaProperty QMetaObject::property(int index) const enum_name = colon+1; } - const QMetaObject *scope = 0; + const QMetaObject *scope = nullptr; if (qstrcmp(scope_name, "Qt") == 0) scope = &QObject::staticQtMetaObject; else @@ -1542,14 +1542,14 @@ bool QMetaObject::invokeMethodImpl(QObject *object, QtPrivate::QSlotObjectBase * return false; } - QCoreApplication::postEvent(object, new QMetaCallEvent(slot, 0, -1, 1)); + QCoreApplication::postEvent(object, new QMetaCallEvent(slot, nullptr, -1, 1)); } else if (type == Qt::BlockingQueuedConnection) { #if QT_CONFIG(thread) if (currentThread == objectThread) qWarning("QMetaObject::invokeMethod: Dead lock detected"); QSemaphore semaphore; - QCoreApplication::postEvent(object, new QMetaCallEvent(slot, 0, -1, argv, &semaphore)); + QCoreApplication::postEvent(object, new QMetaCallEvent(slot, nullptr, -1, argv, &semaphore)); semaphore.acquire(); #endif // QT_CONFIG(thread) } else { @@ -1988,7 +1988,7 @@ QList<QByteArray> QMetaMethod::parameterNames() const const char *QMetaMethod::typeName() const { if (!mobj) - return 0; + return nullptr; return QMetaMethodPrivate::get(this)->rawReturnTypeName(); } @@ -2020,7 +2020,7 @@ const char *QMetaMethod::typeName() const const char *QMetaMethod::tag() const { if (!mobj) - return 0; + return nullptr; return QMetaMethodPrivate::get(this)->tag().constData(); } @@ -2303,7 +2303,7 @@ bool QMetaMethod::invoke(QObject *object, return false; } - QScopedPointer<QMetaCallEvent> event(new QMetaCallEvent(idx_offset, idx_relative, callFunction, 0, -1, paramCount)); + QScopedPointer<QMetaCallEvent> event(new QMetaCallEvent(idx_offset, idx_relative, callFunction, nullptr, -1, paramCount)); int *types = event->types(); void **args = event->args(); @@ -2340,7 +2340,7 @@ bool QMetaMethod::invoke(QObject *object, QSemaphore semaphore; QCoreApplication::postEvent(object, new QMetaCallEvent(idx_offset, idx_relative, callFunction, - 0, -1, param, &semaphore)); + nullptr, -1, param, &semaphore)); semaphore.acquire(); #endif // QT_CONFIG(thread) } @@ -2563,7 +2563,7 @@ bool QMetaMethod::invokeOnGadget(void* gadget, QGenericReturnArgument returnValu const char *QMetaEnum::name() const { if (!mobj) - return 0; + return nullptr; return rawStringData(mobj, mobj->d.data[handle]); } @@ -2582,7 +2582,7 @@ const char *QMetaEnum::name() const const char *QMetaEnum::enumName() const { if (!mobj) - return 0; + return nullptr; const bool rev8p = priv(mobj->d.data)->revision >= 8; if (rev8p) return rawStringData(mobj, mobj->d.data[handle + 1]); @@ -2610,13 +2610,13 @@ int QMetaEnum::keyCount() const const char *QMetaEnum::key(int index) const { if (!mobj) - return 0; + return nullptr; const int offset = priv(mobj->d.data)->revision >= 8 ? 3 : 2; int count = mobj->d.data[handle + offset]; int data = mobj->d.data[handle + offset + 1]; if (index >= 0 && index < count) return rawStringData(mobj, mobj->d.data[data + 2*index]); - return 0; + return nullptr; } /*! @@ -2679,7 +2679,7 @@ bool QMetaEnum::isScoped() const */ const char *QMetaEnum::scope() const { - return mobj ? objectClassName(mobj) : 0; + return mobj ? objectClassName(mobj) : nullptr; } /*! @@ -2695,7 +2695,7 @@ const char *QMetaEnum::scope() const */ int QMetaEnum::keyToValue(const char *key, bool *ok) const { - if (ok != 0) + if (ok != nullptr) *ok = false; if (!mobj || !key) return -1; @@ -2715,7 +2715,7 @@ int QMetaEnum::keyToValue(const char *key, bool *ok) const const QByteArray className = stringData(mobj, priv(mobj->d.data)->className); if ((!scope || (className.size() == int(scope) && strncmp(qualified_key, className.constData(), scope) == 0)) && strcmp(key, rawStringData(mobj, mobj->d.data[data + 2*i])) == 0) { - if (ok != 0) + if (ok != nullptr) *ok = true; return mobj->d.data[data + 2*i + 1]; } @@ -2734,14 +2734,14 @@ int QMetaEnum::keyToValue(const char *key, bool *ok) const const char* QMetaEnum::valueToKey(int value) const { if (!mobj) - return 0; + return nullptr; const int offset = priv(mobj->d.data)->revision >= 8 ? 3 : 2; int count = mobj->d.data[handle + offset]; int data = mobj->d.data[handle + offset + 1]; for (int i = 0; i < count; ++i) if (value == (int)mobj->d.data[data + 2*i + 1]) return rawStringData(mobj, mobj->d.data[data + 2*i]); - return 0; + return nullptr; } /*! @@ -2756,11 +2756,11 @@ const char* QMetaEnum::valueToKey(int value) const */ int QMetaEnum::keysToValue(const char *keys, bool *ok) const { - if (ok != 0) + if (ok != nullptr) *ok = false; if (!mobj || !keys) return -1; - if (ok != 0) + if (ok != nullptr) *ok = true; const QString keysString = QString::fromLatin1(keys); const QVector<QStringRef> splitKeys = keysString.splitRef(QLatin1Char('|')); @@ -2793,7 +2793,7 @@ int QMetaEnum::keysToValue(const char *keys, bool *ok) const } } if (i < 0) { - if (ok != 0) + if (ok != nullptr) *ok = false; value |= -1; } @@ -2896,7 +2896,7 @@ static QByteArray qualifiedName(const QMetaEnum &e) \internal */ QMetaProperty::QMetaProperty() - : mobj(0), handle(0), idx(0) + : mobj(nullptr), handle(0), idx(0) { } @@ -2909,7 +2909,7 @@ QMetaProperty::QMetaProperty() const char *QMetaProperty::name() const { if (!mobj) - return 0; + return nullptr; int handle = priv(mobj->d.data)->propertyData + 3*idx; return rawStringData(mobj, mobj->d.data[handle]); } @@ -2922,7 +2922,7 @@ const char *QMetaProperty::name() const const char *QMetaProperty::typeName() const { if (!mobj) - return 0; + return nullptr; int handle = priv(mobj->d.data)->propertyData + 3*idx; return rawTypeNameFromTypeInfo(mobj, mobj->d.data[handle + 1]); } @@ -3112,7 +3112,7 @@ QVariant QMetaProperty::read(const QObject *object) const t = enumMetaTypeId; } else { int handle = priv(mobj->d.data)->propertyData + 3*idx; - const char *typeName = 0; + const char *typeName = nullptr; Q_ASSERT(priv(mobj->d.data)->revision >= 7); uint typeInfo = mobj->d.data[handle + 1]; if (!(typeInfo & IsUnresolvedType)) @@ -3138,11 +3138,11 @@ QVariant QMetaProperty::read(const QObject *object) const // changed: result stored directly in value int status = -1; QVariant value; - void *argv[] = { 0, &value, &status }; + void *argv[] = { nullptr, &value, &status }; if (t == QMetaType::QVariant) { argv[0] = &value; } else { - value = QVariant(t, (void*)0); + value = QVariant(t, (void*)nullptr); argv[0] = value.data(); } if (priv(mobj->d.data)->flags & PropertyAccessInStaticMetaCall && mobj->d.static_metacall) { @@ -3196,7 +3196,7 @@ bool QMetaProperty::write(QObject *object, const QVariant &value) const v.convert(QVariant::Int); } else { int handle = priv(mobj->d.data)->propertyData + 3*idx; - const char *typeName = 0; + const char *typeName = nullptr; Q_ASSERT(priv(mobj->d.data)->revision >= 7); uint typeInfo = mobj->d.data[handle + 1]; if (!(typeInfo & IsUnresolvedType)) @@ -3213,7 +3213,7 @@ bool QMetaProperty::write(QObject *object, const QVariant &value) const if (!value.isValid()) { if (isResettable()) return reset(object); - v = QVariant(t, 0); + v = QVariant(t, nullptr); } else if (!v.convert(t)) { return false; } @@ -3229,7 +3229,7 @@ bool QMetaProperty::write(QObject *object, const QVariant &value) const // the flags variable is used by the declarative module to implement // interception of property writes. int flags = 0; - void *argv[] = { 0, &v, &status, &flags }; + void *argv[] = { nullptr, &v, &status, &flags }; if (t == QMetaType::QVariant) argv[0] = &v; else @@ -3254,7 +3254,7 @@ bool QMetaProperty::reset(QObject *object) const { if (!object || !mobj || !isResettable()) return false; - void *argv[] = { 0 }; + void *argv[] = { nullptr }; if (priv(mobj->d.data)->flags & PropertyAccessInStaticMetaCall && mobj->d.static_metacall) mobj->d.static_metacall(object, QMetaObject::ResetProperty, idx, argv); else @@ -3638,7 +3638,7 @@ bool QMetaProperty::isEditable(const QObject *object) const const char *QMetaClassInfo::name() const { if (!mobj) - return 0; + return nullptr; return rawStringData(mobj, mobj->d.data[handle]); } @@ -3650,7 +3650,7 @@ const char *QMetaClassInfo::name() const const char* QMetaClassInfo::value() const { if (!mobj) - return 0; + return nullptr; return rawStringData(mobj, mobj->d.data[handle + 1]); } diff --git a/src/corelib/kernel/qmetaobjectbuilder.cpp b/src/corelib/kernel/qmetaobjectbuilder.cpp index f77c4ce32f..4ecc340787 100644 --- a/src/corelib/kernel/qmetaobjectbuilder.cpp +++ b/src/corelib/kernel/qmetaobjectbuilder.cpp @@ -210,7 +210,7 @@ public: : flags(0) { superClass = &QObject::staticMetaObject; - staticMetacallFunction = 0; + staticMetacallFunction = nullptr; } bool hasRevisionedProperties() const; @@ -749,7 +749,7 @@ void QMetaObjectBuilder::addMetaObject Q_ASSERT(priv(prototype->d.data)->revision >= 2); const auto *objects = prototype->d.relatedMetaObjects; if (objects) { - while (*objects != 0) { + while (*objects != nullptr) { addRelatedMetaObject(*objects); ++objects; } @@ -831,7 +831,7 @@ const QMetaObject *QMetaObjectBuilder::relatedMetaObject(int index) const if (index >= 0 && index < d->relatedMetaObjects.size()) return d->relatedMetaObjects[index]; else - return 0; + return nullptr; } /*! @@ -1196,8 +1196,8 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf, ALIGN(size, int); if (buf) { if (!relocatable) meta->d.superdata = d->superClass; - meta->d.relatedMetaObjects = 0; - meta->d.extradata = 0; + meta->d.relatedMetaObjects = nullptr; + meta->d.extradata = nullptr; meta->d.static_metacall = d->staticMetacallFunction; } @@ -1494,7 +1494,7 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf, */ QMetaObject *QMetaObjectBuilder::toMetaObject() const { - int size = buildMetaObject(d, 0, 0, false); + int size = buildMetaObject(d, nullptr, 0, false); char *buf = reinterpret_cast<char *>(malloc(size)); memset(buf, 0, size); buildMetaObject(d, buf, size, false); @@ -1517,7 +1517,7 @@ QMetaObject *QMetaObjectBuilder::toMetaObject() const */ QByteArray QMetaObjectBuilder::toRelocatableData(bool *ok) const { - int size = buildMetaObject(d, 0, 0, true); + int size = buildMetaObject(d, nullptr, 0, true); if (size == -1) { if (ok) *ok = false; return QByteArray(); @@ -1555,9 +1555,9 @@ void QMetaObjectBuilder::fromRelocatableData(QMetaObject *output, output->d.superdata = superclass; output->d.stringdata = reinterpret_cast<const QByteArrayData *>(buf + stringdataOffset); output->d.data = reinterpret_cast<const uint *>(buf + dataOffset); - output->d.extradata = 0; - output->d.relatedMetaObjects = 0; - output->d.static_metacall = 0; + output->d.extradata = nullptr; + output->d.relatedMetaObjects = nullptr; + output->d.static_metacall = nullptr; } /*! @@ -1720,14 +1720,14 @@ void QMetaObjectBuilder::deserialize d->enumerators.clear(); d->constructors.clear(); d->relatedMetaObjects.clear(); - d->staticMetacallFunction = 0; + d->staticMetacallFunction = nullptr; // Read the class and super class names. stream >> d->className; stream >> name; if (name.isEmpty()) { - d->superClass = 0; - } else if ((cl = resolveClassName(references, name)) != 0) { + d->superClass = nullptr; + } else if ((cl = resolveClassName(references, name)) != nullptr) { d->superClass = cl; } else { stream.setStatus(QDataStream::ReadCorruptData); @@ -1877,7 +1877,7 @@ QMetaMethodBuilderPrivate *QMetaMethodBuilder::d_func() const else if (_mobj && -_index >= 1 && -_index <= int(_mobj->d->constructors.size())) return &(_mobj->d->constructors[(-_index) - 1]); else - return 0; + return nullptr; } /*! @@ -2116,7 +2116,7 @@ QMetaPropertyBuilderPrivate *QMetaPropertyBuilder::d_func() const if (_mobj && _index >= 0 && _index < int(_mobj->d->properties.size())) return &(_mobj->d->properties[_index]); else - return 0; + return nullptr; } /*! @@ -2588,7 +2588,7 @@ QMetaEnumBuilderPrivate *QMetaEnumBuilder::d_func() const if (_mobj && _index >= 0 && _index < int(_mobj->d->enumerators.size())) return &(_mobj->d->enumerators[_index]); else - return 0; + return nullptr; } /*! diff --git a/src/corelib/kernel/qmetatype.cpp b/src/corelib/kernel/qmetatype.cpp index 356a675517..af9a2e0dd2 100644 --- a/src/corelib/kernel/qmetatype.cpp +++ b/src/corelib/kernel/qmetatype.cpp @@ -506,6 +506,31 @@ struct DefinedTypesFilter { Destructs this object. */ +/*! + \fn template<typename T> QMetaType QMetaType::fromType() + \since 5.15 + + Returns the QMetaType corresponding to the type in the template parameter. +*/ + +/*! \fn bool operator==(const QMetaType &a, const QMetaType &b) + \since 5.15 + \relates QMetaType + \overload + + Returns \c true if the QMetaType \a a represents the same type + as the QMetaType \a b, otherwise returns \c false. +*/ + +/*! \fn bool operator!=(const QMetaType &a, const QMetaType &c) + \since 5.15 + \relates QMetaType + \overload + + Returns \c true if the QMetaType \a a represents a difference type + than the QMetaType \a b, otherwise returns \c false. +*/ + #define QT_ADD_STATIC_METATYPE(MetaTypeName, MetaTypeId, RealName) \ { #RealName, sizeof(#RealName) - 1, MetaTypeId }, @@ -930,7 +955,7 @@ constexpr MetaTypeOffsets<QtPrivate::Indexes<QMetaType::HighestInternalId + 1>:: pointer if no matching type was found. The returned pointer must not be deleted. - \sa type(), isRegistered(), Type + \sa type(), isRegistered(), Type, name() */ const char *QMetaType::typeName(int typeId) { @@ -950,6 +975,20 @@ const char *QMetaType::typeName(int typeId) #undef QT_METATYPE_TYPEID_TYPENAME_CONVERTER } +/*! + \since 5.15 + + Returns the type name associated with this QMetaType, or a null + pointer if no matching type was found. The returned pointer must not be + deleted. + + \sa typeName() +*/ +QByteArray QMetaType::name() const +{ + return QMetaType::typeName(m_typeId); +} + /* Similar to QMetaType::type(), but only looks in the static set of types. */ @@ -1113,8 +1152,8 @@ static int registerNormalizedType(const NS(QByteArray) &normalizedTypeName, QCustomTypeInfo inf; inf.typeName = normalizedTypeName; #ifndef QT_NO_DATASTREAM - inf.loadOp = 0; - inf.saveOp = 0; + inf.loadOp = nullptr; + inf.saveOp = nullptr; #endif inf.alias = -1; inf.typedConstructor = typedConstructor; @@ -1955,7 +1994,7 @@ public: return Q_LIKELY(qMetaTypeWidgetsHelper) ? qMetaTypeWidgetsHelper[type - QMetaType::FirstWidgetsType].metaObject : nullptr; - return 0; + return nullptr; } }; @@ -2214,6 +2253,8 @@ QMetaType QMetaType::typeInfo(const int type) \since 5.0 Constructs a QMetaType object that contains all information about type \a typeId. + + \note: The default parameter was added in Qt 5.15 */ QMetaType::QMetaType(const int typeId) : m_typeId(typeId) diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h index d41f7ee80e..825f767425 100644 --- a/src/corelib/kernel/qmetatype.h +++ b/src/corelib/kernel/qmetatype.h @@ -572,7 +572,7 @@ public: static bool load(QDataStream &stream, int type, void *data); #endif - explicit QMetaType(const int type); // ### Qt6: drop const + explicit QMetaType(const int type = QMetaType::UnknownType); // ### Qt6: drop const inline ~QMetaType(); inline bool isValid() const; @@ -581,12 +581,24 @@ public: inline int sizeOf() const; inline TypeFlags flags() const; inline const QMetaObject *metaObject() const; + QT_PREPEND_NAMESPACE(QByteArray) name() const; inline void *create(const void *copy = nullptr) const; inline void destroy(void *data) const; inline void *construct(void *where, const void *copy = nullptr) const; inline void destruct(void *data) const; + template<typename T> + static QMetaType fromType() + { return QMetaType(qMetaTypeId<T>()); } + + friend bool operator==(const QMetaType &a, const QMetaType &b) + { return a.m_typeId == b.m_typeId; } + + friend bool operator!=(const QMetaType &a, const QMetaType &b) + { return a.m_typeId != b.m_typeId; } + + public: template<typename T> static bool registerComparators() @@ -1212,9 +1224,12 @@ public: { IteratorOwner<typename T::const_iterator>::assign(iterator, static_cast<const T*>(container)->find(*static_cast<const typename T::key_type*>(p))); } + QT_WARNING_PUSH + QT_WARNING_DISABLE_DEPRECATED // Hits on the deprecated QHash::iterator::operator--() template<class T> static void advanceImpl(void **p, int step) { std::advance(*static_cast<typename T::const_iterator*>(*p), step); } + QT_WARNING_POP template<class T> static void beginImpl(const void *container, void **iterator) diff --git a/src/corelib/kernel/qmimedata.cpp b/src/corelib/kernel/qmimedata.cpp index 9a98db21d3..00e5183eb1 100644 --- a/src/corelib/kernel/qmimedata.cpp +++ b/src/corelib/kernel/qmimedata.cpp @@ -319,7 +319,7 @@ QVariant QMimeDataPrivate::retrieveTypedData(const QString &format, QVariant::Ty Constructs a new MIME data object with no data in it. */ QMimeData::QMimeData() - : QObject(*new QMimeDataPrivate, 0) + : QObject(*new QMimeDataPrivate, nullptr) { } diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index cf107498dd..a2c5d7db75 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -109,7 +109,7 @@ static int *queuedConnectionTypes(const QList<QByteArray> &typeNames) "(Make sure '%s' is registered using qRegisterMetaType().)", typeName.constData(), typeName.constData()); delete [] types; - return 0; + return nullptr; } } types[typeNames.count()] = 0; @@ -133,7 +133,7 @@ static int *queuedConnectionTypes(const QArgumentType *argumentTypes, int argc) qWarning("QObject::connect: Cannot queue arguments of type '%s'\n" "(Make sure '%s' is registered using qRegisterMetaType().)", type.name().constData(), type.name().constData()); - return 0; + return nullptr; } } types[argc] = 0; @@ -160,13 +160,13 @@ extern "C" Q_CORE_EXPORT void qt_removeObject(QObject *) {} #endif -void (*QAbstractDeclarativeData::destroyed)(QAbstractDeclarativeData *, QObject *) = 0; -void (*QAbstractDeclarativeData::destroyed_qml1)(QAbstractDeclarativeData *, QObject *) = 0; -void (*QAbstractDeclarativeData::parentChanged)(QAbstractDeclarativeData *, QObject *, QObject *) = 0; -void (*QAbstractDeclarativeData::signalEmitted)(QAbstractDeclarativeData *, QObject *, int, void **) = 0; -int (*QAbstractDeclarativeData::receivers)(QAbstractDeclarativeData *, const QObject *, int) = 0; -bool (*QAbstractDeclarativeData::isSignalConnected)(QAbstractDeclarativeData *, const QObject *, int) = 0; -void (*QAbstractDeclarativeData::setWidgetParent)(QObject *, QObject *) = 0; +void (*QAbstractDeclarativeData::destroyed)(QAbstractDeclarativeData *, QObject *) = nullptr; +void (*QAbstractDeclarativeData::destroyed_qml1)(QAbstractDeclarativeData *, QObject *) = nullptr; +void (*QAbstractDeclarativeData::parentChanged)(QAbstractDeclarativeData *, QObject *, QObject *) = nullptr; +void (*QAbstractDeclarativeData::signalEmitted)(QAbstractDeclarativeData *, QObject *, int, void **) = nullptr; +int (*QAbstractDeclarativeData::receivers)(QAbstractDeclarativeData *, const QObject *, int) = nullptr; +bool (*QAbstractDeclarativeData::isSignalConnected)(QAbstractDeclarativeData *, const QObject *, int) = nullptr; +void (*QAbstractDeclarativeData::setWidgetParent)(QObject *, QObject *) = nullptr; /*! \fn QObjectData::QObjectData() @@ -182,7 +182,7 @@ QMetaObject *QObjectData::dynamicMetaObject() const } QObjectPrivate::QObjectPrivate(int version) - : threadData(0), currentChildBeingDeleted(0) + : threadData(nullptr), currentChildBeingDeleted(nullptr) { #ifdef QT_BUILD_INTERNAL // Don't check the version parameter in internal builds. @@ -195,8 +195,8 @@ QObjectPrivate::QObjectPrivate(int version) #endif // QObjectData initialization - q_ptr = 0; - parent = 0; // no parent yet. It is set by setParent() + q_ptr = nullptr; + parent = nullptr; // no parent yet. It is set by setParent() isWidget = false; // assume not a widget object blockSig = false; // not blocking signals wasDeleted = false; // double-delete catcher @@ -204,19 +204,20 @@ QObjectPrivate::QObjectPrivate(int version) sendChildEvents = true; // if we should send ChildAdded and ChildRemoved events to parent receiveChildEvents = true; postedEvents = 0; - extraData = 0; - metaObject = 0; + extraData = nullptr; + metaObject = nullptr; isWindow = false; deleteLaterCalled = false; } QObjectPrivate::~QObjectPrivate() { + auto thisThreadData = threadData.loadRelaxed(); if (extraData && !extraData->runningTimers.isEmpty()) { - if (Q_LIKELY(threadData->thread.loadAcquire() == QThread::currentThread())) { + if (Q_LIKELY(thisThreadData->thread.loadAcquire() == QThread::currentThread())) { // unregister pending timers - if (threadData->hasEventDispatcher()) - threadData->eventDispatcher.loadRelaxed()->unregisterTimers(q_ptr); + if (thisThreadData->hasEventDispatcher()) + thisThreadData->eventDispatcher.loadRelaxed()->unregisterTimers(q_ptr); // release the timer ids back to the pool for (int i = 0; i < extraData->runningTimers.size(); ++i) @@ -229,7 +230,7 @@ QObjectPrivate::~QObjectPrivate() if (postedEvents) QCoreApplication::removePostedEvents(q_ptr, 0); - threadData->deref(); + thisThreadData->deref(); if (metaObject) metaObject->objectDestroyed(q_ptr); @@ -906,30 +907,8 @@ static bool check_parent_thread(QObject *parent, */ QObject::QObject(QObject *parent) - : d_ptr(new QObjectPrivate) + : QObject(*new QObjectPrivate, parent) { - Q_ASSERT_X(this != parent, Q_FUNC_INFO, "Cannot parent a QObject to itself"); - - Q_D(QObject); - d_ptr->q_ptr = this; - d->threadData = (parent && !parent->thread()) ? parent->d_func()->threadData : QThreadData::current(); - d->threadData->ref(); - if (parent) { - QT_TRY { - if (!check_parent_thread(parent, parent ? parent->d_func()->threadData : 0, d->threadData)) - parent = 0; - setParent(parent); - } QT_CATCH(...) { - d->threadData->deref(); - QT_RETHROW; - } - } -#if QT_VERSION < 0x60000 - qt_addObject(this); -#endif - if (Q_UNLIKELY(qtHookData[QHooks::AddQObject])) - reinterpret_cast<QHooks::AddQObjectCallback>(qtHookData[QHooks::AddQObject])(this); - Q_TRACE(QObject_ctor, this); } /*! @@ -942,12 +921,13 @@ QObject::QObject(QObjectPrivate &dd, QObject *parent) Q_D(QObject); d_ptr->q_ptr = this; - d->threadData = (parent && !parent->thread()) ? parent->d_func()->threadData : QThreadData::current(); - d->threadData->ref(); + auto threadData = (parent && !parent->thread()) ? parent->d_func()->threadData.loadRelaxed() : QThreadData::current(); + threadData->ref(); + d->threadData.storeRelaxed(threadData); if (parent) { QT_TRY { - if (!check_parent_thread(parent, parent ? parent->d_func()->threadData : 0, d->threadData)) - parent = 0; + if (!check_parent_thread(parent, parent ? parent->d_func()->threadData.loadRelaxed() : nullptr, threadData)) + parent = nullptr; if (d->isWidget) { if (parent) { d->parent = parent; @@ -958,7 +938,7 @@ QObject::QObject(QObjectPrivate &dd, QObject *parent) setParent(parent); } } QT_CATCH(...) { - d->threadData->deref(); + threadData->deref(); QT_RETHROW; } } @@ -1115,7 +1095,7 @@ QObject::~QObject() Q_TRACE(QObject_dtor, this); if (d->parent) // remove it from parent object - d->setParent_helper(0); + d->setParent_helper(nullptr); } QObjectPrivate::Connection::~Connection() @@ -1342,7 +1322,7 @@ bool QObject::event(QEvent *e) case QEvent::ThreadChange: { Q_D(QObject); - QThreadData *threadData = d->threadData; + QThreadData *threadData = d->threadData.loadRelaxed(); QAbstractEventDispatcher *eventDispatcher = threadData->eventDispatcher.loadRelaxed(); if (eventDispatcher) { QList<QAbstractEventDispatcher::TimerInfo> timers = eventDispatcher->registeredTimers(this); @@ -1509,7 +1489,7 @@ bool QObject::blockSignals(bool block) noexcept */ QThread *QObject::thread() const { - return d_func()->threadData->thread.loadAcquire(); + return d_func()->threadData.loadRelaxed()->thread.loadAcquire(); } /*! @@ -1556,12 +1536,12 @@ void QObject::moveToThread(QThread *targetThread) { Q_D(QObject); - if (d->threadData->thread.loadAcquire() == targetThread) { + if (d->threadData.loadRelaxed()->thread.loadAcquire() == targetThread) { // object is already in this thread return; } - if (d->parent != 0) { + if (d->parent != nullptr) { qWarning("QObject::moveToThread: Cannot move objects with a parent"); return; } @@ -1572,13 +1552,14 @@ void QObject::moveToThread(QThread *targetThread) QThreadData *currentData = QThreadData::current(); QThreadData *targetData = targetThread ? QThreadData::get2(targetThread) : nullptr; - if (d->threadData->thread.loadAcquire() == 0 && currentData == targetData) { + QThreadData *thisThreadData = d->threadData.loadRelaxed(); + if (!thisThreadData->thread.loadAcquire() && currentData == targetData) { // one exception to the rule: we allow moving objects with no thread affinity to the current thread currentData = d->threadData; - } else if (d->threadData != currentData) { + } else if (thisThreadData != currentData) { qWarning("QObject::moveToThread: Current thread (%p) is not the object's thread (%p).\n" "Cannot move to target thread (%p)\n", - currentData->thread.loadRelaxed(), d->threadData->thread.loadRelaxed(), targetData ? targetData->thread.loadRelaxed() : nullptr); + currentData->thread.loadRelaxed(), thisThreadData->thread.loadRelaxed(), targetData ? targetData->thread.loadRelaxed() : nullptr); #ifdef Q_OS_MAC qWarning("You might be loading two sets of Qt binaries into the same process. " @@ -1637,7 +1618,7 @@ void QObjectPrivate::setThreadData_helper(QThreadData *currentData, QThreadData if (pe.receiver == q) { // move this post event to the targetList targetData->postEventList.addEvent(pe); - const_cast<QPostEvent &>(pe).event = 0; + const_cast<QPostEvent &>(pe).event = nullptr; ++eventsMoved; } } @@ -1675,8 +1656,10 @@ void QObjectPrivate::setThreadData_helper(QThreadData *currentData, QThreadData // set new thread data targetData->ref(); - threadData->deref(); - threadData = targetData; + threadData.loadRelaxed()->deref(); + + // synchronizes with loadAcquire e.g. in QCoreApplication::postEvent + threadData.storeRelease(targetData); for (int i = 0; i < children.size(); ++i) { QObject *child = children.at(i); @@ -1688,7 +1671,7 @@ void QObjectPrivate::_q_reregisterTimers(void *pointer) { Q_Q(QObject); QList<QAbstractEventDispatcher::TimerInfo> *timerList = reinterpret_cast<QList<QAbstractEventDispatcher::TimerInfo> *>(pointer); - QAbstractEventDispatcher *eventDispatcher = threadData->eventDispatcher.loadRelaxed(); + QAbstractEventDispatcher *eventDispatcher = threadData.loadRelaxed()->eventDispatcher.loadRelaxed(); for (int i = 0; i < timerList->size(); ++i) { const QAbstractEventDispatcher::TimerInfo &ti = timerList->at(i); eventDispatcher->registerTimer(ti.timerId, ti.interval, ti.timerType, q); @@ -1746,7 +1729,9 @@ int QObject::startTimer(int interval, Qt::TimerType timerType) qWarning("QObject::startTimer: Timers cannot have negative intervals"); return 0; } - if (Q_UNLIKELY(!d->threadData->hasEventDispatcher())) { + + auto thisThreadData = d->threadData.loadRelaxed(); + if (Q_UNLIKELY(!thisThreadData->hasEventDispatcher())) { qWarning("QObject::startTimer: Timers can only be used with threads started with QThread"); return 0; } @@ -1754,7 +1739,7 @@ int QObject::startTimer(int interval, Qt::TimerType timerType) qWarning("QObject::startTimer: Timers cannot be started from another thread"); return 0; } - int timerId = d->threadData->eventDispatcher.loadRelaxed()->registerTimer(interval, timerType, this); + int timerId = thisThreadData->eventDispatcher.loadRelaxed()->registerTimer(interval, timerType, this); if (!d->extraData) d->extraData = new QObjectPrivate::ExtraData; d->extraData->runningTimers.append(timerId); @@ -1828,8 +1813,9 @@ void QObject::killTimer(int id) return; } - if (d->threadData->hasEventDispatcher()) - d->threadData->eventDispatcher.loadRelaxed()->unregisterTimer(id); + auto thisThreadData = d->threadData.loadRelaxed(); + if (thisThreadData->hasEventDispatcher()) + thisThreadData->eventDispatcher.loadRelaxed()->unregisterTimer(id); d->extraData->runningTimers.remove(at); QAbstractEventDispatcherPrivate::releaseTimerId(id); @@ -2079,7 +2065,7 @@ void qt_qFindChildren_helper(const QObject *parent, const QRegularExpression &re QObject *qt_qFindChild_helper(const QObject *parent, const QString &name, const QMetaObject &mo, Qt::FindChildOptions options) { if (!parent) - return 0; + return nullptr; const QObjectList &children = parent->children(); QObject *obj; int i; @@ -2095,7 +2081,7 @@ QObject *qt_qFindChild_helper(const QObject *parent, const QString &name, const return obj; } } - return 0; + return nullptr; } /*! @@ -2123,7 +2109,7 @@ void QObjectPrivate::deleteChildren() delete currentChildBeingDeleted; } children.clear(); - currentChildBeingDeleted = 0; + currentChildBeingDeleted = nullptr; isDeletingChildren = false; } @@ -2157,7 +2143,9 @@ void QObjectPrivate::setParent_helper(QObject *o) // cleared our entry in parentD->children. } else { const int index = parentD->children.indexOf(q); - if (parentD->isDeletingChildren) { + if (index < 0) { + // we're probably recursing into setParent() from a ChildRemoved event, don't do anything + } else if (parentD->isDeletingChildren) { parentD->children[index] = 0; } else { parentD->children.removeAt(index); @@ -2173,7 +2161,7 @@ void QObjectPrivate::setParent_helper(QObject *o) // object hierarchies are constrained to a single thread if (threadData != parent->d_func()->threadData) { qWarning("QObject::setParent: Cannot set parent, new parent is in a different thread"); - parent = 0; + parent = nullptr; return; } parent->d_func()->children.append(q); @@ -2244,7 +2232,7 @@ void QObject::installEventFilter(QObject *obj) d->extraData = new QObjectPrivate::ExtraData; // clean up unused items in the list - d->extraData->eventFilters.removeAll((QObject*)0); + d->extraData->eventFilters.removeAll((QObject*)nullptr); d->extraData->eventFilters.removeAll(obj); d->extraData->eventFilters.prepend(obj); } @@ -2268,7 +2256,7 @@ void QObject::removeEventFilter(QObject *obj) if (d->extraData) { for (int i = 0; i < d->extraData->eventFilters.count(); ++i) { if (d->extraData->eventFilters.at(i) == obj) - d->extraData->eventFilters[i] = 0; + d->extraData->eventFilters[i] = nullptr; } } } @@ -2391,7 +2379,7 @@ void QObject::deleteLater() const char *qFlagLocation(const char *method) { QThreadData *currentThreadData = QThreadData::current(false); - if (currentThreadData != 0) + if (currentThreadData != nullptr) currentThreadData->flaggedSignatures.store(method); return method; } @@ -2410,7 +2398,7 @@ static const char * extract_location(const char *member) if (*location != '\0') return location; } - return 0; + return nullptr; } static bool check_signal_macro(const QObject *sender, const char *signal, @@ -2449,7 +2437,7 @@ static void err_method_notfound(const QObject *object, case QSIGNAL_CODE: type = "signal"; break; } const char *loc = extract_location(method); - if (strchr(method,')') == 0) // common typing mistake + if (strchr(method,')') == nullptr) // common typing mistake qWarning("QObject::%s: Parentheses expected, %s %s::%s%s%s", func, type, object->metaObject()->className(), method+1, loc ? " in ": "", loc ? loc : ""); @@ -2509,7 +2497,7 @@ QObject *QObject::sender() const return cd->currentSender->sender; } - return 0; + return nullptr; } /*! @@ -2688,7 +2676,7 @@ void QMetaObjectPrivate::memberIndexes(const QObject *obj, return; const QMetaObject *m = obj->metaObject(); // Check that member is member of obj class - while (m != 0 && m != member.mobj) + while (m != nullptr && m != member.mobj) m = m->d.superdata; if (!m) return; @@ -2799,18 +2787,18 @@ QMetaObject::Connection QObject::connect(const QObject *sender, const char *sign const QObject *receiver, const char *method, Qt::ConnectionType type) { - if (sender == 0 || receiver == 0 || signal == 0 || method == 0) { + if (sender == nullptr || receiver == nullptr || signal == nullptr || method == nullptr) { qWarning("QObject::connect: Cannot connect %s::%s to %s::%s", sender ? sender->metaObject()->className() : "(null)", (signal && *signal) ? signal+1 : "(null)", receiver ? receiver->metaObject()->className() : "(null)", (method && *method) ? method+1 : "(null)"); - return QMetaObject::Connection(0); + return QMetaObject::Connection(nullptr); } QByteArray tmp_signal_name; if (!check_signal_macro(sender, signal, "connect", "bind")) - return QMetaObject::Connection(0); + return QMetaObject::Connection(nullptr); const QMetaObject *smeta = sender->metaObject(); const char *signal_arg = signal; ++signal; //skip code @@ -2833,7 +2821,7 @@ QMetaObject::Connection QObject::connect(const QObject *sender, const char *sign if (signal_index < 0) { err_method_notfound(sender, signal_arg, "connect"); err_info_about_objects("connect", sender, receiver); - return QMetaObject::Connection(0); + return QMetaObject::Connection(nullptr); } signal_index = QMetaObjectPrivate::originalClone(smeta, signal_index); signal_index += QMetaObjectPrivate::signalOffset(smeta); @@ -2842,7 +2830,7 @@ QMetaObject::Connection QObject::connect(const QObject *sender, const char *sign int membcode = extract_code(method); if (!check_method_code(membcode, receiver, method, "connect")) - return QMetaObject::Connection(0); + return QMetaObject::Connection(nullptr); const char *method_arg = method; ++method; // skip code @@ -2885,7 +2873,7 @@ QMetaObject::Connection QObject::connect(const QObject *sender, const char *sign if (method_index_relative < 0) { err_method_notfound(receiver, method_arg, "connect"); err_info_about_objects("connect", sender, receiver); - return QMetaObject::Connection(0); + return QMetaObject::Connection(nullptr); } if (!QMetaObjectPrivate::checkConnectArgs(signalTypes.size(), signalTypes.constData(), @@ -2894,13 +2882,13 @@ QMetaObject::Connection QObject::connect(const QObject *sender, const char *sign "\n %s::%s --> %s::%s", sender->metaObject()->className(), signal, receiver->metaObject()->className(), method); - return QMetaObject::Connection(0); + return QMetaObject::Connection(nullptr); } - int *types = 0; + int *types = nullptr; if ((type == Qt::QueuedConnection) && !(types = queuedConnectionTypes(signalTypes.constData(), signalTypes.size()))) { - return QMetaObject::Connection(0); + return QMetaObject::Connection(nullptr); } #ifndef QT_NO_DEBUG @@ -2937,8 +2925,8 @@ QMetaObject::Connection QObject::connect(const QObject *sender, const QMetaMetho const QObject *receiver, const QMetaMethod &method, Qt::ConnectionType type) { - if (sender == 0 - || receiver == 0 + if (sender == nullptr + || receiver == nullptr || signal.methodType() != QMetaMethod::Signal || method.methodType() == QMetaMethod::Constructor) { qWarning("QObject::connect: Cannot connect %s::%s to %s::%s", @@ -2946,7 +2934,7 @@ QMetaObject::Connection QObject::connect(const QObject *sender, const QMetaMetho signal.methodSignature().constData(), receiver ? receiver->metaObject()->className() : "(null)", method.methodSignature().constData() ); - return QMetaObject::Connection(0); + return QMetaObject::Connection(nullptr); } int signal_index; @@ -2962,12 +2950,12 @@ QMetaObject::Connection QObject::connect(const QObject *sender, const QMetaMetho if (signal_index == -1) { qWarning("QObject::connect: Can't find signal %s on instance of class %s", signal.methodSignature().constData(), smeta->className()); - return QMetaObject::Connection(0); + return QMetaObject::Connection(nullptr); } if (method_index == -1) { qWarning("QObject::connect: Can't find method %s on instance of class %s", method.methodSignature().constData(), rmeta->className()); - return QMetaObject::Connection(0); + return QMetaObject::Connection(nullptr); } if (!QMetaObject::checkConnectArgs(signal.methodSignature().constData(), method.methodSignature().constData())) { @@ -2975,19 +2963,19 @@ QMetaObject::Connection QObject::connect(const QObject *sender, const QMetaMetho "\n %s::%s --> %s::%s", smeta->className(), signal.methodSignature().constData(), rmeta->className(), method.methodSignature().constData()); - return QMetaObject::Connection(0); + return QMetaObject::Connection(nullptr); } - int *types = 0; + int *types = nullptr; if ((type == Qt::QueuedConnection) && !(types = queuedConnectionTypes(signal.parameterTypes()))) - return QMetaObject::Connection(0); + return QMetaObject::Connection(nullptr); #ifndef QT_NO_DEBUG check_and_warn_compat(smeta, signal, rmeta, method); #endif QMetaObject::Connection handle = QMetaObject::Connection(QMetaObjectPrivate::connect( - sender, signal_index, signal.enclosingMetaObject(), receiver, method_index, 0, type, types)); + sender, signal_index, signal.enclosingMetaObject(), receiver, method_index, nullptr, type, types)); return handle; } @@ -3070,7 +3058,7 @@ QMetaObject::Connection QObject::connect(const QObject *sender, const QMetaMetho bool QObject::disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method) { - if (sender == 0 || (receiver == 0 && method != 0)) { + if (sender == nullptr || (receiver == nullptr && method != nullptr)) { qWarning("QObject::disconnect: Unexpected null parameter"); return false; } @@ -3142,7 +3130,7 @@ bool QObject::disconnect(const QObject *sender, const char *signal, } if (!method) { - res |= QMetaObjectPrivate::disconnect(sender, signal_index, smeta, receiver, -1, 0); + res |= QMetaObjectPrivate::disconnect(sender, signal_index, smeta, receiver, -1, nullptr); } else { const QMetaObject *rmeta = receiver->metaObject(); do { @@ -3153,7 +3141,7 @@ bool QObject::disconnect(const QObject *sender, const char *signal, rmeta = rmeta->superClass(); if (method_index < 0) break; - res |= QMetaObjectPrivate::disconnect(sender, signal_index, smeta, receiver, method_index, 0); + res |= QMetaObjectPrivate::disconnect(sender, signal_index, smeta, receiver, method_index, nullptr); method_found = true; } while ((rmeta = rmeta->superClass())); } @@ -3205,7 +3193,7 @@ bool QObject::disconnect(const QObject *sender, const char *signal, bool QObject::disconnect(const QObject *sender, const QMetaMethod &signal, const QObject *receiver, const QMetaMethod &method) { - if (sender == 0 || (receiver == 0 && method.mobj != 0)) { + if (sender == nullptr || (receiver == nullptr && method.mobj != nullptr)) { qWarning("QObject::disconnect: Unexpected null parameter"); return false; } @@ -3254,7 +3242,7 @@ bool QObject::disconnect(const QObject *sender, const QMetaMethod &signal, return false; } - if (!QMetaObjectPrivate::disconnect(sender, signal_index, signal.mobj, receiver, method_index, 0)) + if (!QMetaObjectPrivate::disconnect(sender, signal_index, signal.mobj, receiver, method_index, nullptr)) return false; if (!signal.isValid()) { @@ -3393,7 +3381,7 @@ QMetaObject::Connection QMetaObject::connect(const QObject *sender, int signal_i signal_index = methodIndexToSignalIndex(&smeta, signal_index); return Connection(QMetaObjectPrivate::connect(sender, signal_index, smeta, receiver, method_index, - 0, //FIXME, we could speed this connection up by computing the relative index + nullptr, //FIXME, we could speed this connection up by computing the relative index type, types)); } @@ -3469,7 +3457,7 @@ bool QMetaObject::disconnect(const QObject *sender, int signal_index, const QMetaObject *smeta = sender->metaObject(); signal_index = methodIndexToSignalIndex(&smeta, signal_index); return QMetaObjectPrivate::disconnect(sender, signal_index, smeta, - receiver, method_index, 0); + receiver, method_index, nullptr); } /*! @@ -3485,7 +3473,7 @@ bool QMetaObject::disconnectOne(const QObject *sender, int signal_index, const QMetaObject *smeta = sender->metaObject(); signal_index = methodIndexToSignalIndex(&smeta, signal_index); return QMetaObjectPrivate::disconnect(sender, signal_index, smeta, - receiver, method_index, 0, + receiver, method_index, nullptr, QMetaObjectPrivate::DisconnectOne); } @@ -3694,7 +3682,7 @@ static void queued_activate(QObject *sender, int signal, QObjectPrivate::Connect argumentTypes = queuedConnectionTypes(m.parameterTypes()); if (!argumentTypes) // cannot queue arguments argumentTypes = &DIRECT_CONNECTION_ONLY; - if (!c->argumentTypes.testAndSetOrdered(0, argumentTypes)) { + if (!c->argumentTypes.testAndSetOrdered(nullptr, argumentTypes)) { if (argumentTypes != &DIRECT_CONNECTION_ONLY) delete [] argumentTypes; argumentTypes = c->argumentTypes.loadRelaxed(); @@ -3794,7 +3782,7 @@ void doActivate(QObject *sender, int signal_index, void **argv) list = &signalVector->at(-1); Qt::HANDLE currentThreadId = QThread::currentThreadId(); - bool inSenderThread = currentThreadId == QObjectPrivate::get(sender)->threadData->threadId.loadRelaxed(); + bool inSenderThread = currentThreadId == QObjectPrivate::get(sender)->threadData.loadRelaxed()->threadId.loadRelaxed(); // We need to check against the highest connection id to ensure that signals added // during the signal emission are not emitted in this emission. @@ -4305,10 +4293,10 @@ QObjectUserData* QObject::userData(uint id) const { Q_D(const QObject); if (!d->extraData) - return 0; + return nullptr; if ((int)id < d->extraData->userData.size()) return d->extraData->userData.at(id); - return 0; + return nullptr; } #endif // QT_NO_USERDATA @@ -4964,7 +4952,7 @@ QMetaObject::Connection QObject::connectImpl(const QObject *sender, void **signa if (!senderMetaObject) { qWarning("QObject::connect: signal not found in %s", sender->metaObject()->className()); slotObj->destroyIfLastRef(); - return QMetaObject::Connection(0); + return QMetaObject::Connection(nullptr); } signal_index += QMetaObjectPrivate::signalOffset(senderMetaObject); return QObjectPrivate::connectImpl(sender, signal_index, receiver, slot, slotObj, type, types, senderMetaObject); @@ -5150,7 +5138,7 @@ bool QObject::disconnect(const QMetaObject::Connection &connection) bool QObject::disconnectImpl(const QObject *sender, void **signal, const QObject *receiver, void **slot, const QMetaObject *senderMetaObject) { - if (sender == 0 || (receiver == 0 && slot != 0)) { + if (sender == nullptr || (receiver == nullptr && slot != nullptr)) { qWarning("QObject::disconnect: Unexpected null parameter"); return false; } @@ -5190,7 +5178,7 @@ QMetaObject::Connection QObjectPrivate::connect(const QObject *sender, int signa const QMetaObject *senderMetaObject = sender->metaObject(); signal_index = methodIndexToSignalIndex(&senderMetaObject, signal_index); - return QObjectPrivate::connectImpl(sender, signal_index, sender, /*slot*/0, slotObj, type, /*types*/0, senderMetaObject); + return QObjectPrivate::connectImpl(sender, signal_index, sender, /*slot*/nullptr, slotObj, type, /*types*/nullptr, senderMetaObject); } /*! @@ -5247,7 +5235,7 @@ QMetaObject::Connection& QMetaObject::Connection::operator=(const QMetaObject::C Creates a Connection instance. */ -QMetaObject::Connection::Connection() : d_ptr(0) {} +QMetaObject::Connection::Connection() : d_ptr(nullptr) {} /*! Destructor for QMetaObject::Connection. diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h index feafcaf323..1ebf8e7a07 100644 --- a/src/corelib/kernel/qobject_p.h +++ b/src/corelib/kernel/qobject_p.h @@ -374,7 +374,13 @@ public: } public: ExtraData *extraData; // extra data set by the user - QThreadData *threadData; // id of the thread that owns the object + QThreadData *getThreadData() const { return threadData.loadAcquire(); } + // This atomic requires acquire/release semantics in a few places, + // e.g. QObject::moveToThread must synchronize with QCoreApplication::postEvent, + // because postEvent is thread-safe. + // However, most of the code paths involving QObject are only reentrant and + // not thread-safe, so synchronization should not be necessary there. + QAtomicPointer<QThreadData> threadData; // id of the thread that owns the object using ConnectionDataPointer = QExplicitlySharedDataPointer<ConnectionData>; QAtomicPointer<ConnectionData> connections; diff --git a/src/corelib/kernel/qobjectcleanuphandler.cpp b/src/corelib/kernel/qobjectcleanuphandler.cpp index b6c62af4b3..8bf0e1fcab 100644 --- a/src/corelib/kernel/qobjectcleanuphandler.cpp +++ b/src/corelib/kernel/qobjectcleanuphandler.cpp @@ -94,7 +94,7 @@ QObjectCleanupHandler::~QObjectCleanupHandler() QObject *QObjectCleanupHandler::add(QObject* object) { if (!object) - return 0; + return nullptr; connect(object, SIGNAL(destroyed(QObject*)), this, SLOT(objectDestroyed(QObject*))); cleanupObjects.insert(0, object); diff --git a/src/corelib/kernel/qsharedmemory.cpp b/src/corelib/kernel/qsharedmemory.cpp index 39f3002394..2d65e0bbe4 100644 --- a/src/corelib/kernel/qsharedmemory.cpp +++ b/src/corelib/kernel/qsharedmemory.cpp @@ -441,7 +441,7 @@ bool QSharedMemory::attach(AccessMode mode) bool QSharedMemory::isAttached() const { Q_D(const QSharedMemory); - return (0 != d->memory); + return (nullptr != d->memory); } /*! diff --git a/src/corelib/kernel/qsharedmemory_systemv.cpp b/src/corelib/kernel/qsharedmemory_systemv.cpp index fea4a65b5c..0ba5f65641 100644 --- a/src/corelib/kernel/qsharedmemory_systemv.cpp +++ b/src/corelib/kernel/qsharedmemory_systemv.cpp @@ -182,9 +182,9 @@ bool QSharedMemoryPrivate::attach(QSharedMemory::AccessMode mode) } // grab the memory - memory = shmat(id, 0, (mode == QSharedMemory::ReadOnly ? SHM_RDONLY : 0)); + memory = shmat(id, nullptr, (mode == QSharedMemory::ReadOnly ? SHM_RDONLY : 0)); if ((void*) - 1 == memory) { - memory = 0; + memory = nullptr; setErrorString(QLatin1String("QSharedMemory::attach (shmat)")); return false; } @@ -216,7 +216,7 @@ bool QSharedMemoryPrivate::detach() } return false; } - memory = 0; + memory = nullptr; size = 0; // Get the number of current attachments diff --git a/src/corelib/kernel/qsharedmemory_unix.cpp b/src/corelib/kernel/qsharedmemory_unix.cpp index f6d7e78441..bc0f3b03ca 100644 --- a/src/corelib/kernel/qsharedmemory_unix.cpp +++ b/src/corelib/kernel/qsharedmemory_unix.cpp @@ -68,7 +68,7 @@ QSharedMemoryPrivate::QSharedMemoryPrivate() : #ifndef QT_NO_QOBJECT QObjectPrivate(), #endif - memory(0), size(0), error(QSharedMemory::NoError), + memory(nullptr), size(0), error(QSharedMemory::NoError), #ifndef QT_NO_SYSTEMSEMAPHORE systemSemaphore(QString()), lockedByMe(false), #endif diff --git a/src/corelib/kernel/qsocketnotifier.cpp b/src/corelib/kernel/qsocketnotifier.cpp index 2a246b1204..78269ee605 100644 --- a/src/corelib/kernel/qsocketnotifier.cpp +++ b/src/corelib/kernel/qsocketnotifier.cpp @@ -147,12 +147,14 @@ QSocketNotifier::QSocketNotifier(qintptr socket, Type type, QObject *parent) d->sntype = type; d->snenabled = true; + auto thisThreadData = d->threadData.loadRelaxed(); + if (socket < 0) qWarning("QSocketNotifier: Invalid socket specified"); - else if (!d->threadData->hasEventDispatcher()) + else if (!thisThreadData->hasEventDispatcher()) qWarning("QSocketNotifier: Can only be used with threads started with QThread"); else - d->threadData->eventDispatcher.loadRelaxed()->registerSocketNotifier(this); + thisThreadData->eventDispatcher.loadRelaxed()->registerSocketNotifier(this); } /*! @@ -234,16 +236,19 @@ void QSocketNotifier::setEnabled(bool enable) return; d->snenabled = enable; - if (!d->threadData->hasEventDispatcher()) // perhaps application/thread is shutting down + + auto thisThreadData = d->threadData.loadRelaxed(); + + if (!thisThreadData->hasEventDispatcher()) // perhaps application/thread is shutting down return; if (Q_UNLIKELY(thread() != QThread::currentThread())) { qWarning("QSocketNotifier: Socket notifiers cannot be enabled or disabled from another thread"); return; } if (d->snenabled) - d->threadData->eventDispatcher.loadRelaxed()->registerSocketNotifier(this); + thisThreadData->eventDispatcher.loadRelaxed()->registerSocketNotifier(this); else - d->threadData->eventDispatcher.loadRelaxed()->unregisterSocketNotifier(this); + thisThreadData->eventDispatcher.loadRelaxed()->unregisterSocketNotifier(this); } diff --git a/src/corelib/kernel/qtestsupport_core.cpp b/src/corelib/kernel/qtestsupport_core.cpp index 7bd81ed498..8498f7f025 100644 --- a/src/corelib/kernel/qtestsupport_core.cpp +++ b/src/corelib/kernel/qtestsupport_core.cpp @@ -55,7 +55,7 @@ Q_CORE_EXPORT void QTestPrivate::qSleep(int ms) Sleep(uint(ms)); #else struct timespec ts = { time_t(ms / 1000), (ms % 1000) * 1000 * 1000 }; - nanosleep(&ts, NULL); + nanosleep(&ts, nullptr); #endif } diff --git a/src/corelib/kernel/qtimer.cpp b/src/corelib/kernel/qtimer.cpp index 4d8778ecf5..25ce0c032f 100644 --- a/src/corelib/kernel/qtimer.cpp +++ b/src/corelib/kernel/qtimer.cpp @@ -277,7 +277,7 @@ protected: }; QSingleShotTimer::QSingleShotTimer(int msec, Qt::TimerType timerType, const QObject *r, const char *member) - : QObject(QAbstractEventDispatcher::instance()), hasValidReceiver(true), slotObj(0) + : QObject(QAbstractEventDispatcher::instance()), hasValidReceiver(true), slotObj(nullptr) { timerId = startTimer(msec, timerType); connect(this, SIGNAL(timeout()), r, member); @@ -290,7 +290,7 @@ QSingleShotTimer::QSingleShotTimer(int msec, Qt::TimerType timerType, const QObj if (r && thread() != r->thread()) { // Avoid leaking the QSingleShotTimer instance in case the application exits before the timer fires connect(QCoreApplication::instance(), &QCoreApplication::aboutToQuit, this, &QObject::deleteLater); - setParent(0); + setParent(nullptr); moveToThread(r->thread()); } } @@ -316,7 +316,7 @@ void QSingleShotTimer::timerEvent(QTimerEvent *) if (Q_LIKELY(!receiver.isNull() || !hasValidReceiver)) { // We allocate only the return type - we previously checked the function had // no arguments. - void *args[1] = { 0 }; + void *args[1] = { nullptr }; slotObj->call(const_cast<QObject*>(receiver.data()), args); } } else { diff --git a/src/corelib/kernel/qtimerinfo_unix.cpp b/src/corelib/kernel/qtimerinfo_unix.cpp index 39010c19cb..b425ca3dcb 100644 --- a/src/corelib/kernel/qtimerinfo_unix.cpp +++ b/src/corelib/kernel/qtimerinfo_unix.cpp @@ -83,7 +83,7 @@ QTimerInfoList::QTimerInfoList() } #endif - firstTimerInfo = 0; + firstTimerInfo = nullptr; } timespec QTimerInfoList::updateCurrentTime() @@ -389,7 +389,7 @@ bool QTimerInfoList::timerWait(timespec &tm) repairTimersIfNeeded(); // Find first waiting timer not already active - QTimerInfo *t = 0; + QTimerInfo *t = nullptr; for (QTimerInfoList::const_iterator it = constBegin(); it != constEnd(); ++it) { if (!(*it)->activateRef) { t = *it; @@ -450,7 +450,7 @@ void QTimerInfoList::registerTimer(int timerId, int interval, Qt::TimerType time t->interval = interval; t->timerType = timerType; t->obj = object; - t->activateRef = 0; + t->activateRef = nullptr; timespec expected = updateCurrentTime() + interval; @@ -514,9 +514,9 @@ bool QTimerInfoList::unregisterTimer(int timerId) // found it removeAt(i); if (t == firstTimerInfo) - firstTimerInfo = 0; + firstTimerInfo = nullptr; if (t->activateRef) - *(t->activateRef) = 0; + *(t->activateRef) = nullptr; delete t; return true; } @@ -535,9 +535,9 @@ bool QTimerInfoList::unregisterTimers(QObject *object) // object found removeAt(i); if (t == firstTimerInfo) - firstTimerInfo = 0; + firstTimerInfo = nullptr; if (t->activateRef) - *(t->activateRef) = 0; + *(t->activateRef) = nullptr; delete t; // move back one so that we don't skip the new current item --i; @@ -571,7 +571,7 @@ int QTimerInfoList::activateTimers() return 0; // nothing to do int n_act = 0, maxCount = 0; - firstTimerInfo = 0; + firstTimerInfo = nullptr; timespec currentTime = updateCurrentTime(); // qDebug() << "Thread" << QThread::currentThreadId() << "woken up at" << currentTime; @@ -643,11 +643,11 @@ int QTimerInfoList::activateTimers() QCoreApplication::sendEvent(currentTimerInfo->obj, &e); if (currentTimerInfo) - currentTimerInfo->activateRef = 0; + currentTimerInfo->activateRef = nullptr; } } - firstTimerInfo = 0; + firstTimerInfo = nullptr; // qDebug() << "Thread" << QThread::currentThreadId() << "activated" << n_act << "timers"; return n_act; } diff --git a/src/corelib/kernel/qtranslator.cpp b/src/corelib/kernel/qtranslator.cpp index ddb96ecad6..93d75feafa 100644 --- a/src/corelib/kernel/qtranslator.cpp +++ b/src/corelib/kernel/qtranslator.cpp @@ -289,8 +289,8 @@ public: #if defined(QT_USE_MMAP) used_mmap(0), #endif - unmapPointer(0), unmapLength(0), resource(0), - messageArray(0), offsetArray(0), contextArray(0), numerusRulesArray(0), + unmapPointer(nullptr), unmapLength(0), resource(nullptr), + messageArray(nullptr), offsetArray(nullptr), contextArray(nullptr), numerusRulesArray(nullptr), messageLength(0), offsetLength(0), contextLength(0), numerusRulesLength(0) {} #if defined(QT_USE_MMAP) @@ -539,7 +539,7 @@ bool QTranslatorPrivate::do_load(const QString &realname, const QString &directo ok = true; } else { delete resource; - resource = 0; + resource = nullptr; } } @@ -610,8 +610,8 @@ bool QTranslatorPrivate::do_load(const QString &realname, const QString &directo delete [] unmapPointer; delete d->resource; - d->resource = 0; - d->unmapPointer = 0; + d->resource = nullptr; + d->unmapPointer = nullptr; d->unmapLength = 0; return false; @@ -874,10 +874,10 @@ bool QTranslatorPrivate::do_load(const uchar *data, qsizetype len, const QString } if (!ok) { - messageArray = 0; - contextArray = 0; - offsetArray = 0; - numerusRulesArray = 0; + messageArray = nullptr; + contextArray = nullptr; + offsetArray = nullptr; + numerusRulesArray = nullptr; messageLength = 0; contextLength = 0; offsetLength = 0; @@ -890,7 +890,7 @@ bool QTranslatorPrivate::do_load(const uchar *data, qsizetype len, const QString static QString getMessage(const uchar *m, const uchar *end, const char *context, const char *sourceText, const char *comment, uint numerus) { - const uchar *tn = 0; + const uchar *tn = nullptr; uint tn_length = 0; const uint sourceTextLen = uint(strlen(sourceText)); const uint contextLen = uint(strlen(context)); @@ -957,11 +957,11 @@ end: QString QTranslatorPrivate::do_translate(const char *context, const char *sourceText, const char *comment, int n) const { - if (context == 0) + if (context == nullptr) context = ""; - if (sourceText == 0) + if (sourceText == nullptr) sourceText = ""; - if (comment == 0) + if (comment == nullptr) comment = ""; uint numerus = 0; @@ -1076,13 +1076,13 @@ void QTranslatorPrivate::clear() } delete resource; - resource = 0; - unmapPointer = 0; + resource = nullptr; + unmapPointer = nullptr; unmapLength = 0; - messageArray = 0; - contextArray = 0; - offsetArray = 0; - numerusRulesArray = 0; + messageArray = nullptr; + contextArray = nullptr; + offsetArray = nullptr; + numerusRulesArray = nullptr; messageLength = 0; contextLength = 0; offsetLength = 0; diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp index a1e1c71d12..40a401361d 100644 --- a/src/corelib/kernel/qvariant.cpp +++ b/src/corelib/kernel/qvariant.cpp @@ -2254,10 +2254,10 @@ QVariant::QVariant(const QRegularExpression &re) : d(RegularExpression) { v_construct<QRegularExpression>(&d, re); } #endif // QT_CONFIG(regularexpression) -#ifndef QT_BOOTSTRAPPED QVariant::QVariant(const QUuid &uuid) : d(Uuid) { v_construct<QUuid>(&d, uuid); } +#ifndef QT_BOOTSTRAPPED QVariant::QVariant(const QJsonValue &jsonValue) : d(QMetaType::QJsonValue) { v_construct<QJsonValue>(&d, jsonValue); } @@ -2523,7 +2523,7 @@ void QVariant::load(QDataStream &s) return; } } - create(typeId, 0); + create(typeId, nullptr); d.is_null = is_null; if (!isValid()) { @@ -3011,7 +3011,6 @@ QPersistentModelIndex QVariant::toPersistentModelIndex() const } #endif // QT_CONFIG(itemmodel) -#ifndef QT_BOOTSTRAPPED /*! \since 5.0 @@ -3026,6 +3025,7 @@ QUuid QVariant::toUuid() const return qVariantToHelper<QUuid>(d, handlerManager); } +#ifndef QT_BOOTSTRAPPED /*! \since 5.0 @@ -3829,6 +3829,7 @@ bool QVariant::convert(const int type, void *ptr) const /*! \fn bool QVariant::operator<(const QVariant &v) const + \obsolete Compares this QVariant with \a v and returns \c true if this is less than \a v. @@ -3838,10 +3839,15 @@ bool QVariant::convert(const int type, void *ptr) const \warning To make this function work with a custom type registered with qRegisterMetaType(), its comparison operator must be registered using QMetaType::registerComparators(). + + This operator is deprecated as it cannot establish a total order required + for most use of this operator, which is the reason you cannot use QVariant + as the key of a QMap. */ /*! \fn bool QVariant::operator<=(const QVariant &v) const + \obsolete Compares this QVariant with \a v and returns \c true if this is less or equal than \a v. @@ -3851,10 +3857,13 @@ bool QVariant::convert(const int type, void *ptr) const \warning To make this function work with a custom type registered with qRegisterMetaType(), its comparison operator must be registered using QMetaType::registerComparators(). + + This operator is deprecated as it cannot establish a total order. */ /*! \fn bool QVariant::operator>(const QVariant &v) const + \obsolete Compares this QVariant with \a v and returns \c true if this is larger than \a v. @@ -3864,10 +3873,13 @@ bool QVariant::convert(const int type, void *ptr) const \warning To make this function work with a custom type registered with qRegisterMetaType(), its comparison operator must be registered using QMetaType::registerComparators(). + + This operator is deprecated as it cannot establish a total order. */ /*! \fn bool QVariant::operator>=(const QVariant &v) const + \obsolete Compares this QVariant with \a v and returns \c true if this is larger or equal than \a v. @@ -3877,6 +3889,8 @@ bool QVariant::convert(const int type, void *ptr) const \warning To make this function work with a custom type registered with qRegisterMetaType(), its comparison operator must be registered using QMetaType::registerComparators(). + + This operator is deprecated as it cannot establish a total order. */ static bool qIsNumericType(uint tp) diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h index a4957472ec..f48419c934 100644 --- a/src/corelib/kernel/qvariant.h +++ b/src/corelib/kernel/qvariant.h @@ -256,12 +256,12 @@ class Q_CORE_EXPORT QVariant #if QT_CONFIG(regularexpression) QVariant(const QRegularExpression &re); #endif // QT_CONFIG(regularexpression) -#ifndef QT_BOOTSTRAPPED - QVariant(const QUrl &url); #if QT_CONFIG(easingcurve) QVariant(const QEasingCurve &easing); #endif QVariant(const QUuid &uuid); +#ifndef QT_BOOTSTRAPPED + QVariant(const QUrl &url); QVariant(const QJsonValue &jsonValue); QVariant(const QJsonObject &jsonObject); QVariant(const QJsonArray &jsonArray); @@ -332,12 +332,12 @@ class Q_CORE_EXPORT QVariant #if QT_CONFIG(regularexpression) QRegularExpression toRegularExpression() const; #endif // QT_CONFIG(regularexpression) -#ifndef QT_BOOTSTRAPPED - QUrl toUrl() const; #if QT_CONFIG(easingcurve) QEasingCurve toEasingCurve() const; #endif QUuid toUuid() const; +#ifndef QT_BOOTSTRAPPED + QUrl toUrl() const; QJsonValue toJsonValue() const; QJsonObject toJsonObject() const; QJsonArray toJsonArray() const; @@ -463,14 +463,16 @@ class Q_CORE_EXPORT QVariant { return cmp(v); } inline bool operator!=(const QVariant &v) const { return !cmp(v); } - inline bool operator<(const QVariant &v) const +#if QT_DEPRECATED_SINCE(5, 15) + QT_DEPRECATED inline bool operator<(const QVariant &v) const { return compare(v) < 0; } - inline bool operator<=(const QVariant &v) const + QT_DEPRECATED inline bool operator<=(const QVariant &v) const { return compare(v) <= 0; } - inline bool operator>(const QVariant &v) const + QT_DEPRECATED inline bool operator>(const QVariant &v) const { return compare(v) > 0; } - inline bool operator>=(const QVariant &v) const + QT_DEPRECATED inline bool operator>=(const QVariant &v) const { return compare(v) >= 0; } +#endif protected: friend inline bool operator==(const QVariant &, const QVariantComparisonHelper &); diff --git a/src/corelib/kernel/qwineventnotifier.cpp b/src/corelib/kernel/qwineventnotifier.cpp index d2ae9668fe..db5d44b276 100644 --- a/src/corelib/kernel/qwineventnotifier.cpp +++ b/src/corelib/kernel/qwineventnotifier.cpp @@ -124,7 +124,7 @@ QWinEventNotifier::QWinEventNotifier(HANDLE hEvent, QObject *parent) : QObject(*new QWinEventNotifierPrivate(hEvent, false), parent) { Q_D(QWinEventNotifier); - QAbstractEventDispatcher *eventDispatcher = d->threadData->eventDispatcher.loadRelaxed(); + QAbstractEventDispatcher *eventDispatcher = d->threadData.loadRelaxed()->eventDispatcher.loadRelaxed(); if (Q_UNLIKELY(!eventDispatcher)) { qWarning("QWinEventNotifier: Can only be used with threads started with QThread"); return; @@ -197,7 +197,7 @@ void QWinEventNotifier::setEnabled(bool enable) return; d->enabled = enable; - QAbstractEventDispatcher *eventDispatcher = d->threadData->eventDispatcher.loadRelaxed(); + QAbstractEventDispatcher *eventDispatcher = d->threadData.loadRelaxed()->eventDispatcher.loadRelaxed(); if (!eventDispatcher) { // perhaps application is shutting down if (!enable && d->waitHandle != nullptr) d->unregisterWaitObject(); @@ -256,7 +256,7 @@ void QWinEventNotifierPrivate::unregisterWaitObject() static void CALLBACK wfsoCallback(void *context, BOOLEAN /*ignore*/) { QWinEventNotifierPrivate *nd = reinterpret_cast<QWinEventNotifierPrivate *>(context); - QAbstractEventDispatcher *eventDispatcher = nd->threadData->eventDispatcher.loadRelaxed(); + QAbstractEventDispatcher *eventDispatcher = nd->threadData.loadRelaxed()->eventDispatcher.loadRelaxed(); // Happens when Q(Core)Application is destroyed before QWinEventNotifier. // https://bugreports.qt.io/browse/QTBUG-70214 |