summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel
diff options
context:
space:
mode:
authorAlexandru Croitor <alexandru.croitor@qt.io>2019-10-11 16:16:29 +0200
committerAlexandru Croitor <alexandru.croitor@qt.io>2019-10-11 16:23:19 +0200
commitf4b4c4f79b629498f3cddbbc10df8c1b4d6020d9 (patch)
tree4119707660438ff58bd51f9cbe0f9e2a33f4b806 /src/corelib/kernel
parent9bd6cec74dbbc5aece55dc0c8808494db29b9963 (diff)
parent93f2f33a49f6c96a4f94f344edf03164ed944d02 (diff)
Merge remote-tracking branch 'origin/wip/qt6' into wip/cmake
Diffstat (limited to 'src/corelib/kernel')
-rw-r--r--src/corelib/kernel/qcore_mac.cpp3
-rw-r--r--src/corelib/kernel/qcore_mac_p.h12
-rw-r--r--src/corelib/kernel/qcore_unix.cpp4
-rw-r--r--src/corelib/kernel/qcoreapplication.cpp29
-rw-r--r--src/corelib/kernel/qcoreapplication_win.cpp3
-rw-r--r--src/corelib/kernel/qeventdispatcher_win.cpp67
-rw-r--r--src/corelib/kernel/qeventdispatcher_win_p.h2
-rw-r--r--src/corelib/kernel/qmetaobject.cpp47
-rw-r--r--src/corelib/kernel/qmetaobject_p.h8
-rw-r--r--src/corelib/kernel/qmetatype.cpp2
-rw-r--r--src/corelib/kernel/qmetatype.h9
-rw-r--r--src/corelib/kernel/qmetatype_p.h2
-rw-r--r--src/corelib/kernel/qobject.cpp210
-rw-r--r--src/corelib/kernel/qobject.h24
-rw-r--r--src/corelib/kernel/qobject_p.h53
-rw-r--r--src/corelib/kernel/qvariant.cpp8
-rw-r--r--src/corelib/kernel/qvariant.h8
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;