diff options
author | Alexandru Croitor <alexandru.croitor@qt.io> | 2019-10-11 16:16:29 +0200 |
---|---|---|
committer | Alexandru Croitor <alexandru.croitor@qt.io> | 2019-10-11 16:23:19 +0200 |
commit | f4b4c4f79b629498f3cddbbc10df8c1b4d6020d9 (patch) | |
tree | 4119707660438ff58bd51f9cbe0f9e2a33f4b806 /src/corelib/kernel | |
parent | 9bd6cec74dbbc5aece55dc0c8808494db29b9963 (diff) | |
parent | 93f2f33a49f6c96a4f94f344edf03164ed944d02 (diff) |
Merge remote-tracking branch 'origin/wip/qt6' into wip/cmake
Change-Id: I3a1d7673c3c20019ab12a2ea0a60f1619920a34c
Diffstat (limited to 'src/corelib/kernel')
-rw-r--r-- | src/corelib/kernel/qcore_mac.cpp | 3 | ||||
-rw-r--r-- | src/corelib/kernel/qcore_mac_p.h | 12 | ||||
-rw-r--r-- | src/corelib/kernel/qcore_unix.cpp | 4 | ||||
-rw-r--r-- | src/corelib/kernel/qcoreapplication.cpp | 29 | ||||
-rw-r--r-- | src/corelib/kernel/qcoreapplication_win.cpp | 3 | ||||
-rw-r--r-- | src/corelib/kernel/qeventdispatcher_win.cpp | 67 | ||||
-rw-r--r-- | src/corelib/kernel/qeventdispatcher_win_p.h | 2 | ||||
-rw-r--r-- | src/corelib/kernel/qmetaobject.cpp | 47 | ||||
-rw-r--r-- | src/corelib/kernel/qmetaobject_p.h | 8 | ||||
-rw-r--r-- | src/corelib/kernel/qmetatype.cpp | 2 | ||||
-rw-r--r-- | src/corelib/kernel/qmetatype.h | 9 | ||||
-rw-r--r-- | src/corelib/kernel/qmetatype_p.h | 2 | ||||
-rw-r--r-- | src/corelib/kernel/qobject.cpp | 210 | ||||
-rw-r--r-- | src/corelib/kernel/qobject.h | 24 | ||||
-rw-r--r-- | src/corelib/kernel/qobject_p.h | 53 | ||||
-rw-r--r-- | src/corelib/kernel/qvariant.cpp | 8 | ||||
-rw-r--r-- | src/corelib/kernel/qvariant.h | 8 |
17 files changed, 258 insertions, 233 deletions
diff --git a/src/corelib/kernel/qcore_mac.cpp b/src/corelib/kernel/qcore_mac.cpp index b048576f5b..e59835be48 100644 --- a/src/corelib/kernel/qcore_mac.cpp +++ b/src/corelib/kernel/qcore_mac.cpp @@ -44,6 +44,7 @@ #include "qpair.h" #include "qmutex.h" #include "qvarlengtharray.h" +#include "private/qlocking_p.h" QT_BEGIN_NAMESPACE @@ -135,7 +136,7 @@ os_log_type_t AppleUnifiedLogger::logTypeForMessageType(QtMsgType msgType) os_log_t AppleUnifiedLogger::cachedLog(const QString &subsystem, const QString &category) { static QBasicMutex mutex; - QMutexLocker locker(&mutex); + const auto locker = qt_scoped_lock(mutex); static QHash<QPair<QString, QString>, os_log_t> logs; const auto cacheKey = qMakePair(subsystem, category); diff --git a/src/corelib/kernel/qcore_mac_p.h b/src/corelib/kernel/qcore_mac_p.h index 447dcd9cbe..3266dc10a8 100644 --- a/src/corelib/kernel/qcore_mac_p.h +++ b/src/corelib/kernel/qcore_mac_p.h @@ -86,8 +86,14 @@ template <typename T, typename U, U (*RetainFunction)(U), void (*ReleaseFunction class QAppleRefCounted { public: - QAppleRefCounted(const T &t = T()) : value(t) {} - QAppleRefCounted(QAppleRefCounted &&other) : value(other.value) { other.value = T(); } + QAppleRefCounted() : value() {} + QAppleRefCounted(const T &t) : value(t) {} + QAppleRefCounted(T &&t) noexcept(std::is_nothrow_move_constructible<T>::value) + : value(std::move(t)) {} + QAppleRefCounted(QAppleRefCounted &&other) + noexcept(std::is_nothrow_move_assignable<T>::value && + std::is_nothrow_move_constructible<T>::value) + : value(qExchange(other.value, T())) {} QAppleRefCounted(const QAppleRefCounted &other) : value(other.value) { if (value) RetainFunction(value); } ~QAppleRefCounted() { if (value) ReleaseFunction(value); } operator T() const { return value; } @@ -96,6 +102,8 @@ public: QAppleRefCounted &operator=(const QAppleRefCounted &other) { QAppleRefCounted copy(other); swap(copy); return *this; } QAppleRefCounted &operator=(QAppleRefCounted &&other) + noexcept(std::is_nothrow_move_assignable<T>::value && + std::is_nothrow_move_constructible<T>::value) { QAppleRefCounted moved(std::move(other)); swap(moved); return *this; } T *operator&() { return &value; } protected: diff --git a/src/corelib/kernel/qcore_unix.cpp b/src/corelib/kernel/qcore_unix.cpp index 18c031f137..ff0c957770 100644 --- a/src/corelib/kernel/qcore_unix.cpp +++ b/src/corelib/kernel/qcore_unix.cpp @@ -132,8 +132,10 @@ static inline int qt_ppoll(struct pollfd *fds, nfds_t nfds, const struct timespe return ::ppoll(fds, nfds, timeout_ts, nullptr); #elif QT_CONFIG(poll_poll) return ::poll(fds, nfds, timespecToMillisecs(timeout_ts)); -#else +#elif QT_CONFIG(poll_select) return qt_poll(fds, nfds, timeout_ts); +#else + // configure.json reports an error when everything is not available #endif } diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index 2feeae5394..1ecef00a2d 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -55,6 +55,7 @@ #include <qfileinfo.h> #include <qmutex.h> #include <private/qloggingregistry_p.h> +#include <qscopeguard.h> #include <qstandardpaths.h> #ifndef QT_NO_QOBJECT #include <qthread.h> @@ -70,6 +71,7 @@ #include <private/qfactoryloader_p.h> #include <private/qfunctions_p.h> #include <private/qlocale_p.h> +#include <private/qlocking_p.h> #include <private/qhooks_p.h> #ifndef QT_NO_QOBJECT @@ -294,7 +296,7 @@ void qAddPreRoutine(QtStartUpFunction p) // Due to C++11 parallel dynamic initialization, this can be called // from multiple threads. - QMutexLocker locker(&globalRoutinesMutex); + const auto locker = qt_scoped_lock(globalRoutinesMutex); list->prepend(p); // in case QCoreApplication is re-created, see qt_call_pre_routines } @@ -303,7 +305,7 @@ void qAddPostRoutine(QtCleanUpFunction p) QVFuncList *list = postRList(); if (!list) return; - QMutexLocker locker(&globalRoutinesMutex); + const auto locker = qt_scoped_lock(globalRoutinesMutex); list->prepend(p); } @@ -312,7 +314,7 @@ void qRemovePostRoutine(QtCleanUpFunction p) QVFuncList *list = postRList(); if (!list) return; - QMutexLocker locker(&globalRoutinesMutex); + const auto locker = qt_scoped_lock(globalRoutinesMutex); list->removeAll(p); } @@ -323,7 +325,7 @@ static void qt_call_pre_routines() QVFuncList list; { - QMutexLocker locker(&globalRoutinesMutex); + const auto locker = qt_scoped_lock(globalRoutinesMutex); // Unlike qt_call_post_routines, we don't empty the list, because // Q_COREAPP_STARTUP_FUNCTION is a macro, so the user expects // the function to be executed every time QCoreApplication is created. @@ -342,7 +344,7 @@ void Q_CORE_EXPORT qt_call_post_routines() QVFuncList list; { // extract the current list and make the stored list empty - QMutexLocker locker(&globalRoutinesMutex); + const auto locker = qt_scoped_lock(globalRoutinesMutex); qSwap(*postRList, list); } @@ -522,7 +524,7 @@ void QCoreApplicationPrivate::cleanupThreadData() #endif // need to clear the state of the mainData, just in case a new QCoreApplication comes along. - QMutexLocker locker(&threadData->postEventList.mutex); + 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); if (pe.event) { @@ -1705,7 +1707,7 @@ void QCoreApplicationPrivate::sendPostedEvents(QObject *receiver, int event_type ++data->postEventList.recursion; - QMutexLocker locker(&data->postEventList.mutex); + auto locker = qt_unique_lock(data->postEventList.mutex); // by default, we assume that the event dispatcher can go to sleep after // processing all events. if any new events are posted while we send @@ -1821,13 +1823,8 @@ void QCoreApplicationPrivate::sendPostedEvents(QObject *receiver, int event_type // for the next event. const_cast<QPostEvent &>(pe).event = 0; - struct MutexUnlocker - { - QMutexLocker &m; - MutexUnlocker(QMutexLocker &m) : m(m) { m.unlock(); } - ~MutexUnlocker() { m.relock(); } - }; - MutexUnlocker unlocker(locker); + locker.unlock(); + const auto relocker = qScopeGuard([&locker] { locker.lock(); }); QScopedPointer<QEvent> event_deleter(e); // will delete the event (with the mutex unlocked) @@ -1864,7 +1861,7 @@ void QCoreApplicationPrivate::sendPostedEvents(QObject *receiver, int event_type void QCoreApplication::removePostedEvents(QObject *receiver, int eventType) { QThreadData *data = receiver ? receiver->d_func()->threadData : QThreadData::current(); - QMutexLocker locker(&data->postEventList.mutex); + auto locker = qt_unique_lock(data->postEventList.mutex); // the QObject destructor calls this function directly. this can // happen while the event loop is in the middle of posting events, @@ -1927,7 +1924,7 @@ void QCoreApplicationPrivate::removePostedEvent(QEvent * event) QThreadData *data = QThreadData::current(); - QMutexLocker locker(&data->postEventList.mutex); + const auto locker = qt_scoped_lock(data->postEventList.mutex); if (data->postEventList.size() == 0) { #if defined(QT_DEBUG) diff --git a/src/corelib/kernel/qcoreapplication_win.cpp b/src/corelib/kernel/qcoreapplication_win.cpp index 3f22c309ff..37c43dee4f 100644 --- a/src/corelib/kernel/qcoreapplication_win.cpp +++ b/src/corelib/kernel/qcoreapplication_win.cpp @@ -47,6 +47,7 @@ #ifndef QT_NO_QOBJECT #include "qmutex.h" #include <private/qthread_p.h> +#include <private/qlocking_p.h> #endif #include "qtextstream.h" #include <ctype.h> @@ -919,7 +920,7 @@ void QCoreApplicationPrivate::removePostedTimerEvent(QObject *object, int timerI { QThreadData *data = object->d_func()->threadData; - QMutexLocker locker(&data->postEventList.mutex); + const auto locker = qt_scoped_lock(data->postEventList.mutex); if (data->postEventList.size() == 0) return; for (int i = 0; i < data->postEventList.size(); ++i) { diff --git a/src/corelib/kernel/qeventdispatcher_win.cpp b/src/corelib/kernel/qeventdispatcher_win.cpp index c15d740f9e..87623f304a 100644 --- a/src/corelib/kernel/qeventdispatcher_win.cpp +++ b/src/corelib/kernel/qeventdispatcher_win.cpp @@ -100,7 +100,7 @@ LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPA QEventDispatcherWin32Private::QEventDispatcherWin32Private() : threadId(GetCurrentThreadId()), interrupt(false), internalHwnd(0), - wakeUps(0), activateNotifiersPosted(false), + getMessageHook(0), wakeUps(0), activateNotifiersPosted(false), winEventNotifierActivatedEvent(NULL) { } @@ -245,9 +245,6 @@ LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPA case WM_QT_SENDPOSTEDEVENTS: Q_ASSERT(d != 0); - // Allow posting WM_QT_SENDPOSTEDEVENTS message. - d->wakeUps.storeRelaxed(0); - // We send posted events manually, if the window procedure was invoked // by the foreign event loop (e.g. from the native modal dialog). q->sendPostedEvents(); @@ -257,9 +254,9 @@ LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPA return DefWindowProc(hwnd, message, wp, lp); } -static inline UINT inputTimerMask() +static inline UINT inputQueueMask() { - UINT result = QS_TIMER | QS_INPUT | QS_RAWINPUT; + UINT result = QS_ALLEVENTS; // QTBUG 28513, QTBUG-29097, QTBUG-29435: QS_TOUCH, QS_POINTER became part of // QS_INPUT in Windows Kit 8. They should not be used when running on pre-Windows 8. #if WINVER > 0x0601 @@ -269,6 +266,25 @@ static inline UINT inputTimerMask() return result; } +LRESULT QT_WIN_CALLBACK qt_GetMessageHook(int code, WPARAM wp, LPARAM lp) +{ + QEventDispatcherWin32 *q = qobject_cast<QEventDispatcherWin32 *>(QAbstractEventDispatcher::instance()); + Q_ASSERT(q != 0); + QEventDispatcherWin32Private *d = q->d_func(); + MSG *msg = reinterpret_cast<MSG *>(lp); + static const UINT mask = inputQueueMask(); + + if (HIWORD(GetQueueStatus(mask)) == 0 && wp == PM_REMOVE) { + // Allow posting WM_QT_SENDPOSTEDEVENTS message. + d->wakeUps.storeRelaxed(0); + if (!(msg->hwnd == d->internalHwnd && msg->message == WM_QT_SENDPOSTEDEVENTS)) { + PostMessage(d->internalHwnd, WM_QT_SENDPOSTEDEVENTS, + WMWP_QT_TOFOREIGNLOOP, 0); + } + } + return d->getMessageHook ? CallNextHookEx(0, code, wp, lp) : 0; +} + // Provide class name and atom for the message window used by // QEventDispatcherWin32Private via Q_GLOBAL_STATIC shared between threads. struct QWindowsMessageWindowClassContext @@ -447,6 +463,14 @@ void QEventDispatcherWin32::createInternalHwnd() return; d->internalHwnd = qt_create_internal_window(this); + // setup GetMessage hook needed to drive our posted events + d->getMessageHook = SetWindowsHookEx(WH_GETMESSAGE, (HOOKPROC) qt_GetMessageHook, NULL, GetCurrentThreadId()); + if (Q_UNLIKELY(!d->getMessageHook)) { + int errorCode = GetLastError(); + qFatal("Qt: INTERNAL ERROR: failed to install GetMessage hook: %d, %ls", + errorCode, qUtf16Printable(qt_error_string(errorCode))); + } + // start all normal timers for (int i = 0; i < d->timerVec.count(); ++i) d->registerTimer(d->timerVec.at(i)); @@ -499,7 +523,6 @@ bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags) bool canWait; bool retVal = false; - bool needWM_QT_SENDPOSTEDEVENTS = false; do { DWORD waitRet = 0; DWORD nCount = 0; @@ -549,11 +572,8 @@ bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags) if (haveMessage) { if (d->internalHwnd == msg.hwnd && msg.message == WM_QT_SENDPOSTEDEVENTS) { // Set result to 'true', if the message was sent by wakeUp(). - if (msg.wParam == WMWP_QT_FROMWAKEUP) { - d->wakeUps.storeRelaxed(0); + if (msg.wParam == WMWP_QT_FROMWAKEUP) retVal = true; - } - needWM_QT_SENDPOSTEDEVENTS = true; continue; } if (msg.message == WM_TIMER) { @@ -573,22 +593,10 @@ bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags) } if (!filterNativeEvent(QByteArrayLiteral("windows_generic_MSG"), &msg, 0)) { - // Post WM_QT_SENDPOSTEDEVENTS before calling external code, - // as it can start a foreign event loop. - if (needWM_QT_SENDPOSTEDEVENTS) { - needWM_QT_SENDPOSTEDEVENTS = false; - PostMessage(d->internalHwnd, WM_QT_SENDPOSTEDEVENTS, - WMWP_QT_TOFOREIGNLOOP, 0); - } TranslateMessage(&msg); DispatchMessage(&msg); } } else if (waitRet - WAIT_OBJECT_0 < nCount) { - if (needWM_QT_SENDPOSTEDEVENTS) { - needWM_QT_SENDPOSTEDEVENTS = false; - PostMessage(d->internalHwnd, WM_QT_SENDPOSTEDEVENTS, - WMWP_QT_TOFOREIGNLOOP, 0); - } activateEventNotifiers(); } else { // nothing todo so break @@ -606,21 +614,12 @@ bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags) waitRet = MsgWaitForMultipleObjectsEx(nCount, pHandles, INFINITE, QS_ALLINPUT, MWMO_ALERTABLE | MWMO_INPUTAVAILABLE); emit awake(); if (waitRet - WAIT_OBJECT_0 < nCount) { - if (needWM_QT_SENDPOSTEDEVENTS) { - needWM_QT_SENDPOSTEDEVENTS = false; - PostMessage(d->internalHwnd, WM_QT_SENDPOSTEDEVENTS, - WMWP_QT_TOFOREIGNLOOP, 0); - } activateEventNotifiers(); retVal = true; } } } while (canWait); - if (needWM_QT_SENDPOSTEDEVENTS) - PostMessage(d->internalHwnd, WM_QT_SENDPOSTEDEVENTS, - WMWP_QT_TOFOREIGNLOOP, 0); - return retVal; } @@ -1004,6 +1003,10 @@ void QEventDispatcherWin32::closingDown() d->timerDict.clear(); d->closingDown = true; + + if (d->getMessageHook) + UnhookWindowsHookEx(d->getMessageHook); + d->getMessageHook = 0; } bool QEventDispatcherWin32::event(QEvent *e) diff --git a/src/corelib/kernel/qeventdispatcher_win_p.h b/src/corelib/kernel/qeventdispatcher_win_p.h index 697c07f912..e6620178d8 100644 --- a/src/corelib/kernel/qeventdispatcher_win_p.h +++ b/src/corelib/kernel/qeventdispatcher_win_p.h @@ -113,6 +113,7 @@ protected: private: friend LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp); + friend LRESULT QT_WIN_CALLBACK qt_GetMessageHook(int, WPARAM, LPARAM); }; struct QSockNot { @@ -166,6 +167,7 @@ public: // internal window handle used for socketnotifiers/timers/etc HWND internalHwnd; + HHOOK getMessageHook; // for controlling when to send posted events QAtomicInt wakeUps; diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp index acb1f54bdf..cc396d9239 100644 --- a/src/corelib/kernel/qmetaobject.cpp +++ b/src/corelib/kernel/qmetaobject.cpp @@ -814,6 +814,7 @@ int QMetaObjectPrivate::indexOfConstructor(const QMetaObject *m, const QByteArra } /*! + \fn int QMetaObjectPrivate::signalOffset(const QMetaObject *m) \internal \since 5.0 @@ -823,14 +824,6 @@ int QMetaObjectPrivate::indexOfConstructor(const QMetaObject *m, const QByteArra Similar to QMetaObject::methodOffset(), but non-signal methods are excluded. */ -int QMetaObjectPrivate::signalOffset(const QMetaObject *m) -{ - Q_ASSERT(m != 0); - int offset = 0; - for (m = m->d.superdata; m; m = m->d.superdata) - offset += priv(m->d.data)->signalCount; - return offset; -} /*! \internal @@ -1542,21 +1535,14 @@ bool QMetaObject::invokeMethodImpl(QObject *object, QtPrivate::QSlotObjectBase * return false; } - // args and typesCopy will be deallocated by ~QMetaCallEvent() using free() - void **args = static_cast<void **>(calloc(1, sizeof(void *))); - Q_CHECK_PTR(args); - - int *types = static_cast<int *>(calloc(1, sizeof(int))); - Q_CHECK_PTR(types); - - QCoreApplication::postEvent(object, new QMetaCallEvent(slot, 0, -1, 1, types, args)); + QCoreApplication::postEvent(object, new QMetaCallEvent(slot, 0, -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, 0, 0, argv, &semaphore)); + QCoreApplication::postEvent(object, new QMetaCallEvent(slot, 0, -1, argv, &semaphore)); semaphore.acquire(); #endif // QT_CONFIG(thread) } else { @@ -2310,42 +2296,31 @@ bool QMetaMethod::invoke(QObject *object, return false; } - int nargs = 1; // include return type - void **args = (void **) malloc(paramCount * sizeof(void *)); - Q_CHECK_PTR(args); - int *types = (int *) malloc(paramCount * sizeof(int)); - Q_CHECK_PTR(types); - types[0] = 0; // return type - args[0] = 0; + QScopedPointer<QMetaCallEvent> event(new QMetaCallEvent(idx_offset, idx_relative, callFunction, 0, -1, paramCount)); + int *types = event->types(); + void **args = event->args(); + int argIndex = 0; for (int i = 1; i < paramCount; ++i) { types[i] = QMetaType::type(typeNames[i]); if (types[i] == QMetaType::UnknownType && param[i]) { // Try to register the type and try again before reporting an error. - int index = nargs - 1; - void *argv[] = { &types[i], &index }; + void *argv[] = { &types[i], &argIndex }; QMetaObject::metacall(object, QMetaObject::RegisterMethodArgumentMetaType, idx_relative + idx_offset, argv); if (types[i] == -1) { qWarning("QMetaMethod::invoke: Unable to handle unregistered datatype '%s'", typeNames[i]); - for (int x = 1; x < i; ++x) { - if (types[x] && args[x]) - QMetaType::destroy(types[x], args[x]); - } - free(types); - free(args); return false; } } if (types[i] != QMetaType::UnknownType) { args[i] = QMetaType::create(types[i], param[i]); - ++nargs; + ++argIndex; } } - QCoreApplication::postEvent(object, new QMetaCallEvent(idx_offset, idx_relative, callFunction, - 0, -1, nargs, types, args)); + QCoreApplication::postEvent(object, event.take()); } else { // blocking queued connection #if QT_CONFIG(thread) QThread *currentThread = QThread::currentThread(); @@ -2358,7 +2333,7 @@ bool QMetaMethod::invoke(QObject *object, QSemaphore semaphore; QCoreApplication::postEvent(object, new QMetaCallEvent(idx_offset, idx_relative, callFunction, - 0, -1, 0, 0, param, &semaphore)); + 0, -1, param, &semaphore)); semaphore.acquire(); #endif // QT_CONFIG(thread) } diff --git a/src/corelib/kernel/qmetaobject_p.h b/src/corelib/kernel/qmetaobject_p.h index 0cd9da2eac..56e3d6cb44 100644 --- a/src/corelib/kernel/qmetaobject_p.h +++ b/src/corelib/kernel/qmetaobject_p.h @@ -208,7 +208,13 @@ struct QMetaObjectPrivate static int indexOfConstructor(const QMetaObject *m, const QByteArray &name, int argc, const QArgumentType *types); Q_CORE_EXPORT static QMetaMethod signal(const QMetaObject *m, int signal_index); - Q_CORE_EXPORT static int signalOffset(const QMetaObject *m); + static inline int signalOffset(const QMetaObject *m) { + Q_ASSERT(m != nullptr); + int offset = 0; + for (m = m->d.superdata; m; m = m->d.superdata) + offset += reinterpret_cast<const QMetaObjectPrivate*>(m->d.data)->signalCount; + return offset; + } Q_CORE_EXPORT static int absoluteSignalCount(const QMetaObject *m); Q_CORE_EXPORT static int signalIndex(const QMetaMethod &m); static bool checkConnectArgs(int signalArgc, const QArgumentType *signalTypes, diff --git a/src/corelib/kernel/qmetatype.cpp b/src/corelib/kernel/qmetatype.cpp index 754f5a13e4..356a675517 100644 --- a/src/corelib/kernel/qmetatype.cpp +++ b/src/corelib/kernel/qmetatype.cpp @@ -47,7 +47,9 @@ #include "qstringlist.h" #include "qvector.h" #include "qlocale.h" +#if QT_CONFIG(easingcurve) #include "qeasingcurve.h" +#endif #include "quuid.h" #include "qvariant.h" #include "qdatastream.h" diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h index 44cce73359..94a32cec02 100644 --- a/src/corelib/kernel/qmetatype.h +++ b/src/corelib/kernel/qmetatype.h @@ -94,6 +94,13 @@ inline Q_DECL_CONSTEXPR int qMetaTypeId(); #define QT_FOR_EACH_STATIC_PRIMITIVE_POINTER(F)\ F(VoidStar, 31, void*) \ +#if QT_CONFIG(easingcurve) +#define QT_FOR_EACH_STATIC_EASINGCURVE(F)\ + F(QEasingCurve, 29, QEasingCurve) +#else +#define QT_FOR_EACH_STATIC_EASINGCURVE(F) +#endif + #if QT_CONFIG(itemmodel) #define QT_FOR_EACH_STATIC_ITEMMODEL_CLASS(F)\ F(QModelIndex, 42, QModelIndex) \ @@ -122,7 +129,7 @@ inline Q_DECL_CONSTEXPR int qMetaTypeId(); F(QPoint, 25, QPoint) \ F(QPointF, 26, QPointF) \ F(QRegExp, 27, QRegExp) \ - F(QEasingCurve, 29, QEasingCurve) \ + QT_FOR_EACH_STATIC_EASINGCURVE(F) \ F(QUuid, 30, QUuid) \ F(QVariant, 41, QVariant) \ F(QRegularExpression, 44, QRegularExpression) \ diff --git a/src/corelib/kernel/qmetatype_p.h b/src/corelib/kernel/qmetatype_p.h index fa7208369a..d743d5a5c7 100644 --- a/src/corelib/kernel/qmetatype_p.h +++ b/src/corelib/kernel/qmetatype_p.h @@ -206,7 +206,9 @@ template<> struct TypeDefinition<QCborArray> { static const bool IsAvailable = f template<> struct TypeDefinition<QCborMap> { static const bool IsAvailable = false; }; template<> struct TypeDefinition<QCborSimpleType> { static const bool IsAvailable = false; }; template<> struct TypeDefinition<QCborValue> { static const bool IsAvailable = false; }; +#if QT_CONFIG(easingcurve) template<> struct TypeDefinition<QEasingCurve> { static const bool IsAvailable = false; }; +#endif template<> struct TypeDefinition<QJsonArray> { static const bool IsAvailable = false; }; template<> struct TypeDefinition<QJsonDocument> { static const bool IsAvailable = false; }; template<> struct TypeDefinition<QJsonObject> { static const bool IsAvailable = false; }; diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index d364ae1087..ef28c0164c 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -233,10 +233,6 @@ QObjectPrivate::~QObjectPrivate() if (metaObject) metaObject->objectDestroyed(q_ptr); -#ifndef QT_NO_USERDATA - if (extraData) - qDeleteAll(extraData->userData); -#endif delete extraData; } @@ -511,25 +507,85 @@ QAbstractMetaCallEvent::~QAbstractMetaCallEvent() /*! \internal */ -QMetaCallEvent::QMetaCallEvent(ushort method_offset, ushort method_relative, QObjectPrivate::StaticMetaCallFunction callFunction, +inline void QMetaCallEvent::allocArgs() +{ + if (!d.nargs_) + return; + + constexpr size_t each = sizeof(void*) + sizeof(int); + void *const memory = d.nargs_ * each > sizeof(prealloc_) ? + calloc(d.nargs_, each) : prealloc_; + + Q_CHECK_PTR(memory); + d.args_ = static_cast<void **>(memory); +} + +/*! + \internal + + Used for blocking queued connections, just passes \a args through without + allocating any memory. + */ +QMetaCallEvent::QMetaCallEvent(ushort method_offset, ushort method_relative, + QObjectPrivate::StaticMetaCallFunction callFunction, const QObject *sender, int signalId, - int nargs, int *types, void **args, QSemaphore *semaphore) + void **args, QSemaphore *semaphore) : QAbstractMetaCallEvent(sender, signalId, semaphore), - slotObj_(nullptr), nargs_(nargs), types_(types), args_(args), - callFunction_(callFunction), method_offset_(method_offset), method_relative_(method_relative) -{ } + d({nullptr, args, callFunction, 0, method_offset, method_relative}), + prealloc_() +{ +} /*! \internal + + Used for blocking queued connections, just passes \a args through without + allocating any memory. */ -QMetaCallEvent::QMetaCallEvent(QtPrivate::QSlotObjectBase *slotO, const QObject *sender, int signalId, - int nargs, int *types, void **args, QSemaphore *semaphore) +QMetaCallEvent::QMetaCallEvent(QtPrivate::QSlotObjectBase *slotO, + const QObject *sender, int signalId, + void **args, QSemaphore *semaphore) : QAbstractMetaCallEvent(sender, signalId, semaphore), - slotObj_(slotO), nargs_(nargs), types_(types), args_(args), - callFunction_(nullptr), method_offset_(0), method_relative_(ushort(-1)) + d({slotO, args, nullptr, 0, 0, ushort(-1)}), + prealloc_() { - if (slotObj_) - slotObj_->ref(); + if (d.slotObj_) + d.slotObj_->ref(); +} + +/*! + \internal + + Allocates memory for \a nargs; code creating an event needs to initialize + the void* and int arrays by accessing \a args() and \a types(), respectively. + */ +QMetaCallEvent::QMetaCallEvent(ushort method_offset, ushort method_relative, + QObjectPrivate::StaticMetaCallFunction callFunction, + const QObject *sender, int signalId, + int nargs) + : QAbstractMetaCallEvent(sender, signalId), + d({nullptr, nullptr, callFunction, nargs, method_offset, method_relative}), + prealloc_() +{ + allocArgs(); +} + +/*! + \internal + + Allocates memory for \a nargs; code creating an event needs to initialize + the void* and int arrays by accessing \a args() and \a types(), respectively. + */ +QMetaCallEvent::QMetaCallEvent(QtPrivate::QSlotObjectBase *slotO, + const QObject *sender, int signalId, + int nargs) + : QAbstractMetaCallEvent(sender, signalId), + d({slotO, nullptr, nullptr, nargs, 0, ushort(-1)}), + prealloc_() +{ + if (d.slotObj_) + d.slotObj_->ref(); + allocArgs(); } /*! @@ -537,16 +593,17 @@ QMetaCallEvent::QMetaCallEvent(QtPrivate::QSlotObjectBase *slotO, const QObject */ QMetaCallEvent::~QMetaCallEvent() { - if (types_) { - for (int i = 0; i < nargs_; ++i) { - if (types_[i] && args_[i]) - QMetaType::destroy(types_[i], args_[i]); + if (d.nargs_) { + int *typeIDs = types(); + for (int i = 0; i < d.nargs_; ++i) { + if (typeIDs[i] && d.args_[i]) + QMetaType::destroy(typeIDs[i], d.args_[i]); } - free(types_); - free(args_); + if (reinterpret_cast<void*>(d.args_) != reinterpret_cast<void*>(prealloc_)) + free(d.args_); } - if (slotObj_) - slotObj_->destroyIfLastRef(); + if (d.slotObj_) + d.slotObj_->destroyIfLastRef(); } /*! @@ -554,12 +611,13 @@ QMetaCallEvent::~QMetaCallEvent() */ void QMetaCallEvent::placeMetaCall(QObject *object) { - if (slotObj_) { - slotObj_->call(object, args_); - } else if (callFunction_ && method_offset_ <= object->metaObject()->methodOffset()) { - callFunction_(object, QMetaObject::InvokeMetaMethod, method_relative_, args_); + if (d.slotObj_) { + d.slotObj_->call(object, d.args_); + } else if (d.callFunction_ && d.method_offset_ <= object->metaObject()->methodOffset()) { + d.callFunction_(object, QMetaObject::InvokeMetaMethod, d.method_relative_, d.args_); } else { - QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, method_offset_ + method_relative_, args_); + QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, + d.method_offset_ + d.method_relative_, d.args_); } } @@ -3643,12 +3701,25 @@ static void queued_activate(QObject *sender, int signal, QObjectPrivate::Connect int nargs = 1; // include return type while (argumentTypes[nargs-1]) ++nargs; - int *types = (int *) malloc(nargs*sizeof(int)); - Q_CHECK_PTR(types); - void **args = (void **) malloc(nargs*sizeof(void *)); - Q_CHECK_PTR(args); + + QBasicMutexLocker locker(signalSlotLock(c->receiver.loadRelaxed())); + if (!c->receiver.loadRelaxed()) { + // the connection has been disconnected before we got the lock + return; + } + if (c->isSlotObject) + c->slotObj->ref(); + locker.unlock(); + + QMetaCallEvent *ev = c->isSlotObject ? + new QMetaCallEvent(c->slotObj, sender, signal, nargs) : + new QMetaCallEvent(c->method_offset, c->method_relative, c->callFunction, sender, signal, nargs); + + void **args = ev->args(); + int *types = ev->types(); + types[0] = 0; // return type - args[0] = 0; // return value + args[0] = nullptr; // return value if (nargs > 1) { for (int n = 1; n < nargs; ++n) @@ -3658,20 +3729,16 @@ static void queued_activate(QObject *sender, int signal, QObjectPrivate::Connect args[n] = QMetaType::create(types[n], argv[n]); } - QBasicMutexLocker locker(signalSlotLock(c->receiver.loadRelaxed())); + locker.relock(); + if (c->isSlotObject) + c->slotObj->destroyIfLastRef(); if (!c->receiver.loadRelaxed()) { - // the connection has been disconnected before we got the lock + // the connection has been disconnected while we were unlocked locker.unlock(); - for (int n = 1; n < nargs; ++n) - QMetaType::destroy(types[n], args[n]); - free(types); - free(args); + delete ev; return; } - QMetaCallEvent *ev = c->isSlotObject ? - new QMetaCallEvent(c->slotObj, sender, signal, nargs, types, args) : - new QMetaCallEvent(c->method_offset, c->method_relative, c->callFunction, sender, signal, nargs, types, args); QCoreApplication::postEvent(c->receiver.loadRelaxed(), ev); } @@ -3772,8 +3839,9 @@ void doActivate(QObject *sender, int signal_index, void **argv) if (!c->receiver.loadAcquire()) continue; QMetaCallEvent *ev = c->isSlotObject ? - new QMetaCallEvent(c->slotObj, sender, signal_index, 0, 0, argv, &semaphore) : - new QMetaCallEvent(c->method_offset, c->method_relative, c->callFunction, sender, signal_index, 0, 0, argv, &semaphore); + new QMetaCallEvent(c->slotObj, sender, signal_index, argv, &semaphore) : + new QMetaCallEvent(c->method_offset, c->method_relative, c->callFunction, + sender, signal_index, argv, &semaphore); QCoreApplication::postEvent(receiver, ev); } semaphore.acquire(); @@ -4188,58 +4256,6 @@ void QObject::dumpObjectInfo() const } } -#ifndef QT_NO_USERDATA -static QBasicAtomicInteger<uint> user_data_registration = Q_BASIC_ATOMIC_INITIALIZER(0); - -/*! - \internal - */ -uint QObject::registerUserData() -{ - return user_data_registration.fetchAndAddRelaxed(1); -} - -/*! - \fn QObjectUserData::QObjectUserData() - \internal - */ - -/*! - \internal - */ -QObjectUserData::~QObjectUserData() -{ -} - -/*! - \internal - */ -void QObject::setUserData(uint id, QObjectUserData* data) -{ - Q_D(QObject); - if (!d->extraData) - d->extraData = new QObjectPrivate::ExtraData; - - if (d->extraData->userData.size() <= (int) id) - d->extraData->userData.resize((int) id + 1); - d->extraData->userData[id] = data; -} - -/*! - \internal - */ -QObjectUserData* QObject::userData(uint id) const -{ - Q_D(const QObject); - if (!d->extraData) - return 0; - if ((int)id < d->extraData->userData.size()) - return d->extraData->userData.at(id); - return 0; -} - -#endif // QT_NO_USERDATA - #ifndef QT_NO_DEBUG_STREAM QDebug operator<<(QDebug dbg, const QObject *o) @@ -5096,7 +5112,7 @@ bool QObject::disconnectImpl(const QObject *sender, void **signal, const QObject } if (!senderMetaObject) { qWarning("QObject::disconnect: signal not found in %s", sender->metaObject()->className()); - return QMetaObject::Connection(0); + return false; } signal_index += QMetaObjectPrivate::signalOffset(senderMetaObject); } diff --git a/src/corelib/kernel/qobject.h b/src/corelib/kernel/qobject.h index 540b8b32c1..296552c2f2 100644 --- a/src/corelib/kernel/qobject.h +++ b/src/corelib/kernel/qobject.h @@ -78,12 +78,6 @@ class QRegExp; #if QT_CONFIG(regularexpression) class QRegularExpression; #endif -#if !QT_DEPRECATED_SINCE(5, 14) || QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) -# define QT_NO_USERDATA -#endif -#ifndef QT_NO_USERDATA -class QObjectUserData; -#endif struct QDynamicMetaObjectData; typedef QList<QObject*> QObjectList; @@ -408,15 +402,6 @@ public: QList<QByteArray> dynamicPropertyNames() const; #endif // QT_NO_PROPERTIES -#ifndef QT_NO_USERDATA - QT_DEPRECATED_VERSION_5_14 - static uint registerUserData(); - QT_DEPRECATED_VERSION_X_5_14("Use setProperty()") - void setUserData(uint id, QObjectUserData* data); - QT_DEPRECATED_VERSION_X_5_14("Use property()") - QObjectUserData* userData(uint id) const; -#endif // QT_NO_USERDATA - Q_SIGNALS: void destroyed(QObject * = nullptr); void objectNameChanged(const QString &objectName, QPrivateSignal); @@ -485,15 +470,6 @@ inline QMetaObject::Connection QObject::connect(const QObject *asender, const ch inline const QMetaObject *qt_getQtMetaObject() noexcept { return &QObject::staticQtMetaObject; } -#ifndef QT_NO_USERDATA -class Q_CORE_EXPORT QObjectUserData { - Q_DISABLE_COPY(QObjectUserData) -public: - QObjectUserData() = default; - virtual ~QObjectUserData(); -}; -#endif - #if QT_DEPRECATED_SINCE(5, 0) template<typename T> inline QT_DEPRECATED T qFindChild(const QObject *o, const QString &name = QString()) diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h index 95ffc1b2e8..d19d10b47c 100644 --- a/src/corelib/kernel/qobject_p.h +++ b/src/corelib/kernel/qobject_p.h @@ -113,9 +113,6 @@ public: struct ExtraData { ExtraData() {} - #ifndef QT_NO_USERDATA - QVector<QObjectUserData *> userData; - #endif QList<QByteArray> propertyNames; QVector<QVariant> propertyValues; QVector<int> runningTimers; @@ -509,29 +506,47 @@ private: class Q_CORE_EXPORT QMetaCallEvent : public QAbstractMetaCallEvent { public: - QMetaCallEvent(ushort method_offset, ushort method_relative, QObjectPrivate::StaticMetaCallFunction callFunction , const QObject *sender, int signalId, - int nargs = 0, int *types = nullptr, void **args = nullptr, QSemaphore *semaphore = nullptr); - /*! \internal - \a signalId is in the signal index range (see QObjectPrivate::signalIndex()). - */ - QMetaCallEvent(QtPrivate::QSlotObjectBase *slotObj, const QObject *sender, int signalId, - int nargs = 0, int *types = nullptr, void **args = nullptr, QSemaphore *semaphore = nullptr); + // blocking queued with semaphore - args always owned by caller + QMetaCallEvent(ushort method_offset, ushort method_relative, + QObjectPrivate::StaticMetaCallFunction callFunction, + const QObject *sender, int signalId, + void **args, QSemaphore *semaphore); + QMetaCallEvent(QtPrivate::QSlotObjectBase *slotObj, + const QObject *sender, int signalId, + void **args, QSemaphore *semaphore); + + // queued - args allocated by event, copied by caller + QMetaCallEvent(ushort method_offset, ushort method_relative, + QObjectPrivate::StaticMetaCallFunction callFunction, + const QObject *sender, int signalId, + int nargs); + QMetaCallEvent(QtPrivate::QSlotObjectBase *slotObj, + const QObject *sender, int signalId, + int nargs); ~QMetaCallEvent() override; - inline int id() const { return method_offset_ + method_relative_; } - inline void **args() const { return args_; } + inline int id() const { return d.method_offset_ + d.method_relative_; } + inline const void * const* args() const { return d.args_; } + inline void ** args() { return d.args_; } + inline const int *types() const { return reinterpret_cast<int*>(d.args_ + d.nargs_); } + inline int *types() { return reinterpret_cast<int*>(d.args_ + d.nargs_); } virtual void placeMetaCall(QObject *object) override; private: - QtPrivate::QSlotObjectBase *slotObj_; - int nargs_; - int *types_; - void **args_; - QObjectPrivate::StaticMetaCallFunction callFunction_; - ushort method_offset_; - ushort method_relative_; + inline void allocArgs(); + + struct Data { + QtPrivate::QSlotObjectBase *slotObj_; + void **args_; + QObjectPrivate::StaticMetaCallFunction callFunction_; + int nargs_; + ushort method_offset_; + ushort method_relative_; + } d; + // preallocate enough space for three arguments + char prealloc_[3*(sizeof(void*) + sizeof(int))]; }; class QBoolBlocker diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp index 1cd812ee0b..f7fa47c801 100644 --- a/src/corelib/kernel/qvariant.cpp +++ b/src/corelib/kernel/qvariant.cpp @@ -46,7 +46,9 @@ #include "qdebug.h" #include "qmap.h" #include "qdatetime.h" +#if QT_CONFIG(easingcurve) #include "qeasingcurve.h" +#endif #include "qlist.h" #if QT_CONFIG(regularexpression) #include "qregularexpression.h" @@ -2194,7 +2196,7 @@ QVariant::QVariant(const QTime &val) QVariant::QVariant(const QDateTime &val) : d(DateTime) { v_construct<QDateTime>(&d, val); } -#ifndef QT_BOOTSTRAPPED +#if QT_CONFIG(easingcurve) QVariant::QVariant(const QEasingCurve &val) : d(EasingCurve) { v_construct<QEasingCurve>(&d, val); } @@ -2471,7 +2473,9 @@ static const ushort mapIdFromQt3ToCurrent[MapFromThreeCount] = QVariant::Pen, QVariant::LongLong, QVariant::ULongLong, +#if QT_CONFIG(easingcurve) QVariant::EasingCurve +#endif }; /*! @@ -2788,7 +2792,7 @@ QDateTime QVariant::toDateTime() const \sa canConvert(int targetTypeId), convert() */ -#ifndef QT_BOOTSTRAPPED +#if QT_CONFIG(easingcurve) QEasingCurve QVariant::toEasingCurve() const { return qVariantToHelper<QEasingCurve>(d, handlerManager); diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h index 39b7e4c0ce..e7d3d9c835 100644 --- a/src/corelib/kernel/qvariant.h +++ b/src/corelib/kernel/qvariant.h @@ -66,7 +66,9 @@ class QBitArray; class QDataStream; class QDate; class QDateTime; +#if QT_CONFIG(easingcurve) class QEasingCurve; +#endif class QLine; class QLineF; class QLocale; @@ -162,7 +164,9 @@ class Q_CORE_EXPORT QVariant RegExp = QMetaType::QRegExp, RegularExpression = QMetaType::QRegularExpression, Hash = QMetaType::QVariantHash, +#if QT_CONFIG(easingcurve) EasingCurve = QMetaType::QEasingCurve, +#endif Uuid = QMetaType::QUuid, #if QT_CONFIG(itemmodel) ModelIndex = QMetaType::QModelIndex, @@ -254,7 +258,9 @@ class Q_CORE_EXPORT QVariant #endif // QT_CONFIG(regularexpression) #ifndef QT_BOOTSTRAPPED QVariant(const QUrl &url); +#if QT_CONFIG(easingcurve) QVariant(const QEasingCurve &easing); +#endif QVariant(const QUuid &uuid); QVariant(const QJsonValue &jsonValue); QVariant(const QJsonObject &jsonObject); @@ -328,7 +334,9 @@ class Q_CORE_EXPORT QVariant #endif // QT_CONFIG(regularexpression) #ifndef QT_BOOTSTRAPPED QUrl toUrl() const; +#if QT_CONFIG(easingcurve) QEasingCurve toEasingCurve() const; +#endif QUuid toUuid() const; QJsonValue toJsonValue() const; QJsonObject toJsonObject() const; |