From 3af4b59e8b59c7b658c925e1f644d31b89e39896 Mon Sep 17 00:00:00 2001 From: Gatis Paeglis Date: Fri, 7 Sep 2018 13:48:34 +0200 Subject: glib dispatcher: rework userEventSourcePrepare() event source This is a better solution for fbb485d4f6985643b27da3cc6c5b5f960c32e74d. The existing solution was working fine, but it was exposing logic that is internal to QWindowSystemInterface and platform plugin interaction. Some platform plugins do event filtering at native event level - those that support QAbstractEventDispatcher::filterNativeEvent(). Other plugins rely on QWindowSystemInterface to do the filtering. Dispatchers should not care about this. The new logic rely on the fact that QWindowSystemInterfacePrivate::handleWindowSystemEvent calls QAbstractEventDispatcher::wakeUp(). The same way postEventSourcePrepare() rely on QCoreApplication::postEvent() to call QAbstractEventDispatcher::wakeUp(). Event sources run in the order they are attached, postEventSourcePrepare runs before userEventSourcePrepare(). We rely on that order to pass wakeUpCalled value. Change-Id: I0327f4f2398fd863fb2421b8033bb1df8d65f5af Reviewed-by: Allan Sandfeld Jensen Reviewed-by: Thiago Macieira --- src/corelib/kernel/qeventdispatcher_glib.cpp | 4 ++-- src/corelib/kernel/qeventdispatcher_glib_p.h | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qeventdispatcher_glib.cpp b/src/corelib/kernel/qeventdispatcher_glib.cpp index 4c780a9294..45c6e29e4b 100644 --- a/src/corelib/kernel/qeventdispatcher_glib.cpp +++ b/src/corelib/kernel/qeventdispatcher_glib.cpp @@ -260,8 +260,8 @@ static gboolean postEventSourcePrepare(GSource *s, gint *timeout) *timeout = canWait ? -1 : 0; GPostEventSource *source = reinterpret_cast(s); - return (!canWait - || (source->serialNumber.load() != source->lastSerialNumber)); + source->d->wakeUpCalled = source->serialNumber.load() != source->lastSerialNumber; + return !canWait || source->d->wakeUpCalled; } static gboolean postEventSourceCheck(GSource *source) diff --git a/src/corelib/kernel/qeventdispatcher_glib_p.h b/src/corelib/kernel/qeventdispatcher_glib_p.h index 799f23b14a..88ff316ee5 100644 --- a/src/corelib/kernel/qeventdispatcher_glib_p.h +++ b/src/corelib/kernel/qeventdispatcher_glib_p.h @@ -108,6 +108,7 @@ public: GSocketNotifierSource *socketNotifierSource; GTimerSource *timerSource; GIdleTimerSource *idleTimerSource; + bool wakeUpCalled = true; void runTimersOnceWithNormalPriority(); }; -- cgit v1.2.3 From 1f6bfc220774e9407fe88916843b76ed103cff72 Mon Sep 17 00:00:00 2001 From: Cristian Maureira-Fredes Date: Mon, 3 Sep 2018 14:02:13 +0200 Subject: Doc: Move literal code block to a separate file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We need to override this snippet for the documentation we generate for Qt for Python, and it is easier to have it on a separate file. Task-number: PYSIDE-801 Task-number: PYSIDE-691 Change-Id: Ideb5b6af25024279f167137d3b65660bb9c96a7e Reviewed-by: Topi Reiniö --- src/corelib/kernel/qdeadlinetimer.cpp | 85 ++++++-------------------------- src/corelib/kernel/qmetaobject.cpp | 20 +------- src/corelib/kernel/qobject.cpp | 13 +---- src/corelib/kernel/qtestsupport_core.cpp | 14 +----- 4 files changed, 20 insertions(+), 112 deletions(-) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qdeadlinetimer.cpp b/src/corelib/kernel/qdeadlinetimer.cpp index 66d0dce7e8..466056d513 100644 --- a/src/corelib/kernel/qdeadlinetimer.cpp +++ b/src/corelib/kernel/qdeadlinetimer.cpp @@ -75,17 +75,7 @@ Q_DECL_CONST_FUNCTION static inline QPair toSecsAndNSecs(qint64 QDeadlineTimer objects can be passed to functions being called to execute this operation so they know how long to still operate. - \code - void executeOperation(int msecs) - { - QDeadlineTimer deadline(msecs); - do { - if (readFromDevice(deadline.remainingTime()) - break; - waitForReadyRead(deadline); - } while (!deadline.hasExpired()); - } - \endcode + \snippet code/src_corelib_kernel_qdeadlinetimer.cpp 0 Many QDeadlineTimer functions deal with time out values, which all are measured in milliseconds. There are two special values, the same as many @@ -125,15 +115,7 @@ Q_DECL_CONST_FUNCTION static inline QPair toSecsAndNSecs(qint64 \c{std::chrono::time_point} objects. In addition, it is fully compatible with the time literals from C++14, which allow one to write code as: - \code - using namespace std::chrono; - using namespace std::chrono_literals; - - QDeadlineTimer deadline(30s); - device->waitForReadyRead(deadline); - if (deadline.remainingTime() > 300ms) - cleanup(); - \endcode + \snippet code/src_corelib_kernel_qdeadlinetimer.cpp 1 As can be seen in the example above, QDeadlineTimer offers a templated version of remainingTime() and deadline() that can be used to return @@ -145,13 +127,7 @@ Q_DECL_CONST_FUNCTION static inline QPair toSecsAndNSecs(qint64 Also note that, due to this conversion, the deadlines will not be precise, so the following code is not expected to compare equally: - \code - using namespace std::chrono; - using namespace std::chrono_literals; - auto now = steady_clock::now(); - QDeadlineTimer deadline(now + 1s); - Q_ASSERT(deadline == now + 1s); - \endcode + \snippet code/src_corelib_kernel_qdeadlinetimer.cpp 2 \sa QTime, QTimer, QDeadlineTimer, Qt::TimerType */ @@ -246,10 +222,7 @@ QDeadlineTimer::QDeadlineTimer(qint64 msecs, Qt::TimerType type) Q_DECL_NOTHROW This constructor can be used with C++14's user-defined literals for time, such as in: - \code - using namespace std::chrono_literals; - QDeadlineTimer deadline(250ms); - \endcode + \snippet code/src_corelib_kernel_qdeadlinetimer.cpp 3 For optimization purposes, if \a remaining is zero or negative, this function may skip obtaining the current time and may instead use a value @@ -339,10 +312,7 @@ void QDeadlineTimer::setPreciseRemainingTime(qint64 secs, qint64 nsecs, Qt::Time This function can be used with C++14's user-defined literals for time, such as in: - \code - using namespace std::chrono_literals; - deadline.setRemainingTime(250ms); - \endcode + \snippet code/src_corelib_kernel_qdeadlinetimer.cpp 4 \note Qt detects the necessary C++14 compiler support by way of the feature test recommendations from @@ -415,9 +385,7 @@ void QDeadlineTimer::setTimerType(Qt::TimerType timerType) lock functions in \l QMutex, \l QWaitCondition, \l QSemaphore, or \l QReadWriteLock. For example: - \code - mutex.tryLock(deadline.remainingTime()); - \endcode + \snippet code/src_corelib_kernel_qdeadlinetimer.cpp 5 \sa remainingTimeNSecs(), isForever(), hasExpired() */ @@ -469,16 +437,7 @@ qint64 QDeadlineTimer::rawRemainingTimeNSecs() const Q_DECL_NOTHROW overdue, by subtracting QDeadlineTimer::current() or QElapsedTimer::msecsSinceReference(), as in the following example: - \code - qint64 realTimeLeft = deadline.deadline(); - if (realTimeLeft != (std::numeric_limits::max)()) { - realTimeLeft -= QDeadlineTimer::current().deadline(); - // or: - //QElapsedTimer timer; - //timer.start(); - //realTimeLeft -= timer.msecsSinceReference(); - } - \endcode + \snippet code/src_corelib_kernel_qdeadlinetimer.cpp 6 \note Timers that were created as expired have an indetermine time point in the past as their deadline, so the above calculation may not work. @@ -505,11 +464,7 @@ qint64 QDeadlineTimer::deadline() const Q_DECL_NOTHROW overdue, by subtracting QDeadlineTimer::current(), as in the following example: - \code - qint64 realTimeLeft = deadline.deadlineNSecs(); - if (realTimeLeft != std::numeric_limits::max()) - realTimeLeft -= QDeadlineTimer::current().deadlineNSecs(); - \endcode + \snippet code/src_corelib_kernel_qdeadlinetimer.cpp 7 \note Timers that were created as expired have an indetermine time point in the past as their deadline, so the above calculation may not work. @@ -614,9 +569,7 @@ QDeadlineTimer QDeadlineTimer::addNSecs(QDeadlineTimer dt, qint64 nsecs) Q_DECL_ same, false otherwise. The timer type used to create the two deadlines is ignored. This function is equivalent to: - \code - return d1.deadlineNSecs() == d2.deadlineNSecs(); - \endcode + \snippet code/src_corelib_kernel_qdeadlinetimer.cpp 8 \note comparing QDeadlineTimer objects with different timer types is not supported and may result in unpredictable behavior. @@ -630,9 +583,7 @@ QDeadlineTimer QDeadlineTimer::addNSecs(QDeadlineTimer dt, qint64 nsecs) Q_DECL_ diferent, false otherwise. The timer type used to create the two deadlines is ignored. This function is equivalent to: - \code - return d1.deadlineNSecs() != d2.deadlineNSecs(); - \endcode + \snippet code/src_corelib_kernel_qdeadlinetimer.cpp 9 \note comparing QDeadlineTimer objects with different timer types is not supported and may result in unpredictable behavior. @@ -646,9 +597,7 @@ QDeadlineTimer QDeadlineTimer::addNSecs(QDeadlineTimer dt, qint64 nsecs) Q_DECL_ d2, false otherwise. The timer type used to create the two deadlines is ignored. This function is equivalent to: - \code - return d1.deadlineNSecs() < d2.deadlineNSecs(); - \endcode + \snippet code/src_corelib_kernel_qdeadlinetimer.cpp 10 \note comparing QDeadlineTimer objects with different timer types is not supported and may result in unpredictable behavior. @@ -662,9 +611,7 @@ QDeadlineTimer QDeadlineTimer::addNSecs(QDeadlineTimer dt, qint64 nsecs) Q_DECL_ deadline in \a d2, false otherwise. The timer type used to create the two deadlines is ignored. This function is equivalent to: - \code - return d1.deadlineNSecs() <= d2.deadlineNSecs(); - \endcode + \snippet code/src_corelib_kernel_qdeadlinetimer.cpp 11 \note comparing QDeadlineTimer objects with different timer types is not supported and may result in unpredictable behavior. @@ -678,9 +625,7 @@ QDeadlineTimer QDeadlineTimer::addNSecs(QDeadlineTimer dt, qint64 nsecs) Q_DECL_ d2, false otherwise. The timer type used to create the two deadlines is ignored. This function is equivalent to: - \code - return d1.deadlineNSecs() > d2.deadlineNSecs(); - \endcode + \snippet code/src_corelib_kernel_qdeadlinetimer.cpp 12 \note comparing QDeadlineTimer objects with different timer types is not supported and may result in unpredictable behavior. @@ -694,9 +639,7 @@ QDeadlineTimer QDeadlineTimer::addNSecs(QDeadlineTimer dt, qint64 nsecs) Q_DECL_ deadline in \a d2, false otherwise. The timer type used to create the two deadlines is ignored. This function is equivalent to: - \code - return d1.deadlineNSecs() >= d2.deadlineNSecs(); - \endcode + \snippet code/src_corelib_kernel_qdeadlinetimer.cpp 13 \note comparing QDeadlineTimer objects with different timer types is not supported and may result in unpredictable behavior. diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp index a6ee12ede1..ac911e287b 100644 --- a/src/corelib/kernel/qmetaobject.cpp +++ b/src/corelib/kernel/qmetaobject.cpp @@ -1996,27 +1996,11 @@ const char *QMetaMethod::typeName() const Tag information can be added in the following way in the function declaration: - \code - // In the class MainWindow declaration - #ifndef Q_MOC_RUN - // define the tag text as empty, so the compiler doesn't see it - # define MY_CUSTOM_TAG - #endif - ... - private slots: - MY_CUSTOM_TAG void testFunc(); - \endcode + \snippet code/src_corelib_kernel_qmetaobject.cpp 10 and the information can be accessed by using: - \code - MainWindow win; - win.show(); - - int functionIndex = win.metaObject()->indexOfSlot("testFunc()"); - QMetaMethod mm = win.metaObject()->method(functionIndex); - qDebug() << mm.tag(); // prints MY_CUSTOM_TAG - \endcode + \snippet code/src_corelib_kernel_qmetaobject.cpp 11 For the moment, \c moc will extract and record all tags, but it will not handle any of them specially. You can use the tags to annotate your methods diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 3cb8c45b41..07208b7f40 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -526,18 +526,9 @@ void QMetaCallEvent::placeMetaCall(QObject *object) constructor and in the destructor it resets the state to what it was before the constructor ran. - \code - { - const QSignalBlocker blocker(someQObject); - // no signals here - } - \endcode + \snippet code/src_corelib_kernel_qobject.cpp 53 is thus equivalent to - \code - const bool wasBlocked = someQObject->blockSignals(true); - // no signals here - someQObject->blockSignals(wasBlocked); - \endcode + \snippet code/src_corelib_kernel_qobject.cpp 54 except the code using QSignalBlocker is safe in the face of exceptions. diff --git a/src/corelib/kernel/qtestsupport_core.cpp b/src/corelib/kernel/qtestsupport_core.cpp index 240e5795db..d69551a227 100644 --- a/src/corelib/kernel/qtestsupport_core.cpp +++ b/src/corelib/kernel/qtestsupport_core.cpp @@ -68,13 +68,7 @@ Q_CORE_EXPORT void QTestPrivate::qSleep(int ms) Example: - \code - MyObject obj; - obj.startup(); - QTest::qWaitFor([&]() { - return obj.isReady(); - }, 3000); - \endcode + \snippet code/src_corelib_kernel_qtestsupport_core.cpp 0 The code above will wait for the object to become ready, for a maximum of three seconds. @@ -91,11 +85,7 @@ Q_CORE_EXPORT void QTestPrivate::qSleep(int ms) Example: - \code - int i = 0; - while (myNetworkServerNotResponding() && i++ < 50) - QTest::qWait(250); - \endcode + \snippet code/src_corelib_kernel_qtestsupport_core.cpp 1 The code above will wait until the network server is responding for a maximum of about 12.5 seconds. -- cgit v1.2.3 From 25b8af074763c0f9a8fa8fba6ff6ac7235afad87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Fri, 7 Sep 2018 10:50:07 +0200 Subject: Clarify behavior of QAbstractEventDispatcher::processEvents MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The function, although implemented differently in each event dispatcher, is not supposed to process newly posted events, only the events that were queued at the time of the call. This is tested by tst_QEventDispatcher::processEventsOnlySendsQueuedEvents, which is not blacklisted on any platforms, so we know it's the behavior in practice. Change-Id: If9a874eeeb8ebcebe88ed119b065ae12fc545129 Reviewed-by: Paul Wicking Reviewed-by: Edward Welbourne Reviewed-by: Tor Arne Vestbø --- src/corelib/kernel/qabstracteventdispatcher.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qabstracteventdispatcher.cpp b/src/corelib/kernel/qabstracteventdispatcher.cpp index 655fe58f98..8e1b560874 100644 --- a/src/corelib/kernel/qabstracteventdispatcher.cpp +++ b/src/corelib/kernel/qabstracteventdispatcher.cpp @@ -207,6 +207,15 @@ QAbstractEventDispatcher *QAbstractEventDispatcher::instance(QThread *thread) \sa hasPendingEvents() */ +/*! + \internal + + \note processEvents() only processes events queued before the function + is called. Events that are posted while the function runs will be queued + until a later round of event processing. This only applies to posted Qt + events. For timers and system level events, the situation is unknown. +*/ + /*! \fn bool QAbstractEventDispatcher::hasPendingEvents() \deprecated -- cgit v1.2.3 From 7bf4ebfb26e571a582fd4a19edec9aef1aef46cb Mon Sep 17 00:00:00 2001 From: Anton Kudryavtsev Date: Tue, 16 Oct 2018 20:19:35 +0300 Subject: Create empty list only if it's needed in QMetaMethod::parameterNames Change-Id: I2d370dff0c4939f27709db0ebf2b15a15eb14877 Reviewed-by: Thiago Macieira --- src/corelib/kernel/qmetaobject.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp index ac911e287b..b647f69978 100644 --- a/src/corelib/kernel/qmetaobject.cpp +++ b/src/corelib/kernel/qmetaobject.cpp @@ -1968,9 +1968,8 @@ QList QMetaMethod::parameterTypes() const */ QList QMetaMethod::parameterNames() const { - QList list; if (!mobj) - return list; + return QList(); return QMetaMethodPrivate::get(this)->parameterNames(); } -- cgit v1.2.3 From aa633ff276e593af227d7c4a84db230382185490 Mon Sep 17 00:00:00 2001 From: Anton Kudryavtsev Date: Mon, 15 Oct 2018 20:08:47 +0300 Subject: QMetaEnum: fix UB Check ptr before usage. Change-Id: Iac757a2e260b237d837318932cc0b5896c6e04c2 Reviewed-by: Olivier Goffart (Woboq GmbH) Reviewed-by: Edward Welbourne Reviewed-by: Thiago Macieira --- src/corelib/kernel/qmetaobject.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp index b647f69978..c642cd07f2 100644 --- a/src/corelib/kernel/qmetaobject.cpp +++ b/src/corelib/kernel/qmetaobject.cpp @@ -2652,8 +2652,10 @@ int QMetaEnum::value(int index) const */ bool QMetaEnum::isFlag() const { + if (!mobj) + return false; const int offset = priv(mobj->d.data)->revision >= 8 ? 2 : 1; - return mobj && mobj->d.data[handle + offset] & EnumIsFlag; + return mobj->d.data[handle + offset] & EnumIsFlag; } /*! @@ -2664,8 +2666,10 @@ bool QMetaEnum::isFlag() const */ bool QMetaEnum::isScoped() const { + if (!mobj) + return false; const int offset = priv(mobj->d.data)->revision >= 8 ? 2 : 1; - return mobj && mobj->d.data[handle + offset] & EnumIsScoped; + return mobj->d.data[handle + offset] & EnumIsScoped; } /*! -- cgit v1.2.3 From 948f8ce2ecb2d6d2713279311d6090268321f0fb Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 28 Aug 2018 17:51:51 -0700 Subject: QWinEventNotifier: fix crash on application shutdown The event dispatcher can be null already but we may have outstanding QWinEventNotifier objects (like in a QProcess). Patch-By: Tamas Karpati Task-number: QTBUG-70214 Change-Id: I5e432e273def425ea334fffd154f34abfd6cb11a Reviewed-by: Friedemann Kleint --- src/corelib/kernel/qwineventnotifier.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qwineventnotifier.cpp b/src/corelib/kernel/qwineventnotifier.cpp index 24de491326..fe086acb5d 100644 --- a/src/corelib/kernel/qwineventnotifier.cpp +++ b/src/corelib/kernel/qwineventnotifier.cpp @@ -256,6 +256,14 @@ static void CALLBACK wfsoCallback(void *context, BOOLEAN /*ignore*/) { QWinEventNotifierPrivate *nd = reinterpret_cast(context); QAbstractEventDispatcher *eventDispatcher = nd->threadData->eventDispatcher.load(); + + // Happens when Q(Core)Application is destroyed before QWinEventNotifier. + // https://bugreports.qt.io/browse/QTBUG-70214 + if (!eventDispatcher) { // perhaps application is shutting down + qWarning("QWinEventNotifier: no event dispatcher, application shutting down? Cannot deliver event."); + return; + } + QEventDispatcherWin32Private *edp = QEventDispatcherWin32Private::get( static_cast(eventDispatcher)); ++nd->signaledCount; -- cgit v1.2.3 From 56410a51cc897e3b38a0794019ebf196b1eb22d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Fri, 7 Sep 2018 11:28:17 +0200 Subject: Clarify behavior of QCoreApplication::processEvents MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The overload that takes a maxtime (now duration) was buggy, but we can't change its behavior, so instead we clarify what it actually does. Change-Id: I8a04fbaea5847c95b6ec6e73396304ab4debd35b Reviewed-by: Paul Wicking Reviewed-by: Edward Welbourne Reviewed-by: Tor Arne Vestbø --- src/corelib/kernel/qcoreapplication.cpp | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index 463e30e1c3..965d65fb5d 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -1266,7 +1266,11 @@ bool QCoreApplication::closingDown() \l{QCoreApplication::sendPostedEvents()}{sendPostedEvents()} from within that local loop. - Calling this function processes events only for the calling thread. + Calling this function processes events only for the calling thread, + and returns after all available events have been processed. Available + events are events queued before the function call. This means that + events that are posted while the function runs will be queued until + a later round of event processing. \threadsafe @@ -1283,7 +1287,7 @@ void QCoreApplication::processEvents(QEventLoop::ProcessEventsFlags flags) /*! \overload processEvents() - Processes pending events for the calling thread for \a maxtime + Processes pending events for the calling thread for \a ms milliseconds or until there are no more events to process, whichever is shorter. @@ -1292,11 +1296,14 @@ void QCoreApplication::processEvents(QEventLoop::ProcessEventsFlags flags) Calling this function processes events only for the calling thread. + \note Unlike the \l{QCoreApplication::processEvents(QEventLoop::ProcessEventsFlags flags)}{processEvents()} + overload, this function also processes events that are posted while the function runs. + \threadsafe \sa exec(), QTimer, QEventLoop::processEvents() */ -void QCoreApplication::processEvents(QEventLoop::ProcessEventsFlags flags, int maxtime) +void QCoreApplication::processEvents(QEventLoop::ProcessEventsFlags flags, int ms) { // ### Qt 6: consider splitting this method into a public and a private // one, so that a user-invoked processEvents can be detected @@ -1307,7 +1314,7 @@ void QCoreApplication::processEvents(QEventLoop::ProcessEventsFlags flags, int m QElapsedTimer start; start.start(); while (data->eventDispatcher.load()->processEvents(flags & ~QEventLoop::WaitForMoreEvents)) { - if (start.elapsed() > maxtime) + if (start.elapsed() > ms) break; } } -- cgit v1.2.3 From 7f54ea714ed62f3b4fb88dedbee9357bf6a26d26 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 23 Oct 2018 11:15:00 +0200 Subject: QtCore/Windows: Add pointer messages to the debug operator for MSG Task-number: QTBUG-71257 Change-Id: I53a4cee7b84b4075342cc016bb3382f473c27788 Reviewed-by: Andre de la Rocha --- src/corelib/kernel/qcoreapplication_win.cpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qcoreapplication_win.cpp b/src/corelib/kernel/qcoreapplication_win.cpp index 0109e2c658..0c57ad34b9 100644 --- a/src/corelib/kernel/qcoreapplication_win.cpp +++ b/src/corelib/kernel/qcoreapplication_win.cpp @@ -417,6 +417,23 @@ static const char *findWMstr(uint msg) { 0x0232, "WM_EXITSIZEMOVE" }, { 0x0233, "WM_DROPFILES" }, { 0x0234, "WM_MDIREFRESHMENU" }, + { 0x0241, "WM_NCPOINTERUPDATE"}, + { 0x0242, "WM_NCPOINTERDOWN"}, + { 0x0243, "WM_NCPOINTERUP"}, + { 0x0245, "WM_POINTERUPDATE"}, + { 0x0246, "WM_POINTERDOWN"}, + { 0x0247, "WM_POINTERUP"}, + { 0x0249, "WM_POINTERENTER"}, + { 0x024A, "WM_POINTERLEAVE"}, + { 0x0248, "WM_POINTERACTIVATE"}, + { 0x024C, "WM_POINTERCAPTURECHANGED"}, + { 0x024D, "WM_TOUCHHITTESTING"}, + { 0x024E, "WM_POINTERWHEEL"}, + { 0x024F, "WM_POINTERHWHEEL"}, + { 0x0250, "DM_POINTERHITTEST"}, + { 0x0251, "WM_POINTERROUTEDTO"}, + { 0x0252, "WM_POINTERROUTEDAWAY"}, + { 0x0253, "WM_POINTERROUTEDRELEASED"}, { 0x0281, "WM_IME_SETCONTEXT" }, { 0x0282, "WM_IME_NOTIFY" }, { 0x0283, "WM_IME_CONTROL" }, -- cgit v1.2.3 From a952fd7d5b03ce1968ec58871fbb8b3600895900 Mon Sep 17 00:00:00 2001 From: Kari Oikarinen Date: Wed, 26 Sep 2018 10:29:14 +0300 Subject: QObject: Fix isSignalConnected() when signals have been disconnected MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The bitmap cache for the first 64 signals being connected was only set when the connection is added. It was never unset when the connection was removed. Internal use of the connectedSignals bitmap is not hurt by it occasionally saying a signal is connected even though it is not, since the purpose of those checks is avoiding expensive operations that are not necessary if nothing is connected to the signal. However, the public API using this cache meant that it also never spotted signals being disconnected. This was not documented. Fix the behavior by only using the cache if it is up to date. If it is not, use a slower path that gives the correct answer. To avoid making disconnections and QObject destructions slower, the cache is only updated to unset disconnected signals when new signal connections are added. No extra work is done in the common case where signals are only removed in the end of the QObject's lifetime. Fixes: QTBUG-32340 Change-Id: Ieb6e498060157153cec60d9c8f1c33056993fda1 Reviewed-by: Ville Voutilainen Reviewed-by: Thiago Macieira Reviewed-by: Olivier Goffart (Woboq GmbH) Reviewed-by: Jędrzej Nowacki --- src/corelib/kernel/qobject.cpp | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 07208b7f40..deab51cfd0 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -421,6 +421,7 @@ void QObjectPrivate::cleanConnectionLists() { if (connectionLists->dirty && !connectionLists->inUse) { // remove broken connections + bool allConnected = false; for (int signal = -1; signal < connectionLists->count(); ++signal) { QObjectPrivate::ConnectionList &connectionList = (*connectionLists)[signal]; @@ -432,11 +433,13 @@ void QObjectPrivate::cleanConnectionLists() QObjectPrivate::Connection **prev = &connectionList.first; QObjectPrivate::Connection *c = *prev; + bool connected = false; // whether the signal is still connected somewhere while (c) { if (c->receiver) { last = c; prev = &c->nextConnectionList; c = *prev; + connected = true; } else { QObjectPrivate::Connection *next = c->nextConnectionList; *prev = next; @@ -448,6 +451,14 @@ void QObjectPrivate::cleanConnectionLists() // Correct the connection list's last pointer. // As conectionList.last could equal last, this could be a noop connectionList.last = last; + + if (!allConnected && !connected && signal >= 0 + && size_t(signal) < sizeof(connectedSignals) * 8) { + // This signal is no longer connected + connectedSignals[signal >> 5] &= ~(1 << (signal & 0x1f)); + } else if (signal == -1) { + allConnected = connected; + } } connectionLists->dirty = false; } @@ -2501,19 +2512,20 @@ bool QObject::isSignalConnected(const QMetaMethod &signal) const signalIndex += QMetaObjectPrivate::signalOffset(signal.mobj); - if (signalIndex < sizeof(d->connectedSignals) * 8) + QMutexLocker locker(signalSlotLock(this)); + if (!d->connectionLists) + return false; + + if (signalIndex < sizeof(d->connectedSignals) * 8 && !d->connectionLists->dirty) return d->isSignalConnected(signalIndex); - QMutexLocker locker(signalSlotLock(this)); - if (d->connectionLists) { - if (signalIndex < uint(d->connectionLists->count())) { - const QObjectPrivate::Connection *c = - d->connectionLists->at(signalIndex).first; - while (c) { - if (c->receiver) - return true; - c = c->nextConnectionList; - } + if (signalIndex < uint(d->connectionLists->count())) { + const QObjectPrivate::Connection *c = + d->connectionLists->at(signalIndex).first; + while (c) { + if (c->receiver) + return true; + c = c->nextConnectionList; } } return false; -- cgit v1.2.3 From 00674a1643422de2e56ac23c89174c0ead83eb18 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Tue, 25 Sep 2018 15:02:58 +0200 Subject: Treat shorts as int in QVariant::canConvert() Follow the pattern of char and float, and treat shorts as a more generic type in QVariant::canConvert() Task-number: QTBUG-60914 Change-Id: Ib1cc7941ee47cb0fc0098f22f98a03cd6f6b63fe Reviewed-by: Thiago Macieira --- src/corelib/kernel/qvariant.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp index 0b4c3f387f..6541b97595 100644 --- a/src/corelib/kernel/qvariant.cpp +++ b/src/corelib/kernel/qvariant.cpp @@ -3523,13 +3523,19 @@ bool QVariant::canConvert(int targetTypeId) const } // TODO Reimplement this function, currently it works but it is a historical mess. - uint currentType = ((d.type == QMetaType::Float) ? QVariant::Double : d.type); + uint currentType = d.type; if (currentType == QMetaType::SChar || currentType == QMetaType::Char) currentType = QMetaType::UInt; if (targetTypeId == QMetaType::SChar || currentType == QMetaType::Char) targetTypeId = QMetaType::UInt; - if (uint(targetTypeId) == uint(QMetaType::Float)) targetTypeId = QVariant::Double; - + if (currentType == QMetaType::Short || currentType == QMetaType::UShort) + currentType = QMetaType::Int; + if (targetTypeId == QMetaType::Short || currentType == QMetaType::UShort) + targetTypeId = QMetaType::Int; + if (currentType == QMetaType::Float) + currentType = QMetaType::Double; + if (targetTypeId == QMetaType::Float) + targetTypeId = QMetaType::Double; if (currentType == uint(targetTypeId)) return true; -- cgit v1.2.3 From c6af950bfd79182eb21438fa63096d4509f90404 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 23 Oct 2018 16:11:10 +0200 Subject: QtCore/Windows: Output unknown messages in hex in the debug operator for MSG Task-number: QTBUG-71257 Change-Id: I89335799529e8c518113925d402571a8f7ada244 Reviewed-by: Andre de la Rocha --- src/corelib/kernel/qcoreapplication_win.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qcoreapplication_win.cpp b/src/corelib/kernel/qcoreapplication_win.cpp index 0c57ad34b9..b373267fcb 100644 --- a/src/corelib/kernel/qcoreapplication_win.cpp +++ b/src/corelib/kernel/qcoreapplication_win.cpp @@ -717,7 +717,7 @@ QString decodeMSG(const MSG& msg) else if (const char *wmmsgC = findWMstr(msg.message)) message = QString::fromLatin1(wmmsgC); else - message = QString::fromLatin1("WM_(%1)").arg(msg.message); // Unknown WM_, so use number + message = QString::fromLatin1("WM_(0x%1)").arg(msg.message, 0, 16); // Unknown WM_, so use number // Yes, we want to give the WM_ names 20 chars of space before showing the // decoded message, since some of the common messages are quite long, and -- cgit v1.2.3 From ceeecbae510af6e2d1ebbf865761e4761d404033 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Mon, 22 Oct 2018 15:53:35 +0200 Subject: Update various qt_attribution.json files Marking various as final because no upstream is known or available. Listing versions of others, where I was able to discover them. Updated a stale link (that helpfully redirected). Task-number: QTBUG-70008 Change-Id: Id00f34827133c560735c68793b4f1353f2b2ca85 Reviewed-by: Tobias Koenig Reviewed-by: Lars Knoll Reviewed-by: Jani Heikkinen Reviewed-by: Volker Hilsheimer --- src/corelib/kernel/qt_attribution.json | 1 + 1 file changed, 1 insertion(+) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qt_attribution.json b/src/corelib/kernel/qt_attribution.json index 37764a5330..6d8f4f2abc 100644 --- a/src/corelib/kernel/qt_attribution.json +++ b/src/corelib/kernel/qt_attribution.json @@ -5,6 +5,7 @@ "QtUsage": "Used in Qt Core on macOS.", "Path": "qeventdispatcher_cf_p.h", + "Description": "Treat as final version; no upstream known", "Description": "Implementation of QAbstractEventDispatcher for macOS.", "License": "BSD 3-clause \"New\" or \"Revised\" License", "LicenseId": "BSD-3-Clause", -- cgit v1.2.3 From 81d8319276f26d399bdff47b49bd69b19bd86c5a Mon Sep 17 00:00:00 2001 From: Martin Smith Date: Wed, 10 Oct 2018 15:54:07 +0200 Subject: doc: Fix all clang parse errors in QtBase during PCH build MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This update eliminates ALL parsing errors when clang parses the Qt headers to build the precompiled header qdoc needs. These errors are often cases where an old use of Q_QDOC no longer works because clang sees the enclosed fake declarations as erroneous. In a few cases, clang reported errors because two dummy function declartations under the Q_CLANG_QDOC guard were indistinguishable, so one of them was removed, and the documentation was patched accordingly. Using the macro Q_DECLARE_INTERFACE(...) causes clang to report errors because the class parametewr is abstract. These uses of the macro are not needed, so they are removed with #ifndef Q_CLANG_QDOC. Some declarations of default GL types that had been provided for qdoc were no longer needed, so they are removed. Now there are some member function signatures in QDBusPendingReply and QDBusPendingCall that have very long template clauses and qualifiers in their signatures. These unwieldy signatures will be unnecessary in the documentation and will look bad there, but for now they are correct. The ultimate solution will be to add a metacommand to qdoc, something like \simplify-signature to tell qdoc to generate the documentation for these member functions without the long template caluses and qualifiers. Change-Id: I012cf17a544fbba2ebc71002f31bdc865119bb8e Reviewed-by: Paul Wicking Reviewed-by: Topi Reiniö Reviewed-by: Martin Smith --- src/corelib/kernel/qmetatype.h | 4 +++- src/corelib/kernel/qvariant.h | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h index 0bf430bb26..a47fbfe28d 100644 --- a/src/corelib/kernel/qmetatype.h +++ b/src/corelib/kernel/qmetatype.h @@ -1977,7 +1977,9 @@ QT_FOR_EACH_STATIC_WIDGETS_CLASS(QT_FORWARD_DECLARE_STATIC_TYPES_ITER) typedef QList QVariantList; typedef QMap QVariantMap; typedef QHash QVariantHash; -#ifndef Q_CLANG_QDOC +#ifdef Q_CLANG_QDOC +class QByteArrayList; +#else typedef QList QByteArrayList; #endif diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h index ff73c27b6e..f95502e75f 100644 --- a/src/corelib/kernel/qvariant.h +++ b/src/corelib/kernel/qvariant.h @@ -55,6 +55,8 @@ #if QT_HAS_INCLUDE() && __cplusplus >= 201703L #include +#elif defined(Q_CLANG_QDOC) +namespace std { template struct variant; } #endif QT_BEGIN_NAMESPACE @@ -365,7 +367,7 @@ class Q_CORE_EXPORT QVariant static inline QVariant fromValue(const T &value) { return qVariantFromValue(value); } -#if defined(Q_CLANG_QDOC) || (QT_HAS_INCLUDE() && __cplusplus >= 201703L) +#if QT_HAS_INCLUDE() && __cplusplus >= 201703L template static inline QVariant fromStdVariant(const std::variant &value) { -- cgit v1.2.3 From ec1548ae122af2febfc61c0242025ee52c8cbc30 Mon Sep 17 00:00:00 2001 From: Topi Reinio Date: Wed, 31 Oct 2018 13:49:14 +0100 Subject: Doc: Fix various documentation warnings These include typos, marking functions as \internal, documenting trivial things, and fixing the function signatures passed to the \fn command. Task-number: QTBUG-71502 Change-Id: I24a9e1f7e1cdb39e5c31b99202bdd593c6b789ff Reviewed-by: Martin Smith Reviewed-by: Paul Wicking Reviewed-by: Edward Welbourne --- src/corelib/kernel/qdeadlinetimer.cpp | 5 +++++ src/corelib/kernel/qeventdispatcher_cf.mm | 2 +- src/corelib/kernel/qtimer.cpp | 18 +++++++++--------- 3 files changed, 15 insertions(+), 10 deletions(-) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qdeadlinetimer.cpp b/src/corelib/kernel/qdeadlinetimer.cpp index 466056d513..6aa886cfe1 100644 --- a/src/corelib/kernel/qdeadlinetimer.cpp +++ b/src/corelib/kernel/qdeadlinetimer.cpp @@ -720,6 +720,11 @@ QDeadlineTimer QDeadlineTimer::addNSecs(QDeadlineTimer dt, qint64 nsecs) Q_DECL_ Returns the time remaining before the deadline. */ +/*! + \fn QPair QDeadlineTimer::_q_data() const + \internal +*/ + // the rest of the functions are in qelapsedtimer_xxx.cpp QT_END_NAMESPACE diff --git a/src/corelib/kernel/qeventdispatcher_cf.mm b/src/corelib/kernel/qeventdispatcher_cf.mm index 8881305b18..b7b379e2c1 100644 --- a/src/corelib/kernel/qeventdispatcher_cf.mm +++ b/src/corelib/kernel/qeventdispatcher_cf.mm @@ -58,7 +58,7 @@ QT_USE_NAMESPACE -/*! +/* During scroll view panning, and possibly other gestures, UIKit will request a switch to UITrackingRunLoopMode via GSEventPushRunLoopMode, which records the new runloop mode and stops the current runloop. diff --git a/src/corelib/kernel/qtimer.cpp b/src/corelib/kernel/qtimer.cpp index 90f29aa630..13f027074a 100644 --- a/src/corelib/kernel/qtimer.cpp +++ b/src/corelib/kernel/qtimer.cpp @@ -571,43 +571,43 @@ void QTimer::singleShot(int msec, Qt::TimerType timerType, const QObject *receiv */ /*! - \fn template QMetaObject::Connection callOnTimeout(Functor functor, Qt::ConnectionType connectionType = Qt::AutoConnection) + \fn template QMetaObject::Connection QTimer::callOnTimeout(Functor slot, Qt::ConnectionType connectionType = Qt::AutoConnection) \since 5.12 \overload - Creates a connection from the timeout() signal to \a functor, and returns a + Creates a connection from the timeout() signal to \a slot, and returns a handle to the connection. This method is provided for convenience. - It's equivalent to calling \c {QObject::connect(timer, &QTimer::timeout, timer, functor, connectionType)}. + It's equivalent to calling \c {QObject::connect(timer, &QTimer::timeout, timer, slot, connectionType)}. \sa QObject::connect(), timeout() */ /*! - \fn template QMetaObject::Connection callOnTimeout(QObject *context, Functor functor, Qt::ConnectionType connectionType = Qt::AutoConnection) + \fn template QMetaObject::Connection QTimer::callOnTimeout(const QObject *context, Functor slot, Qt::ConnectionType connectionType = Qt::AutoConnection) \since 5.12 \overload callOnTimeout() - Creates a connection from the timeout() signal to \a functor to be placed in a specific + Creates a connection from the timeout() signal to \a slot to be placed in a specific event loop of \a context, and returns a handle to the connection. This method is provided for convenience. It's equivalent to calling - \c {QObject::connect(timer, &QTimer::timeout, context, functor, connectionType)}. + \c {QObject::connect(timer, &QTimer::timeout, context, slot, connectionType)}. \sa QObject::connect(), timeout() */ /*! - \fn template QMetaObject::Connection callOnTimeout(QObject *receiver, PointerToMemberFunction method, Qt::ConnectionType connectionType = Qt::AutoConnection) + \fn template QMetaObject::Connection QTimer::callOnTimeout(const QObject *receiver, PointerToMemberFunction slot, Qt::ConnectionType connectionType = Qt::AutoConnection) \since 5.12 \overload callOnTimeout() - Creates a connection from the timeout() signal to the \a method in the \a receiver object. Returns + Creates a connection from the timeout() signal to the \a slot in the \a receiver object. Returns a handle to the connection. This method is provided for convenience. It's equivalent to calling - \c {QObject::connect(timer, &QTimer::timeout, receiver, method, connectionType)}. + \c {QObject::connect(timer, &QTimer::timeout, receiver, slot, connectionType)}. \sa QObject::connect(), timeout() */ -- cgit v1.2.3 From 825f98815683faea06144ab0262129b0367798ee Mon Sep 17 00:00:00 2001 From: Liang Qi Date: Tue, 2 Oct 2018 12:59:24 +0200 Subject: Modernize the "textcodec" feature Also clean up QTextCodec usage in qmake build and some includes of qtextcodec.h. Change-Id: I0475b82690024054add4e85a8724c8ea3adcf62a Reviewed-by: Edward Welbourne Reviewed-by: Oswald Buddenhagen --- src/corelib/kernel/qcoreapplication.cpp | 1 - src/corelib/kernel/qcoreglobaldata.cpp | 2 ++ src/corelib/kernel/qcoreglobaldata_p.h | 2 ++ src/corelib/kernel/qmimedata.cpp | 6 ++++-- 4 files changed, 8 insertions(+), 3 deletions(-) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index 4e32f90964..0ea969ece5 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -55,7 +55,6 @@ #include #include #include -#include #ifndef QT_NO_QOBJECT #include #include diff --git a/src/corelib/kernel/qcoreglobaldata.cpp b/src/corelib/kernel/qcoreglobaldata.cpp index e2087b9e64..c3ca2f74e4 100644 --- a/src/corelib/kernel/qcoreglobaldata.cpp +++ b/src/corelib/kernel/qcoreglobaldata.cpp @@ -38,7 +38,9 @@ ****************************************************************************/ #include "qcoreglobaldata_p.h" +#if QT_CONFIG(textcodec) #include "qtextcodec.h" +#endif QT_BEGIN_NAMESPACE diff --git a/src/corelib/kernel/qcoreglobaldata_p.h b/src/corelib/kernel/qcoreglobaldata_p.h index c3c2f7b4a4..fda6b52b6e 100644 --- a/src/corelib/kernel/qcoreglobaldata_p.h +++ b/src/corelib/kernel/qcoreglobaldata_p.h @@ -57,7 +57,9 @@ #include "QtCore/qreadwritelock.h" #include "QtCore/qhash.h" #include "QtCore/qbytearray.h" +#if QT_CONFIG(textcodec) #include "QtCore/qtextcodec.h" +#endif #include "QtCore/qmutex.h" QT_BEGIN_NAMESPACE diff --git a/src/corelib/kernel/qmimedata.cpp b/src/corelib/kernel/qmimedata.cpp index 73307e925a..c8ad1bc43f 100644 --- a/src/corelib/kernel/qmimedata.cpp +++ b/src/corelib/kernel/qmimedata.cpp @@ -42,7 +42,9 @@ #include "private/qobject_p.h" #include "qurl.h" #include "qstringlist.h" +#if QT_CONFIG(textcodec) #include "qtextcodec.h" +#endif QT_BEGIN_NAMESPACE @@ -150,7 +152,7 @@ QVariant QMimeDataPrivate::retrieveTypedData(const QString &format, QVariant::Ty if (data.type() == QVariant::ByteArray) { // see if we can convert to the requested type switch(type) { -#ifndef QT_NO_TEXTCODEC +#if QT_CONFIG(textcodec) case QVariant::String: { const QByteArray ba = data.toByteArray(); QTextCodec *codec = QTextCodec::codecForName("utf-8"); @@ -158,7 +160,7 @@ QVariant QMimeDataPrivate::retrieveTypedData(const QString &format, QVariant::Ty codec = QTextCodec::codecForHtml(ba, codec); return codec->toUnicode(ba); } -#endif // QT_NO_TEXTCODEC +#endif // textcodec case QVariant::Color: { QVariant newData = data; newData.convert(QVariant::Color); -- cgit v1.2.3 From b971310e2df095678dd0d6d8e08a8f657d346036 Mon Sep 17 00:00:00 2001 From: Kari Oikarinen Date: Tue, 6 Nov 2018 15:14:44 +0200 Subject: QObject: Check for declarative signals in isSignalConnected Amends a952fd7d5b03ce1968ec58871fbb8b3600895900. The mentioned commit started to skip QObjectPrivate::isSignalConnected() call if the connectionLists are dirty, which lead to tst_qqmllanguage::receivers() test inside qtdeclarative breaking. Declarative signals were not checked if that function was not called. It previously also wasn't called for signals higher than 64. Fix that by checking for declarative signals after the connectionLists search is unsuccessful. Fixes: QTBUG-71550 Change-Id: Ifcb5fdd0dc9a6b14b9f448a016fd09356a55b985 Reviewed-by: Liang Qi Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/kernel/qobject.cpp | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index deab51cfd0..14af9ac8ef 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -2513,22 +2513,21 @@ bool QObject::isSignalConnected(const QMetaMethod &signal) const signalIndex += QMetaObjectPrivate::signalOffset(signal.mobj); QMutexLocker locker(signalSlotLock(this)); - if (!d->connectionLists) - return false; - - if (signalIndex < sizeof(d->connectedSignals) * 8 && !d->connectionLists->dirty) - return d->isSignalConnected(signalIndex); + if (d->connectionLists) { + if (signalIndex < sizeof(d->connectedSignals) * 8 && !d->connectionLists->dirty) + return d->isSignalConnected(signalIndex); - if (signalIndex < uint(d->connectionLists->count())) { - const QObjectPrivate::Connection *c = - d->connectionLists->at(signalIndex).first; - while (c) { - if (c->receiver) - return true; - c = c->nextConnectionList; + if (signalIndex < uint(d->connectionLists->count())) { + const QObjectPrivate::Connection *c = + d->connectionLists->at(signalIndex).first; + while (c) { + if (c->receiver) + return true; + c = c->nextConnectionList; + } } } - return false; + return d->isDeclarativeSignalConnected(signalIndex); } /*! -- cgit v1.2.3 From 527406cbd99f44470ef87468b73c18df949e8ac7 Mon Sep 17 00:00:00 2001 From: Liang Qi Date: Mon, 12 Nov 2018 09:40:47 +0100 Subject: Modernize the "settings" feature Change-Id: I9b8a61ecb1413b513ae5c9e77d3ee1b3e8b6562c Reviewed-by: Edward Welbourne Reviewed-by: Oswald Buddenhagen --- src/corelib/kernel/qcoreapplication_p.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qcoreapplication_p.h b/src/corelib/kernel/qcoreapplication_p.h index cd995c17f1..b3479414ab 100644 --- a/src/corelib/kernel/qcoreapplication_p.h +++ b/src/corelib/kernel/qcoreapplication_p.h @@ -53,7 +53,9 @@ #include "QtCore/qcoreapplication.h" #include "QtCore/qtranslator.h" +#if QT_CONFIG(settings) #include "QtCore/qsettings.h" +#endif #ifndef QT_NO_QOBJECT #include "private/qobject_p.h" #endif -- cgit v1.2.3 From 49d63057e31427aff84d4fe33d60bacfe2445076 Mon Sep 17 00:00:00 2001 From: Kevin Funk Date: Wed, 28 Nov 2018 10:09:00 +0100 Subject: qobject_p.h: Use nullptr everywhere Change-Id: I605e44607cc09775548c1e6b781d476c1627c9c7 Reviewed-by: Simon Hausmann --- src/corelib/kernel/qobject_p.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h index 6aea40cf4a..5dfef786ec 100644 --- a/src/corelib/kernel/qobject_p.h +++ b/src/corelib/kernel/qobject_p.h @@ -341,7 +341,7 @@ inline QMetaObject::Connection QObjectPrivate::connect(const typename QtPrivate: Q_STATIC_ASSERT_X((QtPrivate::AreArgumentsCompatible::value), "Return type of the slot is not compatible with the return type of the signal."); - const int *types = 0; + const int *types = nullptr; if (type == Qt::QueuedConnection || type == Qt::BlockingQueuedConnection) types = QtPrivate::ConnectionTypes::types(); -- cgit v1.2.3 From d3ec5a2b09f3c9f5a67e757aa6b7b0dd09bbe97a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Sun, 25 Nov 2018 00:41:00 +0100 Subject: CoreText: Use QCFType to track CoreFoundation member variables The operator T() function of QAppleRefCounted should be const so that the underlying type can be accessed from const member functions just like the naked underlying type could. Change-Id: I0819c5795d28442a6ff4db2732e211b183574f9f Reviewed-by: Simon Hausmann --- src/corelib/kernel/qcore_mac_p.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qcore_mac_p.h b/src/corelib/kernel/qcore_mac_p.h index b14a494296..acb87f8a3c 100644 --- a/src/corelib/kernel/qcore_mac_p.h +++ b/src/corelib/kernel/qcore_mac_p.h @@ -89,7 +89,7 @@ public: QAppleRefCounted(QAppleRefCounted &&other) : value(other.value) { other.value = T(); } QAppleRefCounted(const QAppleRefCounted &other) : value(other.value) { if (value) RetainFunction(value); } ~QAppleRefCounted() { if (value) ReleaseFunction(value); } - operator T() { return value; } + operator T() const { return value; } void swap(QAppleRefCounted &other) Q_DECL_NOEXCEPT_EXPR(noexcept(qSwap(value, other.value))) { qSwap(value, other.value); } QAppleRefCounted &operator=(const QAppleRefCounted &other) -- cgit v1.2.3 From 652098d40fab7c1085b913487809c6237eb2d49d Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Mon, 19 Nov 2018 11:00:51 -0800 Subject: QTranslator: add initial largefile support Using QT_MMAP macro instead of mmap() so we could map more than 2 GB of the file. Not that the file format supports such a thing, but just in case. Change-Id: Iae320a2868db402a993dfffd15689bba1d667c7d Reviewed-by: Lars Knoll Reviewed-by: Thiago Macieira --- src/corelib/kernel/qtranslator.cpp | 33 +++++++++++++-------------------- 1 file changed, 13 insertions(+), 20 deletions(-) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qtranslator.cpp b/src/corelib/kernel/qtranslator.cpp index 744bbfbff5..dc39490ab0 100644 --- a/src/corelib/kernel/qtranslator.cpp +++ b/src/corelib/kernel/qtranslator.cpp @@ -61,14 +61,8 @@ #if defined(Q_OS_UNIX) && !defined(Q_OS_INTEGRITY) #define QT_USE_MMAP #include "private/qcore_unix_p.h" -#endif - -// most of the headers below are already included in qplatformdefs.h -// also this lacks Large File support but that's probably irrelevant -#if defined(QT_USE_MMAP) // for mmap #include -#include #endif #include @@ -302,7 +296,7 @@ public: bool used_mmap : 1; #endif char *unmapPointer; // used memory (mmap, new or resource file) - quint32 unmapLength; + qsizetype unmapLength; // The resource object in case we loaded the translations from a resource QResource *resource; @@ -322,7 +316,7 @@ public: uint numerusRulesLength; bool do_load(const QString &filename, const QString &directory); - bool do_load(const uchar *data, int len, const QString &directory); + bool do_load(const uchar *data, qsizetype len, const QString &directory); QString do_translate(const char *context, const char *sourceText, const char *comment, int n) const; void clear(); @@ -553,7 +547,7 @@ bool QTranslatorPrivate::do_load(const QString &realname, const QString &directo return false; qint64 fileSize = file.size(); - if (fileSize < MagicLength || quint32(-1) <= fileSize) + if (fileSize < MagicLength || fileSize > std::numeric_limits::max()) return false; { @@ -563,7 +557,7 @@ bool QTranslatorPrivate::do_load(const QString &realname, const QString &directo return false; } - d->unmapLength = quint32(fileSize); + d->unmapLength = qsizetype(fileSize); #ifdef QT_USE_MMAP @@ -571,21 +565,20 @@ bool QTranslatorPrivate::do_load(const QString &realname, const QString &directo #define MAP_FILE 0 #endif #ifndef MAP_FAILED -#define MAP_FAILED -1 +#define MAP_FAILED reinterpret_cast(-1) #endif int fd = file.handle(); if (fd >= 0) { - char *ptr; - ptr = reinterpret_cast( - mmap(0, d->unmapLength, // any address, whole file - PROT_READ, // read-only memory - MAP_FILE | MAP_PRIVATE, // swap-backed map from file - fd, 0)); // from offset 0 of fd - if (ptr && ptr != reinterpret_cast(MAP_FAILED)) { + int protection = PROT_READ; // read-only memory + int flags = MAP_FILE | MAP_PRIVATE; // swap-backed map from file + void *ptr = QT_MMAP(nullptr, d->unmapLength,// any address, whole file + protection, flags, + fd, 0); // from offset 0 of fd + if (ptr != MAP_FAILED) { file.close(); d->used_mmap = true; - d->unmapPointer = ptr; + d->unmapPointer = static_cast(ptr); ok = true; } } @@ -815,7 +808,7 @@ static quint32 read32(const uchar *data) return qFromBigEndian(data); } -bool QTranslatorPrivate::do_load(const uchar *data, int len, const QString &directory) +bool QTranslatorPrivate::do_load(const uchar *data, qsizetype len, const QString &directory) { bool ok = true; const uchar *end = data + len; -- cgit v1.2.3 From 83bf7d82609b45a76c91c2a869cfbcbcbb9e0995 Mon Sep 17 00:00:00 2001 From: Martin Smith Date: Wed, 5 Dec 2018 13:37:00 +0100 Subject: doc: Let qdoc ignore Q_DECLARE_INTERFACE MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This macro declares three template functions that are different for each use of the macro. The functions are in the public API but they are not meant to be documented. This update just defines the macro to be empty so clang in qdoc will ignore it. Without this, clang reports a lot of errors incorrectly, but if we let clang process the macro, it declares all those extra functions which then must be documented with \internal in the cpp files, and we don't want to do that. This will probably be redone in a later version using a custom annotation attribute. Change-Id: I78ae4bcc98a3844b803d7ef7b1eba5d5539b043f Reviewed-by: Tor Arne Vestbø --- src/corelib/kernel/qobject.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qobject.h b/src/corelib/kernel/qobject.h index aac9bcdee9..9ae6155f52 100644 --- a/src/corelib/kernel/qobject.h +++ b/src/corelib/kernel/qobject.h @@ -517,7 +517,10 @@ inline T qobject_cast(const QObject *object) template inline const char * qobject_interface_iid() { return nullptr; } -#if !defined(Q_MOC_RUN) && !defined(Q_CLANG_QDOC) + +#if defined(Q_CLANG_QDOC) +# define Q_DECLARE_INTERFACE(IFace, IId) +#elif !defined(Q_MOC_RUN) # define Q_DECLARE_INTERFACE(IFace, IId) \ template <> inline const char *qobject_interface_iid() \ { return IId; } \ -- cgit v1.2.3 From e2093219665b02e9ac2a416412a371aeb60c7750 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 16 Oct 2018 15:29:58 +0200 Subject: Use Q_DISABLE_COPY_MOVE for private classes Change-Id: I3cfcfba892ff4a0ab4e31f308620b445162bb17b Reviewed-by: Giuseppe D'Angelo --- src/corelib/kernel/qjni_p.h | 2 +- src/corelib/kernel/qmetaobjectbuilder_p.h | 2 +- src/corelib/kernel/qobject_p.h | 2 +- src/corelib/kernel/qobjectdefs_impl.h | 2 +- src/corelib/kernel/qppsobject_p.h | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qjni_p.h b/src/corelib/kernel/qjni_p.h index 52abd51dc1..ec8525e6e1 100644 --- a/src/corelib/kernel/qjni_p.h +++ b/src/corelib/kernel/qjni_p.h @@ -76,7 +76,7 @@ public: private: friend class QAndroidJniEnvironment; - Q_DISABLE_COPY(QJNIEnvironmentPrivate) + Q_DISABLE_COPY_MOVE(QJNIEnvironmentPrivate) JNIEnv *jniEnv; }; diff --git a/src/corelib/kernel/qmetaobjectbuilder_p.h b/src/corelib/kernel/qmetaobjectbuilder_p.h index 115ec835aa..6100835bad 100644 --- a/src/corelib/kernel/qmetaobjectbuilder_p.h +++ b/src/corelib/kernel/qmetaobjectbuilder_p.h @@ -184,7 +184,7 @@ public: #endif private: - Q_DISABLE_COPY(QMetaObjectBuilder) + Q_DISABLE_COPY_MOVE(QMetaObjectBuilder) QMetaObjectBuilderPrivate *d; diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h index 9c6724d8ab..a762e6f529 100644 --- a/src/corelib/kernel/qobject_p.h +++ b/src/corelib/kernel/qobject_p.h @@ -407,7 +407,7 @@ private: class QBoolBlocker { - Q_DISABLE_COPY(QBoolBlocker) + Q_DISABLE_COPY_MOVE(QBoolBlocker) public: explicit inline QBoolBlocker(bool &b, bool value=true):block(b), reset(b){block = value;} inline ~QBoolBlocker(){block = reset; } diff --git a/src/corelib/kernel/qobjectdefs_impl.h b/src/corelib/kernel/qobjectdefs_impl.h index 8afff1fb98..aa6bd84e95 100644 --- a/src/corelib/kernel/qobjectdefs_impl.h +++ b/src/corelib/kernel/qobjectdefs_impl.h @@ -395,7 +395,7 @@ namespace QtPrivate { protected: ~QSlotObjectBase() {} private: - Q_DISABLE_COPY(QSlotObjectBase) + Q_DISABLE_COPY_MOVE(QSlotObjectBase) }; // implementation of QSlotObjectBase for which the slot is a pointer to member function of a QObject diff --git a/src/corelib/kernel/qppsobject_p.h b/src/corelib/kernel/qppsobject_p.h index c7b99c8e42..a4649918fc 100644 --- a/src/corelib/kernel/qppsobject_p.h +++ b/src/corelib/kernel/qppsobject_p.h @@ -119,7 +119,7 @@ Q_SIGNALS: private: Q_DECLARE_PRIVATE(QPpsObject) - Q_DISABLE_COPY(QPpsObject) + Q_DISABLE_COPY_MOVE(QPpsObject) }; QT_END_NAMESPACE -- cgit v1.2.3 From 43720ec2003339918c51cddeee38c2b10ed27ddf Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Mon, 10 Dec 2018 14:58:18 +0100 Subject: Deprecate QObject::findChildren(const QRegExp &, ...) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the overload using QRegularExpression instead. Change-Id: I1bf468b248c0a3f5b2304b1831379a127093df06 Reviewed-by: Jędrzej Nowacki --- src/corelib/kernel/qobject.cpp | 3 +++ src/corelib/kernel/qobject.h | 3 +++ 2 files changed, 6 insertions(+) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index d2a3d957e9..36c108b697 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -1820,12 +1820,15 @@ void QObject::killTimer(int id) /*! \fn template QList QObject::findChildren(const QRegExp ®Exp, Qt::FindChildOptions options) const \overload findChildren() + \obsolete Returns the children of this object that can be cast to type T and that have names matching the regular expression \a regExp, or an empty list if there are no such objects. The search is performed recursively, unless \a options specifies the option FindDirectChildrenOnly. + + Use the findChildren overload taking a QRegularExpression instead. */ /*! diff --git a/src/corelib/kernel/qobject.h b/src/corelib/kernel/qobject.h index 9ae6155f52..52c1b8e555 100644 --- a/src/corelib/kernel/qobject.h +++ b/src/corelib/kernel/qobject.h @@ -176,7 +176,9 @@ public: } #ifndef QT_NO_REGEXP +#if QT_DEPRECATED_SINCE(5, 13) template + QT_DEPRECATED_X("Use findChildren(const RegularExpression &, ...) instead.") inline QList findChildren(const QRegExp &re, Qt::FindChildOptions options = Qt::FindChildrenRecursively) const { typedef typename std::remove_cv::type>::type ObjType; @@ -186,6 +188,7 @@ public: return list; } #endif +#endif #if QT_CONFIG(regularexpression) template -- cgit v1.2.3 From c41c5159d7d7688d61bdd1b013278302bb0116fb Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Sun, 16 Dec 2018 11:02:58 -0800 Subject: Doc: mark QMetaObject::invokeMethod overloads as threadsafe Fixes: QTBUG-72599 Change-Id: I61ce366d57bc46c89db5fffd1570e578a7979749 Reviewed-by: Giuseppe D'Angelo Reviewed-by: Paul Wicking --- src/corelib/kernel/qmetaobject.cpp | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp index c642cd07f2..5de2717078 100644 --- a/src/corelib/kernel/qmetaobject.cpp +++ b/src/corelib/kernel/qmetaobject.cpp @@ -1381,6 +1381,8 @@ static inline QByteArray findMethodCandidates(const QMetaObject *metaObject, con } /*! + \threadsafe + Invokes the \a member (a signal or a slot name) on the object \a obj. Returns \c true if the member could be invoked. Returns \c false if there is no such member or the parameters did not match. @@ -1570,6 +1572,7 @@ bool QMetaObject::invokeMethodImpl(QObject *object, QtPrivate::QSlotObjectBase * QGenericArgument val7 = QGenericArgument(), QGenericArgument val8 = QGenericArgument(), QGenericArgument val9 = QGenericArgument()); + \threadsafe \overload invokeMethod() This overload always invokes the member using the connection type Qt::AutoConnection. @@ -1588,6 +1591,7 @@ bool QMetaObject::invokeMethodImpl(QObject *object, QtPrivate::QSlotObjectBase * QGenericArgument val8 = QGenericArgument(), QGenericArgument val9 = QGenericArgument()) + \threadsafe \overload invokeMethod() This overload can be used if the return value of the member is of no interest. @@ -1606,6 +1610,7 @@ bool QMetaObject::invokeMethodImpl(QObject *object, QtPrivate::QSlotObjectBase * QGenericArgument val8 = QGenericArgument(), QGenericArgument val9 = QGenericArgument()) + \threadsafe \overload invokeMethod() This overload invokes the member using the connection type Qt::AutoConnection and @@ -1617,6 +1622,7 @@ bool QMetaObject::invokeMethodImpl(QObject *object, QtPrivate::QSlotObjectBase * \since 5.10 + \threadsafe \overload Invokes the \a function in the event loop of \a context. \a function can be a functor @@ -1630,6 +1636,7 @@ bool QMetaObject::invokeMethodImpl(QObject *object, QtPrivate::QSlotObjectBase * \since 5.10 + \threadsafe \overload Invokes the \a function in the event loop of \a context using the connection type Qt::AutoConnection. -- cgit v1.2.3 From 28a28af182c7fb9b0cf6d0b9ccc948843c6992a1 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Thu, 20 Dec 2018 15:48:06 +0100 Subject: QtCore: Unify license headers Change-Id: Iff4f6da9f0bbf7a0627101f455dd8467681b2783 Reviewed-by: Thiago Macieira --- src/corelib/kernel/qcore_mac_objc.mm | 76 ++++++++++++++--------------- src/corelib/kernel/qppsattribute.cpp | 74 ++++++++++++++-------------- src/corelib/kernel/qppsattribute_p.h | 75 ++++++++++++++-------------- src/corelib/kernel/qppsattributeprivate_p.h | 74 ++++++++++++++-------------- src/corelib/kernel/qppsobject.cpp | 74 ++++++++++++++-------------- src/corelib/kernel/qppsobject_p.h | 74 ++++++++++++++-------------- src/corelib/kernel/qppsobjectprivate_p.h | 74 ++++++++++++++-------------- src/corelib/kernel/qtestsupport_core.cpp | 2 +- src/corelib/kernel/qtestsupport_core.h | 2 +- 9 files changed, 263 insertions(+), 262 deletions(-) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qcore_mac_objc.mm b/src/corelib/kernel/qcore_mac_objc.mm index 4ca9c2e996..cb3539f3ec 100644 --- a/src/corelib/kernel/qcore_mac_objc.mm +++ b/src/corelib/kernel/qcore_mac_objc.mm @@ -1,42 +1,42 @@ /**************************************************************************** - ** - ** Copyright (C) 2016 The Qt Company Ltd. - ** Copyright (C) 2014 Petroules Corporation. - ** Contact: https://www.qt.io/licensing/ - ** - ** This file is part of the QtCore module of the Qt Toolkit. - ** - ** $QT_BEGIN_LICENSE:LGPL$ - ** Commercial License Usage - ** Licensees holding valid commercial Qt licenses may use this file in - ** accordance with the commercial license agreement provided with the - ** Software or, alternatively, in accordance with the terms contained in - ** a written agreement between you and The Qt Company. For licensing terms - ** and conditions see https://www.qt.io/terms-conditions. For further - ** information use the contact form at https://www.qt.io/contact-us. - ** - ** GNU Lesser General Public License Usage - ** Alternatively, this file may be used under the terms of the GNU Lesser - ** General Public License version 3 as published by the Free Software - ** Foundation and appearing in the file LICENSE.LGPL3 included in the - ** packaging of this file. Please review the following information to - ** ensure the GNU Lesser General Public License version 3 requirements - ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. - ** - ** GNU General Public License Usage - ** Alternatively, this file may be used under the terms of the GNU - ** General Public License version 2.0 or (at your option) the GNU General - ** Public license version 3 or any later version approved by the KDE Free - ** Qt Foundation. The licenses are as published by the Free Software - ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 - ** included in the packaging of this file. Please review the following - ** information to ensure the GNU General Public License requirements will - ** be met: https://www.gnu.org/licenses/gpl-2.0.html and - ** https://www.gnu.org/licenses/gpl-3.0.html. - ** - ** $QT_END_LICENSE$ - ** - ****************************************************************************/ +** +** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2014 Petroules Corporation. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ #include diff --git a/src/corelib/kernel/qppsattribute.cpp b/src/corelib/kernel/qppsattribute.cpp index ffd5c53a6d..6be462edb5 100644 --- a/src/corelib/kernel/qppsattribute.cpp +++ b/src/corelib/kernel/qppsattribute.cpp @@ -1,41 +1,41 @@ /**************************************************************************** - ** - ** Copyright (C) 2013 BlackBerry Limited. All rights reserved. - ** Contact: https://www.qt.io/licensing/ - ** - ** This file is part of the QtCore module of the Qt Toolkit. - ** - ** $QT_BEGIN_LICENSE:LGPL$ - ** Commercial License Usage - ** Licensees holding valid commercial Qt licenses may use this file in - ** accordance with the commercial license agreement provided with the - ** Software or, alternatively, in accordance with the terms contained in - ** a written agreement between you and The Qt Company. For licensing terms - ** and conditions see https://www.qt.io/terms-conditions. For further - ** information use the contact form at https://www.qt.io/contact-us. - ** - ** GNU Lesser General Public License Usage - ** Alternatively, this file may be used under the terms of the GNU Lesser - ** General Public License version 3 as published by the Free Software - ** Foundation and appearing in the file LICENSE.LGPL3 included in the - ** packaging of this file. Please review the following information to - ** ensure the GNU Lesser General Public License version 3 requirements - ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. - ** - ** GNU General Public License Usage - ** Alternatively, this file may be used under the terms of the GNU - ** General Public License version 2.0 or (at your option) the GNU General - ** Public license version 3 or any later version approved by the KDE Free - ** Qt Foundation. The licenses are as published by the Free Software - ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 - ** included in the packaging of this file. Please review the following - ** information to ensure the GNU General Public License requirements will - ** be met: https://www.gnu.org/licenses/gpl-2.0.html and - ** https://www.gnu.org/licenses/gpl-3.0.html. - ** - ** $QT_END_LICENSE$ - ** - ****************************************************************************/ +** +** Copyright (C) 2013 BlackBerry Limited. All rights reserved. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ #include "qppsattribute_p.h" #include "qppsattributeprivate_p.h" diff --git a/src/corelib/kernel/qppsattribute_p.h b/src/corelib/kernel/qppsattribute_p.h index 035756e002..b59dcd5851 100644 --- a/src/corelib/kernel/qppsattribute_p.h +++ b/src/corelib/kernel/qppsattribute_p.h @@ -1,41 +1,42 @@ /**************************************************************************** - ** - ** Copyright (C) 2013 BlackBerry Limited. All rights reserved. - ** Contact: https://www.qt.io/licensing/ - ** - ** This file is part of the QtCore module of the Qt Toolkit. - ** - ** $QT_BEGIN_LICENSE:LGPL$ - ** Commercial License Usage - ** Licensees holding valid commercial Qt licenses may use this file in - ** accordance with the commercial license agreement provided with the - ** Software or, alternatively, in accordance with the terms contained in - ** a written agreement between you and The Qt Company. For licensing terms - ** and conditions see https://www.qt.io/terms-conditions. For further - ** information use the contact form at https://www.qt.io/contact-us. - ** - ** GNU Lesser General Public License Usage - ** Alternatively, this file may be used under the terms of the GNU Lesser - ** General Public License version 3 as published by the Free Software - ** Foundation and appearing in the file LICENSE.LGPL3 included in the - ** packaging of this file. Please review the following information to - ** ensure the GNU Lesser General Public License version 3 requirements - ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. - ** - ** GNU General Public License Usage - ** Alternatively, this file may be used under the terms of the GNU - ** General Public License version 2.0 or (at your option) the GNU General - ** Public license version 3 or any later version approved by the KDE Free - ** Qt Foundation. The licenses are as published by the Free Software - ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 - ** included in the packaging of this file. Please review the following - ** information to ensure the GNU General Public License requirements will - ** be met: https://www.gnu.org/licenses/gpl-2.0.html and - ** https://www.gnu.org/licenses/gpl-3.0.html. - ** - ** $QT_END_LICENSE$ - ** - ****************************************************************************/ +** +** Copyright (C) 2013 BlackBerry Limited. All rights reserved. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + #ifndef QPPSATTRIBUTE_P_H #define QPPSATTRIBUTE_P_H diff --git a/src/corelib/kernel/qppsattributeprivate_p.h b/src/corelib/kernel/qppsattributeprivate_p.h index 6166447ef2..78b7b3c4c2 100644 --- a/src/corelib/kernel/qppsattributeprivate_p.h +++ b/src/corelib/kernel/qppsattributeprivate_p.h @@ -1,41 +1,41 @@ /**************************************************************************** - ** - ** Copyright (C) 2013 BlackBerry Limited. All rights reserved. - ** Contact: https://www.qt.io/licensing/ - ** - ** This file is part of the QtCore module of the Qt Toolkit. - ** - ** $QT_BEGIN_LICENSE:LGPL$ - ** Commercial License Usage - ** Licensees holding valid commercial Qt licenses may use this file in - ** accordance with the commercial license agreement provided with the - ** Software or, alternatively, in accordance with the terms contained in - ** a written agreement between you and The Qt Company. For licensing terms - ** and conditions see https://www.qt.io/terms-conditions. For further - ** information use the contact form at https://www.qt.io/contact-us. - ** - ** GNU Lesser General Public License Usage - ** Alternatively, this file may be used under the terms of the GNU Lesser - ** General Public License version 3 as published by the Free Software - ** Foundation and appearing in the file LICENSE.LGPL3 included in the - ** packaging of this file. Please review the following information to - ** ensure the GNU Lesser General Public License version 3 requirements - ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. - ** - ** GNU General Public License Usage - ** Alternatively, this file may be used under the terms of the GNU - ** General Public License version 2.0 or (at your option) the GNU General - ** Public license version 3 or any later version approved by the KDE Free - ** Qt Foundation. The licenses are as published by the Free Software - ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 - ** included in the packaging of this file. Please review the following - ** information to ensure the GNU General Public License requirements will - ** be met: https://www.gnu.org/licenses/gpl-2.0.html and - ** https://www.gnu.org/licenses/gpl-3.0.html. - ** - ** $QT_END_LICENSE$ - ** - ****************************************************************************/ +** +** Copyright (C) 2013 BlackBerry Limited. All rights reserved. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ #ifndef QPPSATTRIBUTEPRIVATE_P_H #define QPPSATTRIBUTEPRIVATE_P_H diff --git a/src/corelib/kernel/qppsobject.cpp b/src/corelib/kernel/qppsobject.cpp index d58715d12b..f4001d3833 100644 --- a/src/corelib/kernel/qppsobject.cpp +++ b/src/corelib/kernel/qppsobject.cpp @@ -1,41 +1,41 @@ /**************************************************************************** - ** - ** Copyright (C) 2013 BlackBerry Limited. All rights reserved. - ** Contact: https://www.qt.io/licensing/ - ** - ** This file is part of the QtCore module of the Qt Toolkit. - ** - ** $QT_BEGIN_LICENSE:LGPL$ - ** Commercial License Usage - ** Licensees holding valid commercial Qt licenses may use this file in - ** accordance with the commercial license agreement provided with the - ** Software or, alternatively, in accordance with the terms contained in - ** a written agreement between you and The Qt Company. For licensing terms - ** and conditions see https://www.qt.io/terms-conditions. For further - ** information use the contact form at https://www.qt.io/contact-us. - ** - ** GNU Lesser General Public License Usage - ** Alternatively, this file may be used under the terms of the GNU Lesser - ** General Public License version 3 as published by the Free Software - ** Foundation and appearing in the file LICENSE.LGPL3 included in the - ** packaging of this file. Please review the following information to - ** ensure the GNU Lesser General Public License version 3 requirements - ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. - ** - ** GNU General Public License Usage - ** Alternatively, this file may be used under the terms of the GNU - ** General Public License version 2.0 or (at your option) the GNU General - ** Public license version 3 or any later version approved by the KDE Free - ** Qt Foundation. The licenses are as published by the Free Software - ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 - ** included in the packaging of this file. Please review the following - ** information to ensure the GNU General Public License requirements will - ** be met: https://www.gnu.org/licenses/gpl-2.0.html and - ** https://www.gnu.org/licenses/gpl-3.0.html. - ** - ** $QT_END_LICENSE$ - ** - ****************************************************************************/ +** +** Copyright (C) 2013 BlackBerry Limited. All rights reserved. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ #include "qppsobject_p.h" diff --git a/src/corelib/kernel/qppsobject_p.h b/src/corelib/kernel/qppsobject_p.h index c7b99c8e42..abcf00fa05 100644 --- a/src/corelib/kernel/qppsobject_p.h +++ b/src/corelib/kernel/qppsobject_p.h @@ -1,41 +1,41 @@ /**************************************************************************** - ** - ** Copyright (C) 2013 BlackBerry Limited. All rights reserved. - ** Contact: https://www.qt.io/licensing/ - ** - ** This file is part of the QtCore module of the Qt Toolkit. - ** - ** $QT_BEGIN_LICENSE:LGPL$ - ** Commercial License Usage - ** Licensees holding valid commercial Qt licenses may use this file in - ** accordance with the commercial license agreement provided with the - ** Software or, alternatively, in accordance with the terms contained in - ** a written agreement between you and The Qt Company. For licensing terms - ** and conditions see https://www.qt.io/terms-conditions. For further - ** information use the contact form at https://www.qt.io/contact-us. - ** - ** GNU Lesser General Public License Usage - ** Alternatively, this file may be used under the terms of the GNU Lesser - ** General Public License version 3 as published by the Free Software - ** Foundation and appearing in the file LICENSE.LGPL3 included in the - ** packaging of this file. Please review the following information to - ** ensure the GNU Lesser General Public License version 3 requirements - ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. - ** - ** GNU General Public License Usage - ** Alternatively, this file may be used under the terms of the GNU - ** General Public License version 2.0 or (at your option) the GNU General - ** Public license version 3 or any later version approved by the KDE Free - ** Qt Foundation. The licenses are as published by the Free Software - ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 - ** included in the packaging of this file. Please review the following - ** information to ensure the GNU General Public License requirements will - ** be met: https://www.gnu.org/licenses/gpl-2.0.html and - ** https://www.gnu.org/licenses/gpl-3.0.html. - ** - ** $QT_END_LICENSE$ - ** - ****************************************************************************/ +** +** Copyright (C) 2013 BlackBerry Limited. All rights reserved. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ #ifndef QPPSOBJECT_P_H #define QPPSOBJECT_P_H diff --git a/src/corelib/kernel/qppsobjectprivate_p.h b/src/corelib/kernel/qppsobjectprivate_p.h index dae44e3609..d6b4640832 100644 --- a/src/corelib/kernel/qppsobjectprivate_p.h +++ b/src/corelib/kernel/qppsobjectprivate_p.h @@ -1,41 +1,41 @@ /**************************************************************************** - ** - ** Copyright (C) 2013 BlackBerry Limited. All rights reserved. - ** Contact: https://www.qt.io/licensing/ - ** - ** This file is part of the QtCore module of the Qt Toolkit. - ** - ** $QT_BEGIN_LICENSE:LGPL$ - ** Commercial License Usage - ** Licensees holding valid commercial Qt licenses may use this file in - ** accordance with the commercial license agreement provided with the - ** Software or, alternatively, in accordance with the terms contained in - ** a written agreement between you and The Qt Company. For licensing terms - ** and conditions see https://www.qt.io/terms-conditions. For further - ** information use the contact form at https://www.qt.io/contact-us. - ** - ** GNU Lesser General Public License Usage - ** Alternatively, this file may be used under the terms of the GNU Lesser - ** General Public License version 3 as published by the Free Software - ** Foundation and appearing in the file LICENSE.LGPL3 included in the - ** packaging of this file. Please review the following information to - ** ensure the GNU Lesser General Public License version 3 requirements - ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. - ** - ** GNU General Public License Usage - ** Alternatively, this file may be used under the terms of the GNU - ** General Public License version 2.0 or (at your option) the GNU General - ** Public license version 3 or any later version approved by the KDE Free - ** Qt Foundation. The licenses are as published by the Free Software - ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 - ** included in the packaging of this file. Please review the following - ** information to ensure the GNU General Public License requirements will - ** be met: https://www.gnu.org/licenses/gpl-2.0.html and - ** https://www.gnu.org/licenses/gpl-3.0.html. - ** - ** $QT_END_LICENSE$ - ** - ****************************************************************************/ +** +** Copyright (C) 2013 BlackBerry Limited. All rights reserved. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ #ifndef QPPSOBJECTPRIVATE_P_H_ #define QPPSOBJECTPRIVATE_P_H_ diff --git a/src/corelib/kernel/qtestsupport_core.cpp b/src/corelib/kernel/qtestsupport_core.cpp index d69551a227..e00ad75fef 100644 --- a/src/corelib/kernel/qtestsupport_core.cpp +++ b/src/corelib/kernel/qtestsupport_core.cpp @@ -3,7 +3,7 @@ ** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** -** This file is part of the QtTest module of the Qt Toolkit. +** This file is part of the QtCore module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage diff --git a/src/corelib/kernel/qtestsupport_core.h b/src/corelib/kernel/qtestsupport_core.h index 7fc0054580..c8b664b6d3 100644 --- a/src/corelib/kernel/qtestsupport_core.h +++ b/src/corelib/kernel/qtestsupport_core.h @@ -3,7 +3,7 @@ ** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** -** This file is part of the QtTest module of the Qt Toolkit. +** This file is part of the QtCore module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage -- cgit v1.2.3 From 4dc2bc323c985bdceb27f096dd6c8e7af657bb6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Wed, 2 Jan 2019 19:35:07 +0100 Subject: macOS: Remove Mojave forward-declarations now that we build with Xcode 10 Change-Id: I8528932f3744fbf3473219b6eeda7c26ac039b67 Reviewed-by: Timur Pocheptsov --- src/corelib/kernel/qcore_mac_objc.mm | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qcore_mac_objc.mm b/src/corelib/kernel/qcore_mac_objc.mm index cb3539f3ec..7b78ef11be 100644 --- a/src/corelib/kernel/qcore_mac_objc.mm +++ b/src/corelib/kernel/qcore_mac_objc.mm @@ -41,12 +41,7 @@ #include #ifdef Q_OS_MACOS -# include -# if !QT_MACOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_14) -@interface NSApplication (MojaveForwardDeclarations) -@property (strong) NSAppearance *effectiveAppearance NS_AVAILABLE_MAC(10_14); -@end -# endif +#include #endif #if defined(QT_PLATFORM_UIKIT) @@ -174,10 +169,11 @@ QDebug operator<<(QDebug debug, const QMacAutoReleasePool *pool) #ifdef Q_OS_MACOS bool qt_mac_applicationIsInDarkMode() { +#if QT_MACOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_14) if (__builtin_available(macOS 10.14, *)) return [NSApp.effectiveAppearance.name hasSuffix:@"DarkAqua"]; - else - return false; +#endif + return false; } #endif -- cgit v1.2.3 From 3b03150aa2af76b13424c988c6c7892d19cce6c5 Mon Sep 17 00:00:00 2001 From: Topi Reinio Date: Wed, 12 Dec 2018 12:36:39 +0100 Subject: Doc: Restore documentation for QTest functions in other modules Qt Test library sources specific to Core, GUI and Widgets modules were moved around in commit 88867e39b. The new source locations must be referenced in Qt Test documentation configuration. The same sources are excluded in their original doc projects, and the related snippet file is moved over to qttestlib. The commit also fixes the remaining documentation issues for Qt Test. Change-Id: Ibe011aa83639e574d647f12bc9e53e618781bce6 Reviewed-by: Martin Smith --- src/corelib/kernel/qtestsupport_core.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qtestsupport_core.cpp b/src/corelib/kernel/qtestsupport_core.cpp index d69551a227..aba2a136a1 100644 --- a/src/corelib/kernel/qtestsupport_core.cpp +++ b/src/corelib/kernel/qtestsupport_core.cpp @@ -59,8 +59,7 @@ Q_CORE_EXPORT void QTestPrivate::qSleep(int ms) #endif } -/*! \fn template bool qWaitFor(Functor predicate, int timeout) - \relates QTest +/*! \fn template bool QTest::qWaitFor(Functor predicate, int timeout) Waits for \a timeout milliseconds or until the \a predicate returns true. @@ -77,8 +76,7 @@ Q_CORE_EXPORT void QTestPrivate::qSleep(int ms) */ -/*! \fn void qWait(int ms) - \relates QTest +/*! \fn void QTest::qWait(int ms) Waits for \a ms milliseconds. While waiting, events will be processed and your test will stay responsive to user interface events or network communication. -- cgit v1.2.3 From 1075f10184e52ecb08e9b91ae8da25d12f17a9ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Sat, 22 Dec 2018 20:08:27 +0100 Subject: macOS: Optimize detection of dark mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I579527c54f8453c1e4f57bab7eebfc576b6ad365 Reviewed-by: Morten Johan Sørvig --- src/corelib/kernel/qcore_mac_objc.mm | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qcore_mac_objc.mm b/src/corelib/kernel/qcore_mac_objc.mm index 7b78ef11be..bc23e821fd 100644 --- a/src/corelib/kernel/qcore_mac_objc.mm +++ b/src/corelib/kernel/qcore_mac_objc.mm @@ -170,8 +170,11 @@ QDebug operator<<(QDebug debug, const QMacAutoReleasePool *pool) bool qt_mac_applicationIsInDarkMode() { #if QT_MACOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_14) - if (__builtin_available(macOS 10.14, *)) - return [NSApp.effectiveAppearance.name hasSuffix:@"DarkAqua"]; + if (__builtin_available(macOS 10.14, *)) { + auto appearance = [NSApp.effectiveAppearance bestMatchFromAppearancesWithNames: + @[ NSAppearanceNameAqua, NSAppearanceNameDarkAqua ]]; + return [appearance isEqualToString:NSAppearanceNameDarkAqua]; + } #endif return false; } -- cgit v1.2.3 From ecdccce8e468784e050b65052da193bb40e2d9b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Nowacki?= Date: Fri, 4 Jan 2019 13:48:56 +0100 Subject: Fix warnings about uninitialized variables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit qtbase/src/corelib/kernel/qmetatype.cpp: In static member function ‘static void QMetaType::destroy(int, void*)’: qtbase/src/corelib/kernel/qmetatype.cpp:2599:27: error: ‘info.QMetaType::m_destructor’ may be used uninitialized in this function [-Werror=maybe-uninitialized] if (m_typedDestructor && !m_destructor) ~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~ qtbase/src/corelib/kernel/qmetatype.cpp:1868:15: note: ‘info.QMetaType::m_destructor’ was declared here QMetaType info(type); ^~~~ qtbase/src/corelib/kernel/qmetatype.cpp:2600:26: error: ‘info.QMetaType::m_typedDestructor’ may be used uninitialized in this function [-Werror=maybe-uninitialized] m_typedDestructor(m_typeId, data); ~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~ qtbase/src/corelib/kernel/qmetatype.cpp:1868:15: note: ‘info.QMetaType::m_typedDestructor’ was declared here QMetaType info(type); ^~~~ The extended (not inlined) function may be called on a half initialized invalid instance. Change-Id: I26d677a8ad2bd0c5846233f06393e774d377936d Reviewed-by: Liang Qi Reviewed-by: Thiago Macieira --- src/corelib/kernel/qmetatype.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qmetatype.cpp b/src/corelib/kernel/qmetatype.cpp index eb67544f21..632b86959d 100644 --- a/src/corelib/kernel/qmetatype.cpp +++ b/src/corelib/kernel/qmetatype.cpp @@ -2566,6 +2566,8 @@ void *QMetaType::createExtended(const void *copy) const */ void QMetaType::destroyExtended(void *data) const { + if (m_typeId == QMetaType::UnknownType) + return; if (Q_UNLIKELY(m_typedDestructor && !m_destructor)) m_typedDestructor(m_typeId, data); else @@ -2582,6 +2584,8 @@ void QMetaType::destroyExtended(void *data) const */ void *QMetaType::constructExtended(void *where, const void *copy) const { + if (m_typeId == QMetaType::UnknownType) + return nullptr; if (m_typedConstructor && !m_constructor) return m_typedConstructor(m_typeId, where, copy); return nullptr; @@ -2596,6 +2600,8 @@ void *QMetaType::constructExtended(void *where, const void *copy) const */ void QMetaType::destructExtended(void *data) const { + if (m_typeId == QMetaType::UnknownType) + return; if (m_typedDestructor && !m_destructor) m_typedDestructor(m_typeId, data); } -- cgit v1.2.3 From f7d7d7c81cf233a305ec1b1972bb459623a68e2b Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Mon, 17 Dec 2018 13:49:51 +0100 Subject: Minor optimization Avoid calling QThread::current() in many cases. Change-Id: Iac2e8ff1a72e3d39b6efa7e94239abbce29924ac Reviewed-by: Thiago Macieira Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/kernel/qmetaobject.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp index 5de2717078..27153e0c4d 100644 --- a/src/corelib/kernel/qmetaobject.cpp +++ b/src/corelib/kernel/qmetaobject.cpp @@ -2257,9 +2257,9 @@ bool QMetaMethod::invoke(QObject *object, return false; // check connection type - QThread *currentThread = QThread::currentThread(); - QThread *objectThread = object->thread(); if (connectionType == Qt::AutoConnection) { + QThread *currentThread = QThread::currentThread(); + QThread *objectThread = object->thread(); connectionType = currentThread == objectThread ? Qt::DirectConnection : Qt::QueuedConnection; @@ -2342,6 +2342,8 @@ bool QMetaMethod::invoke(QObject *object, 0, -1, nargs, types, args)); } else { // blocking queued connection #if QT_CONFIG(thread) + QThread *currentThread = QThread::currentThread(); + QThread *objectThread = object->thread(); if (currentThread == objectThread) { qWarning("QMetaMethod::invoke: Dead lock detected in " "BlockingQueuedConnection: Receiver is %s(%p)", -- cgit v1.2.3 From 87c47c6a82c7b6b40e248844feb23088d109f744 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Thu, 3 Jan 2019 15:25:59 +0100 Subject: Minor optimization Avoid a couple of branches in QMetaObject::activate(). Change-Id: I15394d1ede48be771797fc5f64a5de6387e6f814 Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/kernel/qobject.cpp | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 36c108b697..5989fbd1ef 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -3673,10 +3673,12 @@ void QMetaObject::activate(QObject *sender, int signalOffset, int local_signal_i return; } - void *empty_argv[] = { 0 }; + void *empty_argv[] = { nullptr }; + if (!argv) + argv = empty_argv; + if (qt_signal_spy_callback_set.signal_begin_callback != 0) { - qt_signal_spy_callback_set.signal_begin_callback(sender, signal_index, - argv ? argv : empty_argv); + qt_signal_spy_callback_set.signal_begin_callback(sender, signal_index, argv); } Q_TRACE(QMetaObject_activate_begin_signal, sender, signal_index); @@ -3739,7 +3741,7 @@ void QMetaObject::activate(QObject *sender, int signalOffset, int local_signal_i // put into the event queue if ((c->connectionType == Qt::AutoConnection && !receiverInSameThread) || (c->connectionType == Qt::QueuedConnection)) { - queued_activate(sender, signal_index, c, argv ? argv : empty_argv, locker); + queued_activate(sender, signal_index, c, argv, locker); continue; #if QT_CONFIG(thread) } else if (c->connectionType == Qt::BlockingQueuedConnection) { @@ -3751,8 +3753,8 @@ void QMetaObject::activate(QObject *sender, int signalOffset, int local_signal_i } QSemaphore semaphore; QMetaCallEvent *ev = c->isSlotObject ? - new QMetaCallEvent(c->slotObj, sender, signal_index, 0, 0, argv ? argv : empty_argv, &semaphore) : - new QMetaCallEvent(c->method_offset, c->method_relative, c->callFunction, sender, signal_index, 0, 0, argv ? argv : empty_argv, &semaphore); + 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); QCoreApplication::postEvent(receiver, ev); locker.unlock(); semaphore.acquire(); @@ -3771,7 +3773,7 @@ void QMetaObject::activate(QObject *sender, int signalOffset, int local_signal_i QScopedPointer obj(c->slotObj); locker.unlock(); Q_TRACE(QMetaObject_activate_begin_slot_functor, obj.data()); - obj->call(receiver, argv ? argv : empty_argv); + obj->call(receiver, argv); Q_TRACE(QMetaObject_activate_end_slot_functor, obj.data()); // Make sure the slot object gets destroyed before the mutex is locked again, as the @@ -3787,10 +3789,10 @@ void QMetaObject::activate(QObject *sender, int signalOffset, int local_signal_i const auto callFunction = c->callFunction; locker.unlock(); if (qt_signal_spy_callback_set.slot_begin_callback != 0) - qt_signal_spy_callback_set.slot_begin_callback(receiver, methodIndex, argv ? argv : empty_argv); + qt_signal_spy_callback_set.slot_begin_callback(receiver, methodIndex, argv); Q_TRACE(QMetaObject_activate_begin_slot, receiver, methodIndex); - callFunction(receiver, QMetaObject::InvokeMetaMethod, method_relative, argv ? argv : empty_argv); + callFunction(receiver, QMetaObject::InvokeMetaMethod, method_relative, argv); Q_TRACE(QMetaObject_activate_end_slot, receiver, methodIndex); if (qt_signal_spy_callback_set.slot_end_callback != 0) @@ -3801,13 +3803,11 @@ void QMetaObject::activate(QObject *sender, int signalOffset, int local_signal_i locker.unlock(); if (qt_signal_spy_callback_set.slot_begin_callback != 0) { - qt_signal_spy_callback_set.slot_begin_callback(receiver, - method, - argv ? argv : empty_argv); + qt_signal_spy_callback_set.slot_begin_callback(receiver, method, argv); } Q_TRACE(QMetaObject_activate_begin_slot, receiver, method); - metacall(receiver, QMetaObject::InvokeMetaMethod, method, argv ? argv : empty_argv); + metacall(receiver, QMetaObject::InvokeMetaMethod, method, argv); Q_TRACE(QMetaObject_activate_end_slot, receiver, method); if (qt_signal_spy_callback_set.slot_end_callback != 0) -- cgit v1.2.3 From 68511d41d50b1a136fb0e74fdabfd362e0b21a1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Wed, 5 Sep 2018 13:47:05 +0200 Subject: qWaitFor: Prevent being stuck in QCoreApplication::processEvents MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When using the overload of QCoreApplication::processEvents that takes a maxtime argument, the function will keep processing events until there are no more events, or until it times out. The problem is that the function doesn't distinguish between events that were on the event queue when the function was called, and events generated by processing events as part of its own execution. If for example a widget calls update() in its paintEvent, the function will spin for the entire duration of maxtime. That doesn't work for qWaitFor, where we need to check the predicate between each pass, so we use the overload of processEvents that doesn't take a maxtime. That's fine, as we have our own timeout logic. Change-Id: I9738d7d0187c36d4a5ddfcd3fd075b0bd84583c4 Reviewed-by: Qt CI Bot Reviewed-by: Tor Arne Vestbø --- src/corelib/kernel/qtestsupport_core.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qtestsupport_core.h b/src/corelib/kernel/qtestsupport_core.h index c8b664b6d3..c8209b5ae4 100644 --- a/src/corelib/kernel/qtestsupport_core.h +++ b/src/corelib/kernel/qtestsupport_core.h @@ -67,7 +67,13 @@ Q_REQUIRED_RESULT static bool qWaitFor(Functor predicate, int timeout = 5000) QDeadlineTimer deadline(remaining, Qt::PreciseTimer); do { - QCoreApplication::processEvents(QEventLoop::AllEvents, remaining); + // We explicitly do not pass the remaining time to processEvents, as + // that would keep spinning processEvents for the whole duration if + // new events were posted as part of processing events, and we need + // to return back to this function to check the predicate between + // each pass of processEvents. Our own timer will take care of the + // timeout. + QCoreApplication::processEvents(QEventLoop::AllEvents); QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete); remaining = deadline.remainingTime(); -- cgit v1.2.3 From 574b56913f3d1ca6ad05617c32bd275807613c6b Mon Sep 17 00:00:00 2001 From: Mitch Curtis Date: Mon, 7 Jan 2019 14:55:58 +0100 Subject: Doc: mention that some filtered events need to be explicitly accepted QKeyEvent's detailed description already documents this: "A key event contains a special accept flag that indicates whether the receiver will handle the key event. This flag is set by default for QEvent::KeyPress and QEvent::KeyRelease, so there is no need to call accept() when acting on a key event. For QEvent::ShortcutOverride the receiver needs to explicitly accept the event to trigger the override. Calling ignore() on a key event will propagate it to the parent widget. The event is propagated up the parent widget chain until a widget accepts it or an event filter consumes it." However, someone looking at eventFilter() won't see this, resulting in the shortcut not being consumed and propagating elsewhere, so mention it in the docs for eventFilter() too. Change-Id: I14fece52133be641ccdabd81f75706cd10b64669 Reviewed-by: Friedemann Kleint Reviewed-by: Venugopal Shivashankar Reviewed-by: Paul Wicking --- src/corelib/kernel/qobject.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 14af9ac8ef..b5d97c5538 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -1374,6 +1374,10 @@ void QObject::customEvent(QEvent * /* event */) might have reimplemented eventFilter() for its own internal purposes. + Some events, such as \l QEvent::ShortcutOverride must be explicitly + accepted (by calling \l {QEvent::}{accept()} on them) in order to prevent + propagation. + \warning If you delete the receiver object in this function, be sure to return true. Otherwise, Qt will forward the event to the deleted object and the program might crash. -- cgit v1.2.3 From c365fa49d85810c6ad09bb5f43b5081cd7543bf1 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Mon, 19 Dec 2016 13:50:17 +0100 Subject: fix out-of-bounds access on trailing percent sign in tr() argument tr() recognizes %n and %Ln. it offers no way to escape lone percent signs, which implies that they must be interpreted verbatim, which is what the code actually does. except that it would run off the end if the % appeared at the end of the string. Fixes: QTBUG-57171 Done-with: Mateusz Starzycki Change-Id: Icf81925c482be1ea66ec8daafb3e92ad17ea7fab Reviewed-by: Oswald Buddenhagen --- src/corelib/kernel/qcoreapplication.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index 3c8b0f947c..b6b4da3885 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -2097,9 +2097,13 @@ static void replacePercentN(QString *result, int n) int len = 0; while ((percentPos = result->indexOf(QLatin1Char('%'), percentPos + len)) != -1) { len = 1; + if (percentPos + len == result->length()) + break; QString fmt; if (result->at(percentPos + len) == QLatin1Char('L')) { ++len; + if (percentPos + len == result->length()) + break; fmt = QLatin1String("%L1"); } else { fmt = QLatin1String("%1"); -- cgit v1.2.3 From 119487650e28073f5766cc43cb679eb629a2a0c5 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Tue, 15 Jan 2019 15:32:44 +0100 Subject: Doc: End sentence about Q_GADGET with dot Change-Id: I55380d133017670f212df331fba655e80538e412 Reviewed-by: Leena Miettinen --- src/corelib/kernel/qobject.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index b5d97c5538..4680742a3e 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -4446,7 +4446,7 @@ QDebug operator<<(QDebug dbg, const QObject *o) macro, it must appear in the private section of a class definition. Q_GADGETs can have Q_ENUM, Q_PROPERTY and Q_INVOKABLE, but they cannot have - signals or slots + signals or slots. Q_GADGET makes a class member, \c{staticMetaObject}, available. \c{staticMetaObject} is of type QMetaObject and provides access to the -- cgit v1.2.3 From 4faf011c3f5f4a739f4ddc54040b5319f7fe5d90 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Thu, 10 Jan 2019 17:38:55 +0100 Subject: Document that you shouldn't Q_ENUM() things outside the int range The meta object system stores enums as signed int, probably for performance reasons. This is good enough for about 99% of the use cases. If you try to register larger types and then access them through the metaobject system, you can get undefined behavior. Task-number: QTBUG-71947 Change-Id: I16b395547c22fad10b476c2c2a0768538db0a20e Reviewed-by: Thiago Macieira --- src/corelib/kernel/qobject.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 4680742a3e..42c39f18e3 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -4338,6 +4338,12 @@ QDebug operator<<(QDebug dbg, const QObject *o) in a QVariant, you can convert them to strings. Likewise, passing them to QDebug will print out their names. + Mind that the enum values are stored as signed \c int in the meta object system. + Registering enumerations with values outside the range of values valid for \c int + will lead to overflows and potentially undefined behavior when accessing them through + the meta object system. QML, for example, does access registered enumerations through + the meta object system. + \sa {Qt's Property System} */ @@ -4389,6 +4395,12 @@ QDebug operator<<(QDebug dbg, const QObject *o) used in a QVariant, you can convert them to strings. Likewise, passing them to QDebug will print out their names. + Mind that the enum values are stored as signed \c int in the meta object system. + Registering enumerations with values outside the range of values valid for \c int + will lead to overflows and potentially undefined behavior when accessing them through + the meta object system. QML, for example, does access registered enumerations through + the meta object system. + \sa {Qt's Property System} */ -- cgit v1.2.3 From 589a01ff6b1eacf81e74a5fc4801572135214f43 Mon Sep 17 00:00:00 2001 From: Johan Klokkhammer Helsing Date: Thu, 13 Dec 2018 11:25:24 +0100 Subject: QMimeData: Prefer UTF-8 when multiple charsets are available This was especially a problem on Wayland where both "text/plain" (us-ascii) and "text/plain;charset=utf-8" are typically available. I.e. we would prefer ascii over utf-8, losing special characters. Fixes: QTBUG-54786 Change-Id: I985f66e16fcd5125e800c86c4d3949d210e939ba Reviewed-by: Thiago Macieira Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/corelib/kernel/qmimedata.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qmimedata.cpp b/src/corelib/kernel/qmimedata.cpp index c8ad1bc43f..9a98db21d3 100644 --- a/src/corelib/kernel/qmimedata.cpp +++ b/src/corelib/kernel/qmimedata.cpp @@ -51,6 +51,7 @@ QT_BEGIN_NAMESPACE static inline QString textUriListLiteral() { return QStringLiteral("text/uri-list"); } static inline QString textHtmlLiteral() { return QStringLiteral("text/html"); } static inline QString textPlainLiteral() { return QStringLiteral("text/plain"); } +static inline QString textPlainUtf8Literal() { return QStringLiteral("text/plain;charset=utf-8"); } static inline QString applicationXColorLiteral() { return QStringLiteral("application/x-color"); } static inline QString applicationXQtImageLiteral() { return QStringLiteral("application/x-qt-image"); } @@ -399,6 +400,10 @@ bool QMimeData::hasUrls() const QString QMimeData::text() const { Q_D(const QMimeData); + QVariant utf8Text = d->retrieveTypedData(textPlainUtf8Literal(), QVariant::String); + if (!utf8Text.isNull()) + return utf8Text.toString(); + QVariant data = d->retrieveTypedData(textPlainLiteral(), QVariant::String); return data.toString(); } -- cgit v1.2.3 From 3b514f853595c686d4ed8830567c1f27ea533faf Mon Sep 17 00:00:00 2001 From: Mikhail Svetkin Date: Fri, 4 Jan 2019 16:01:46 +0100 Subject: qtlite: Fix build libs with -no-feature-regularexpression Change-Id: I427ff1f8f4986fbf466aba60a9d3de614c1e006f Reviewed-by: Lars Knoll --- src/corelib/kernel/qvariant.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp index 6541b97595..090436a3c7 100644 --- a/src/corelib/kernel/qvariant.cpp +++ b/src/corelib/kernel/qvariant.cpp @@ -1052,11 +1052,13 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok) return false; #ifndef QT_BOOTSTRAPPED +#if QT_CONFIG(regularexpression) case QMetaType::QRegularExpression: if (d->type != QMetaType::QCborValue || !v_cast(d)->isRegularExpression()) return false; *static_cast(result) = v_cast(d)->toRegularExpression(); break; +#endif case QMetaType::QJsonValue: switch (d->type) { case QMetaType::Nullptr: @@ -1232,9 +1234,11 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok) case QVariant::Url: *static_cast(result) = QCborValue(*v_cast(d)); break; +#if QT_CONFIG(regularexpression) case QVariant::RegularExpression: *static_cast(result) = QCborValue(*v_cast(d)); break; +#endif case QVariant::Uuid: *static_cast(result) = QCborValue(*v_cast(d)); break; -- cgit v1.2.3 From 6a7e2fedefba69b338d859cba091cd8678e2dcc1 Mon Sep 17 00:00:00 2001 From: Christian Andersen Date: Sun, 27 Jan 2019 17:41:15 +0100 Subject: Windows: improve QTimer::remainingTime when called before processEvents This checks that intenalHwnd in QEventDispatcherWin32::remainingTime is initialized. If calling remaningTime, before createInternalHwnd is called, the timeout member in the WinTimerInfo struct is not initialized and contains a random value. This adds a check for that and in that case returns the requested timer interval as the timer has not yet been started. createInternalHwnd is called on the first request to process events. It also adds a test for checking the remaining time. But the issue can only be seen if solely running the remainingTimeInitial test in tst_QTimer. If running the test along side another test the other test likely calls processEvents indirectly, which hides the issue. I don't know if this is an issue in practice (the bug has been there for as long a the git history goes back, 2011), but it causes the basic_chrono test to fail if run as the only test. Change-Id: I05c35105da778912dedf8d749aa7c953841d986e Reviewed-by: Thiago Macieira --- src/corelib/kernel/qeventdispatcher_win.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qeventdispatcher_win.cpp b/src/corelib/kernel/qeventdispatcher_win.cpp index 0bddf89b15..343ed70196 100644 --- a/src/corelib/kernel/qeventdispatcher_win.cpp +++ b/src/corelib/kernel/qeventdispatcher_win.cpp @@ -992,8 +992,14 @@ int QEventDispatcherWin32::remainingTime(int timerId) quint64 currentTime = qt_msectime(); for (const WinTimerInfo *t : qAsConst(d->timerVec)) { - if (t && t->timerId == timerId) // timer found, return time to wait - return t->timeout > currentTime ? t->timeout - currentTime : 0; + if (t && t->timerId == timerId) { + // timer found, return time to wait + + if (d->internalHwnd) + return t->timeout > currentTime ? t->timeout - currentTime : 0; + else + return t->interval; + } } #ifndef QT_NO_DEBUG -- cgit v1.2.3 From 6298850293f5674f43fc0ef28363bb97a4f8ea5f Mon Sep 17 00:00:00 2001 From: Christian Ehrlicher Date: Sun, 27 Jan 2019 17:49:57 +0100 Subject: QtCore: replace 0 with \nullptr in documentation Replace 0 with \nullptr in the documentation. As a drive-by also replace some 0 with nullptr in the corresponding code. Change-Id: I101a61f5fad71cadb73bba9a8fd5dce6cc0836d0 Reviewed-by: Thiago Macieira Reviewed-by: Friedemann Kleint Reviewed-by: Paul Wicking --- src/corelib/kernel/qmetaobject.cpp | 12 ++++++------ src/corelib/kernel/qmetatype.cpp | 4 ++-- src/corelib/kernel/qobject.cpp | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp index 27153e0c4d..8082b7fe9b 100644 --- a/src/corelib/kernel/qmetaobject.cpp +++ b/src/corelib/kernel/qmetaobject.cpp @@ -216,8 +216,8 @@ private: Constructs a new instance of this class. You can pass up to ten arguments (\a val0, \a val1, \a val2, \a val3, \a val4, \a val5, \a val6, \a val7, - \a val8, and \a val9) to the constructor. Returns the new object, or 0 if - no suitable constructor is available. + \a val8, and \a val9) to the constructor. Returns the new object, or + \nullptr if no suitable constructor is available. Note that only constructors that are declared with the Q_INVOKABLE modifier are made available through the meta-object system. @@ -321,8 +321,8 @@ const char *QMetaObject::className() const /*! \fn QMetaObject *QMetaObject::superClass() const - Returns the meta-object of the superclass, or 0 if there is no - such object. + Returns the meta-object of the superclass, or \nullptr if there is + no such object. \sa className() */ @@ -2615,7 +2615,7 @@ int QMetaEnum::keyCount() const } /*! - Returns the key with the given \a index, or 0 if no such key exists. + Returns the key with the given \a index, or \nullptr if no such key exists. \sa keyCount(), value(), valueToKey() */ @@ -2737,7 +2737,7 @@ int QMetaEnum::keyToValue(const char *key, bool *ok) const /*! Returns the string that is used as the name of the given - enumeration \a value, or 0 if \a value is not defined. + enumeration \a value, or \nullptr if \a value is not defined. For flag types, use valueToKeys(). diff --git a/src/corelib/kernel/qmetatype.cpp b/src/corelib/kernel/qmetatype.cpp index b9e35e28e4..a1d53be197 100644 --- a/src/corelib/kernel/qmetatype.cpp +++ b/src/corelib/kernel/qmetatype.cpp @@ -421,8 +421,8 @@ struct DefinedTypesFilter { pointer of this type. (given by QVariant::data for example) If the type is an enumeration, flags() contains QMetaType::IsEnumeration, and this function - returns the QMetaObject of the enclosing object if the enum was registered as a Q_ENUM or 0 - otherwise + returns the QMetaObject of the enclosing object if the enum was registered as a Q_ENUM or + \nullptr otherwise \sa QMetaType::metaObjectForType(), QMetaType::flags() */ diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 73b8c33efe..c0c009f254 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -1763,7 +1763,7 @@ void QObject::killTimer(int id) \fn template T *QObject::findChild(const QString &name, Qt::FindChildOptions options) const Returns the child of this object that can be cast into type T and - that is called \a name, or 0 if there is no such object. + that is called \a name, or \nullptr if there is no such object. Omitting the \a name argument causes all object names to be matched. The search is performed recursively, unless \a options specifies the option FindDirectChildrenOnly. -- cgit v1.2.3 From ddb5d390450de25e510c72b17ed8124b9186a736 Mon Sep 17 00:00:00 2001 From: Andreas Hartmetz Date: Tue, 5 Feb 2019 14:39:41 +0100 Subject: QMetaObject::Connection overview documentation improvements Try to better describe what it is and what it does. Also mention its strongest use case. Change-Id: Ib5c3e8a3c9b96169c139c5d7e8995a6a49d7d5e1 Reviewed-by: Mitch Curtis Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/kernel/qobject.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 42c39f18e3..b4e885e407 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -5070,11 +5070,14 @@ bool QObjectPrivate::disconnect(const QObject *sender, int signal_index, void ** /*! \class QMetaObject::Connection \inmodule QtCore - Represents a handle to a signal-slot connection. - It can be used to disconnect that connection, or check if - the connection was successful + Represents a handle to a signal-slot (or signal-functor) connection. - \sa QObject::disconnect() + It can be used to check if the connection is valid and to disconnect it using + QObject::disconnect(). For a signal-functor connection without a context object, + it is the only way to selectively disconnect that connection. + + As Connection is just a handle, the underlying signal-slot connection is unaffected + when Connection is destroyed or reassigned. */ /*! -- cgit v1.2.3 From e990d4d27f6ca2044808a91f88c39d2ac1c690e2 Mon Sep 17 00:00:00 2001 From: Tobias Hunger Date: Tue, 29 Jan 2019 10:38:23 +0100 Subject: corelib: typo fix in .pro-file Consistently use space before line continuation marker. Change-Id: Ib87d45f76b6fd174c78a04335f06b4dbed1bed13 Reviewed-by: Frederik Gladhorn --- src/corelib/kernel/kernel.pri | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/kernel.pri b/src/corelib/kernel/kernel.pri index 3f7bf3cd47..789bcb7927 100644 --- a/src/corelib/kernel/kernel.pri +++ b/src/corelib/kernel/kernel.pri @@ -7,7 +7,7 @@ HEADERS += \ kernel/qdeadlinetimer.h \ kernel/qdeadlinetimer_p.h \ kernel/qelapsedtimer.h \ - kernel/qeventloop.h\ + kernel/qeventloop.h \ kernel/qpointer.h \ kernel/qcorecmdlineargs_p.h \ kernel/qcoreapplication.h \ -- cgit v1.2.3 From 88a2a746b7ed49f4ac4861bbf8e3a55db691fa43 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Fri, 4 Jan 2019 14:55:28 +0100 Subject: Always return early if no signal is connected And simply emit the signal spy and tracing callbacks in that code path as well. Change-Id: I17f65055c7044caf1be58fac94bb7fe3487f3060 Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/kernel/qobject.cpp | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index c0c009f254..8a03fe2a86 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -3668,12 +3668,14 @@ void QMetaObject::activate(QObject *sender, int signalOffset, int local_signal_i Q_TRACE(QMetaObject_activate_end_declarative_signal, sender, signal_index); } - if (!sender->d_func()->isSignalConnected(signal_index, /*checkDeclarative =*/ false) - && !qt_signal_spy_callback_set.signal_begin_callback - && !qt_signal_spy_callback_set.signal_end_callback - && !Q_TRACE_ENABLED(QMetaObject_activate_begin_signal) - && !Q_TRACE_ENABLED(QMetaObject_activate_end_signal)) { - // The possible declarative connection is done, and nothing else is connected, so: + if (!sender->d_func()->isSignalConnected(signal_index, /*checkDeclarative =*/ false)) { + // The possible declarative connection is done, and nothing else is connected + if (qt_signal_spy_callback_set.signal_begin_callback != nullptr) + qt_signal_spy_callback_set.signal_begin_callback(sender, signal_index, argv); + Q_TRACE(QMetaObject_activate_begin_signal, sender, signal_index); + Q_TRACE(QMetaObject_activate_end_signal, sender, signal_index); + if (qt_signal_spy_callback_set.signal_end_callback != nullptr) + qt_signal_spy_callback_set.signal_end_callback(sender, signal_index); return; } @@ -3711,13 +3713,6 @@ void QMetaObject::activate(QObject *sender, int signalOffset, int local_signal_i QObjectConnectionListVector *operator->() const { return connectionLists; } }; ConnectionListsRef connectionLists = sender->d_func()->connectionLists; - if (!connectionLists.connectionLists) { - locker.unlock(); - if (qt_signal_spy_callback_set.signal_end_callback != 0) - qt_signal_spy_callback_set.signal_end_callback(sender, signal_index); - Q_TRACE(QMetaObject_activate_end_signal, sender, signal_index); - return; - } const QObjectPrivate::ConnectionList *list; if (signal_index < connectionLists->count()) -- cgit v1.2.3 From a5a859e721e7a1d0c5a3ec6abe2db55d9144bb36 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Thu, 3 Jan 2019 16:02:09 +0100 Subject: Get rid of the connectedSignals bitflags Measurements show that it's just almost as fast to simply query the connectionlist directly and avoid both the memory overhead of the bitfield and the associated bookkeeping. For connected signals, the difference is not relevant at all. With a signal that was never connected, removing the bitfield will cause signal emission to be ~2.5% faster. And if you ever disconnect from a signal, the bitfields might not be accurate and this can cause a major slowdown. Here are some numbers to validate this. All times are measured in ms for 100M signal emissions: without change with change string based connect: 3817 3836 pointer based connect: 4552 4571 not connected: 493 479 disconnected: 2113 559 Change-Id: Ia2c85036afaa7f991b883c8ff812f69cf4580f7e Reviewed-by: Olivier Goffart (Woboq GmbH) Reviewed-by: hjk --- src/corelib/kernel/qobject.cpp | 65 ++++++++++++++++++++---------------------- src/corelib/kernel/qobject_p.h | 18 +----------- 2 files changed, 32 insertions(+), 51 deletions(-) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 8a03fe2a86..c158cf9452 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -232,7 +232,6 @@ QObjectPrivate::QObjectPrivate(int version) receiveChildEvents = true; postedEvents = 0; extraData = 0; - connectedSignals[0] = connectedSignals[1] = 0; metaObject = 0; isWindow = false; deleteLaterCalled = false; @@ -409,19 +408,12 @@ void QObjectPrivate::addConnection(int signal, Connection *c) *c->prev = c; if (c->next) c->next->prev = &c->next; - - if (signal < 0) { - connectedSignals[0] = connectedSignals[1] = ~0; - } else if (signal < (int)sizeof(connectedSignals) * 8) { - connectedSignals[signal >> 5] |= (1 << (signal & 0x1f)); - } } void QObjectPrivate::cleanConnectionLists() { if (connectionLists->dirty && !connectionLists->inUse) { // remove broken connections - bool allConnected = false; for (int signal = -1; signal < connectionLists->count(); ++signal) { QObjectPrivate::ConnectionList &connectionList = (*connectionLists)[signal]; @@ -433,13 +425,11 @@ void QObjectPrivate::cleanConnectionLists() QObjectPrivate::Connection **prev = &connectionList.first; QObjectPrivate::Connection *c = *prev; - bool connected = false; // whether the signal is still connected somewhere while (c) { if (c->receiver) { last = c; prev = &c->nextConnectionList; c = *prev; - connected = true; } else { QObjectPrivate::Connection *next = c->nextConnectionList; *prev = next; @@ -451,19 +441,40 @@ void QObjectPrivate::cleanConnectionLists() // Correct the connection list's last pointer. // As conectionList.last could equal last, this could be a noop connectionList.last = last; - - if (!allConnected && !connected && signal >= 0 - && size_t(signal) < sizeof(connectedSignals) * 8) { - // This signal is no longer connected - connectedSignals[signal >> 5] &= ~(1 << (signal & 0x1f)); - } else if (signal == -1) { - allConnected = connected; - } } connectionLists->dirty = false; } } +/*! \internal + + Returns \c true if the signal with index \a signal_index from object \a sender is connected. + + \a signal_index must be the index returned by QObjectPrivate::signalIndex; +*/ +bool QObjectPrivate::isSignalConnected(uint signalIndex, bool checkDeclarative) const +{ + if (checkDeclarative && isDeclarativeSignalConnected(signalIndex)) + return true; + + if (!connectionLists) + return false; + + if (connectionLists->allsignals.first) + return true; + + if (signalIndex < uint(connectionLists->count())) { + const QObjectPrivate::Connection *c = connectionLists->at(signalIndex).first; + while (c) { + if (c->receiver) + return true; + c = c->nextConnectionList; + } + } + return false; +} + + /*! \internal */ @@ -2521,21 +2532,7 @@ bool QObject::isSignalConnected(const QMetaMethod &signal) const signalIndex += QMetaObjectPrivate::signalOffset(signal.mobj); QMutexLocker locker(signalSlotLock(this)); - if (d->connectionLists) { - if (signalIndex < sizeof(d->connectedSignals) * 8 && !d->connectionLists->dirty) - return d->isSignalConnected(signalIndex); - - if (signalIndex < uint(d->connectionLists->count())) { - const QObjectPrivate::Connection *c = - d->connectionLists->at(signalIndex).first; - while (c) { - if (c->receiver) - return true; - c = c->nextConnectionList; - } - } - } - return d->isDeclarativeSignalConnected(signalIndex); + return d->isSignalConnected(signalIndex, true); } /*! @@ -3668,7 +3665,7 @@ void QMetaObject::activate(QObject *sender, int signalOffset, int local_signal_i Q_TRACE(QMetaObject_activate_end_declarative_signal, sender, signal_index); } - if (!sender->d_func()->isSignalConnected(signal_index, /*checkDeclarative =*/ false)) { + if (!sender->d_func()->isSignalConnected(signal_index, false)) { // The possible declarative connection is done, and nothing else is connected if (qt_signal_spy_callback_set.signal_begin_callback != nullptr) qt_signal_spy_callback_set.signal_begin_callback(sender, signal_index, argv); diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h index a762e6f529..7cc82d4f71 100644 --- a/src/corelib/kernel/qobject_p.h +++ b/src/corelib/kernel/qobject_p.h @@ -201,7 +201,7 @@ public: static const QObjectPrivate *get(const QObject *o) { return o->d_func(); } int signalIndex(const char *signalName, const QMetaObject **meta = nullptr) const; - inline bool isSignalConnected(uint signalIdx, bool checkDeclarative = true) const; + bool isSignalConnected(uint signalIdx, bool checkDeclarative = true) const; inline bool isDeclarativeSignalConnected(uint signalIdx) const; // To allow abitrary objects to call connectNotify()/disconnectNotify() without making @@ -232,7 +232,6 @@ public: Connection *senders; // linked list of connections connected to this object Sender *currentSender; // object currently activating the object - mutable quint32 connectedSignals[2]; union { QObject *currentChildBeingDeleted; // should only be used when QObjectData::isDeletingChildren is set @@ -246,21 +245,6 @@ public: Q_DECLARE_TYPEINFO(QObjectPrivate::ConnectionList, Q_MOVABLE_TYPE); -/*! \internal - - Returns \c true if the signal with index \a signal_index from object \a sender is connected. - Signals with indices above a certain range are always considered connected (see connectedSignals - in QObjectPrivate). - - \a signal_index must be the index returned by QObjectPrivate::signalIndex; -*/ -inline bool QObjectPrivate::isSignalConnected(uint signal_index, bool checkDeclarative) const -{ - return signal_index >= sizeof(connectedSignals) * 8 - || (connectedSignals[signal_index >> 5] & (1 << (signal_index & 0x1f)) - || (checkDeclarative && isDeclarativeSignalConnected(signal_index))); -} - inline bool QObjectPrivate::isDeclarativeSignalConnected(uint signal_index) const { return declarativeData && QAbstractDeclarativeData::isSignalConnected -- cgit v1.2.3 From a65752c71bd25bbb66bf33d3a82f7901419c5d95 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Thu, 3 Jan 2019 22:57:28 +0100 Subject: Shave ~5% off from signal emission time Refactor activate(), so that we eliminate almost all checks for signal hooks in the common case. Here are the benchmark numbers showing the improvement for 100M signal emissions without change with change string based connect: 3836 3693 pointer based connect: 4571 4510 not connected: 479 433 disconnected: 559 522 Change-Id: I394e6ea5d5bc96e298e8cc0c763eed78c8041876 Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/kernel/qcoreapplication.cpp | 9 --- src/corelib/kernel/qobject.cpp | 102 ++++++++++++++++++++------------ src/corelib/kernel/qobject_p.h | 4 +- 3 files changed, 65 insertions(+), 50 deletions(-) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index e5098b8415..e6d1d26f3c 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -256,15 +256,6 @@ void QCoreApplicationPrivate::processCommandLineArguments() // Support for introspection -#ifndef QT_NO_QOBJECT -QSignalSpyCallbackSet Q_CORE_EXPORT qt_signal_spy_callback_set = { 0, 0, 0, 0 }; - -void qt_register_signal_spy_callbacks(const QSignalSpyCallbackSet &callback_set) -{ - qt_signal_spy_callback_set = callback_set; -} -#endif - extern "C" void Q_CORE_EXPORT qt_startup_hook() { } diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index c158cf9452..0c81e416da 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -77,6 +77,12 @@ QT_BEGIN_NAMESPACE static int DIRECT_CONNECTION_ONLY = 0; +Q_CORE_EXPORT QBasicAtomicPointer qt_signal_spy_callback_set = Q_BASIC_ATOMIC_INITIALIZER(nullptr); + +void qt_register_signal_spy_callbacks(QSignalSpyCallbackSet *callback_set) +{ + qt_signal_spy_callback_set.store(callback_set); +} QDynamicMetaObjectData::~QDynamicMetaObjectData() { @@ -3638,41 +3644,32 @@ static void queued_activate(QObject *sender, int signal, QObjectPrivate::Connect QCoreApplication::postEvent(c->receiver, ev); } -/*! - \internal - */ -void QMetaObject::activate(QObject *sender, const QMetaObject *m, int local_signal_index, - void **argv) +template +void doActivate(QObject *sender, int signal_index, void **argv) { - activate(sender, QMetaObjectPrivate::signalOffset(m), local_signal_index, argv); -} + QObjectPrivate *sp = QObjectPrivate::get(sender); -/*! - \internal - */ -void QMetaObject::activate(QObject *sender, int signalOffset, int local_signal_index, void **argv) -{ - int signal_index = signalOffset + local_signal_index; - - if (sender->d_func()->blockSig) + if (sp->blockSig) return; - if (sender->d_func()->isDeclarativeSignalConnected(signal_index) + if (sp->isDeclarativeSignalConnected(signal_index) && QAbstractDeclarativeData::signalEmitted) { Q_TRACE(QMetaObject_activate_begin_declarative_signal, sender, signal_index); - QAbstractDeclarativeData::signalEmitted(sender->d_func()->declarativeData, sender, + QAbstractDeclarativeData::signalEmitted(sp->declarativeData, sender, signal_index, argv); Q_TRACE(QMetaObject_activate_end_declarative_signal, sender, signal_index); } - if (!sender->d_func()->isSignalConnected(signal_index, false)) { + const QSignalSpyCallbackSet *signal_spy_set = callbacks_enabled ? qt_signal_spy_callback_set.load() : nullptr; + + if (!sp->isSignalConnected(signal_index, false)) { // The possible declarative connection is done, and nothing else is connected - if (qt_signal_spy_callback_set.signal_begin_callback != nullptr) - qt_signal_spy_callback_set.signal_begin_callback(sender, signal_index, argv); + if (callbacks_enabled && signal_spy_set->signal_begin_callback != nullptr) + signal_spy_set->signal_begin_callback(sender, signal_index, argv); Q_TRACE(QMetaObject_activate_begin_signal, sender, signal_index); Q_TRACE(QMetaObject_activate_end_signal, sender, signal_index); - if (qt_signal_spy_callback_set.signal_end_callback != nullptr) - qt_signal_spy_callback_set.signal_end_callback(sender, signal_index); + if (callbacks_enabled && signal_spy_set->signal_end_callback != nullptr) + signal_spy_set->signal_end_callback(sender, signal_index); return; } @@ -3680,9 +3677,8 @@ void QMetaObject::activate(QObject *sender, int signalOffset, int local_signal_i if (!argv) argv = empty_argv; - if (qt_signal_spy_callback_set.signal_begin_callback != 0) { - qt_signal_spy_callback_set.signal_begin_callback(sender, signal_index, argv); - } + if (callbacks_enabled && signal_spy_set->signal_begin_callback != nullptr) + signal_spy_set->signal_begin_callback(sender, signal_index, argv); Q_TRACE(QMetaObject_activate_begin_signal, sender, signal_index); { @@ -3709,7 +3705,7 @@ void QMetaObject::activate(QObject *sender, int signalOffset, int local_signal_i QObjectConnectionListVector *operator->() const { return connectionLists; } }; - ConnectionListsRef connectionLists = sender->d_func()->connectionLists; + ConnectionListsRef connectionLists = sp->connectionLists; const QObjectPrivate::ConnectionList *list; if (signal_index < connectionLists->count()) @@ -3731,7 +3727,7 @@ void QMetaObject::activate(QObject *sender, int signalOffset, int local_signal_i continue; QObject * const receiver = c->receiver; - const bool receiverInSameThread = currentThreadId == receiver->d_func()->threadData->threadId.load(); + const bool receiverInSameThread = currentThreadId == QObjectPrivate::get(receiver)->threadData->threadId.load(); // determine if this connection should be sent immediately or // put into the event queue @@ -3780,34 +3776,34 @@ void QMetaObject::activate(QObject *sender, int signalOffset, int local_signal_i locker.relock(); } else if (c->callFunction && c->method_offset <= receiver->metaObject()->methodOffset()) { //we compare the vtable to make sure we are not in the destructor of the object. - const int methodIndex = c->method(); const int method_relative = c->method_relative; const auto callFunction = c->callFunction; locker.unlock(); - if (qt_signal_spy_callback_set.slot_begin_callback != 0) - qt_signal_spy_callback_set.slot_begin_callback(receiver, methodIndex, argv); + const int methodIndex = (Q_HAS_TRACEPOINTS || callbacks_enabled) ? c->method() : 0; + if (callbacks_enabled && signal_spy_set->slot_begin_callback != nullptr) + signal_spy_set->slot_begin_callback(receiver, methodIndex, argv); Q_TRACE(QMetaObject_activate_begin_slot, receiver, methodIndex); callFunction(receiver, QMetaObject::InvokeMetaMethod, method_relative, argv); Q_TRACE(QMetaObject_activate_end_slot, receiver, methodIndex); - if (qt_signal_spy_callback_set.slot_end_callback != 0) - qt_signal_spy_callback_set.slot_end_callback(receiver, methodIndex); + if (callbacks_enabled && signal_spy_set->slot_end_callback != nullptr) + signal_spy_set->slot_end_callback(receiver, methodIndex); locker.relock(); } else { const int method = c->method_relative + c->method_offset; locker.unlock(); - if (qt_signal_spy_callback_set.slot_begin_callback != 0) { - qt_signal_spy_callback_set.slot_begin_callback(receiver, method, argv); + if (callbacks_enabled && signal_spy_set->slot_begin_callback != nullptr) { + signal_spy_set->slot_begin_callback(receiver, method, argv); } Q_TRACE(QMetaObject_activate_begin_slot, receiver, method); - metacall(receiver, QMetaObject::InvokeMetaMethod, method, argv); + QMetaObject::metacall(receiver, QMetaObject::InvokeMetaMethod, method, argv); Q_TRACE(QMetaObject_activate_end_slot, receiver, method); - if (qt_signal_spy_callback_set.slot_end_callback != 0) - qt_signal_spy_callback_set.slot_end_callback(receiver, method); + if (callbacks_enabled && signal_spy_set->slot_end_callback != nullptr) + signal_spy_set->slot_end_callback(receiver, method); locker.relock(); } @@ -3824,11 +3820,39 @@ void QMetaObject::activate(QObject *sender, int signalOffset, int local_signal_i } - if (qt_signal_spy_callback_set.signal_end_callback != 0) - qt_signal_spy_callback_set.signal_end_callback(sender, signal_index); + if (callbacks_enabled && signal_spy_set->signal_end_callback != nullptr) + signal_spy_set->signal_end_callback(sender, signal_index); Q_TRACE(QMetaObject_activate_end_signal, sender, signal_index); + } +/*! + \internal + */ +void QMetaObject::activate(QObject *sender, const QMetaObject *m, int local_signal_index, + void **argv) +{ + int signal_index = local_signal_index + QMetaObjectPrivate::signalOffset(m); + + if (Q_UNLIKELY(qt_signal_spy_callback_set.load())) + doActivate(sender, signal_index, argv); + else + doActivate(sender, signal_index, argv); +} + +/*! + \internal + */ +void QMetaObject::activate(QObject *sender, int signalOffset, int local_signal_index, void **argv) +{ + int signal_index = signalOffset + local_signal_index; + + if (Q_UNLIKELY(qt_signal_spy_callback_set.load())) + doActivate(sender, signal_index, argv); + else + doActivate(sender, signal_index, argv); + } + /*! \internal signal_index comes from indexOfMethod() diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h index 7cc82d4f71..a260ed680e 100644 --- a/src/corelib/kernel/qobject_p.h +++ b/src/corelib/kernel/qobject_p.h @@ -79,9 +79,9 @@ struct QSignalSpyCallbackSet EndCallback signal_end_callback, slot_end_callback; }; -void Q_CORE_EXPORT qt_register_signal_spy_callbacks(const QSignalSpyCallbackSet &callback_set); +void Q_CORE_EXPORT qt_register_signal_spy_callbacks(QSignalSpyCallbackSet *callback_set); -extern QSignalSpyCallbackSet Q_CORE_EXPORT qt_signal_spy_callback_set; +extern Q_CORE_EXPORT QBasicAtomicPointer qt_signal_spy_callback_set; enum { QObjectPrivateVersion = QT_VERSION }; -- cgit v1.2.3 From ab92b9e40025dcf08c14232de762a268201a78b4 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Fri, 4 Jan 2019 08:55:40 +0100 Subject: Simplify the code required for switching the current sender Squeezes another percent of performance out of QMetaObject::activate(). Change-Id: I620b8c578681280efcc9bec50cfb1020d2afc928 Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/kernel/qobject.cpp | 55 ++++++++---------------------------------- src/corelib/kernel/qobject_p.h | 50 ++++++++++++++++++-------------------- 2 files changed, 33 insertions(+), 72 deletions(-) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 0c81e416da..f7983f3251 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -166,39 +166,6 @@ extern "C" Q_CORE_EXPORT void qt_removeObject(QObject *) {} #endif -struct QConnectionSenderSwitcher { - QObject *receiver; - QObjectPrivate::Sender *previousSender; - QObjectPrivate::Sender currentSender; - bool switched; - - inline QConnectionSenderSwitcher() : switched(false) {} - - inline QConnectionSenderSwitcher(QObject *receiver, QObject *sender, int signal_absolute_id) - { - switchSender(receiver, sender, signal_absolute_id); - } - - inline void switchSender(QObject *receiver, QObject *sender, int signal_absolute_id) - { - this->receiver = receiver; - currentSender.sender = sender; - currentSender.signal = signal_absolute_id; - currentSender.ref = 1; - previousSender = QObjectPrivate::setCurrentSender(receiver, ¤tSender); - switched = true; - } - - inline ~QConnectionSenderSwitcher() - { - if (switched) - QObjectPrivate::resetCurrentSender(receiver, ¤tSender, previousSender); - } -private: - Q_DISABLE_COPY(QConnectionSenderSwitcher) -}; - - void (*QAbstractDeclarativeData::destroyed)(QAbstractDeclarativeData *, QObject *) = 0; void (*QAbstractDeclarativeData::destroyed_qml1)(QAbstractDeclarativeData *, QObject *) = 0; void (*QAbstractDeclarativeData::parentChanged)(QAbstractDeclarativeData *, QObject *, QObject *) = 0; @@ -938,10 +905,10 @@ QObject::~QObject() } } - // set ref to zero to indicate that this object has been deleted - if (d->currentSender != 0) - d->currentSender->ref = 0; - d->currentSender = 0; + if (d->currentSender) { + d->currentSender->receiverDeleted(); + d->currentSender = nullptr; + } if (d->connectionLists || d->senders) { QMutex *signalSlotMutex = signalSlotLock(this); @@ -1272,7 +1239,7 @@ bool QObject::event(QEvent *e) { QMetaCallEvent *mce = static_cast(e); - QConnectionSenderSwitcher sw(this, const_cast(mce->sender()), mce->signalId()); + QObjectPrivate::Sender sender(this, const_cast(mce->sender()), mce->signalId()); mce->placeMetaCall(this); break; @@ -1576,9 +1543,10 @@ void QObjectPrivate::setThreadData_helper(QThreadData *currentData, QThreadData } // the current emitting thread shouldn't restore currentSender after calling moveToThread() - if (currentSender) - currentSender->ref = 0; - currentSender = 0; + if (currentSender) { + currentSender->receiverDeleted(); + currentSender = nullptr; + } // set new thread data targetData->ref(); @@ -3755,11 +3723,8 @@ void doActivate(QObject *sender, int signal_index, void **argv) #endif } - QConnectionSenderSwitcher sw; + QObjectPrivate::Sender senderData(receiverInSameThread ? receiver : nullptr, sender, signal_index); - if (receiverInSameThread) { - sw.switchSender(receiver, sender, signal_index); - } if (c->isSlotObject) { c->slotObj->ref(); QScopedPointer obj(c->slotObj); diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h index a260ed680e..ab20064c65 100644 --- a/src/corelib/kernel/qobject_p.h +++ b/src/corelib/kernel/qobject_p.h @@ -167,9 +167,31 @@ public: struct Sender { + Sender(QObject *receiver, QObject *sender, int signal) + : receiver(receiver), sender(sender), signal(signal) + { + if (receiver) { + previous = receiver->d_func()->currentSender; + receiver->d_func()->currentSender = this; + } + } + ~Sender() + { + if (receiver) + receiver->d_func()->currentSender = previous; + } + void receiverDeleted() + { + Sender *s = this; + while (s) { + s->receiver = nullptr; + s = s->previous; + } + } + Sender *previous; + QObject *receiver; QObject *sender; int signal; - int ref; }; @@ -189,12 +211,6 @@ public: void addConnection(int signal, Connection *c); void cleanConnectionLists(); - static inline Sender *setCurrentSender(QObject *receiver, - Sender *sender); - static inline void resetCurrentSender(QObject *receiver, - Sender *currentSender, - Sender *previousSender); - static QObjectPrivate *get(QObject *o) { return o->d_func(); } @@ -251,26 +267,6 @@ inline bool QObjectPrivate::isDeclarativeSignalConnected(uint signal_index) cons && QAbstractDeclarativeData::isSignalConnected(declarativeData, q_func(), signal_index); } -inline QObjectPrivate::Sender *QObjectPrivate::setCurrentSender(QObject *receiver, - Sender *sender) -{ - Sender *previousSender = receiver->d_func()->currentSender; - receiver->d_func()->currentSender = sender; - return previousSender; -} - -inline void QObjectPrivate::resetCurrentSender(QObject *receiver, - Sender *currentSender, - Sender *previousSender) -{ - // ref is set to zero when this object is deleted during the metacall - if (currentSender->ref == 1) - receiver->d_func()->currentSender = previousSender; - // if we've recursed, we need to tell the caller about the objects deletion - if (previousSender) - previousSender->ref = currentSender->ref; -} - inline void QObjectPrivate::connectNotify(const QMetaMethod &signal) { q_ptr->connectNotify(signal); -- cgit v1.2.3 From 5cc6f90910082f35e3f5340493facbc8c175f65f Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Mon, 7 Jan 2019 15:05:06 +0100 Subject: Move all connection related data into one data structure Adn create that data structure on demand on the heap. This reduces the size of QObjectPrivate if there are no connections. If we have connections, it'll use the same amount of allocations and memory as before. Change-Id: I900f6980a2cd8a5f72c3ad18697b5dd49100217d Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/kernel/qobject.cpp | 376 +++++++++++++++++++---------------------- src/corelib/kernel/qobject_p.h | 47 +++++- 2 files changed, 213 insertions(+), 210 deletions(-) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index f7983f3251..b8e973a0a3 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -182,7 +182,7 @@ QMetaObject *QObjectData::dynamicMetaObject() const } QObjectPrivate::QObjectPrivate(int version) - : threadData(0), connectionLists(0), senders(0), currentSender(0), currentChildBeingDeleted(0) + : threadData(0), currentChildBeingDeleted(0) { #ifdef QT_BUILD_INTERNAL // Don't check the version parameter in internal builds. @@ -257,59 +257,22 @@ static void computeOffsets(const QMetaObject *metaobject, int *signalOffset, int } } -/* - This vector contains the all connections from an object. - - Each object may have one vector containing the lists of - connections for a given signal. The index in the vector correspond - to the signal index. The signal index is the one returned by - QObjectPrivate::signalIndex (not QMetaObject::indexOfSignal). - Negative index means connections to all signals. - - This vector is protected by the object mutex (signalSlotMutexes()) - - Each Connection is also part of a 'senders' linked list. The mutex - of the receiver must be locked when touching the pointers of this - linked list. -*/ -class QObjectConnectionListVector : public QVector -{ -public: - bool orphaned; //the QObject owner of this vector has been destroyed while the vector was inUse - bool dirty; //some Connection have been disconnected (their receiver is 0) but not removed from the list yet - int inUse; //number of functions that are currently accessing this object or its connections - QObjectPrivate::ConnectionList allsignals; - - QObjectConnectionListVector() - : QVector(), orphaned(false), dirty(false), inUse(0) - { } - - QObjectPrivate::ConnectionList &operator[](int at) - { - if (at < 0) - return allsignals; - return QVector::operator[](at); - } -}; - // Used by QAccessibleWidget bool QObjectPrivate::isSender(const QObject *receiver, const char *signal) const { Q_Q(const QObject); int signal_index = signalIndex(signal); - if (signal_index < 0) + ConnectionData *cd = connections.load(); + if (signal_index < 0 || !cd) return false; QMutexLocker locker(signalSlotLock(q)); - if (connectionLists) { - if (signal_index < connectionLists->count()) { - const QObjectPrivate::Connection *c = - connectionLists->at(signal_index).first; + if (signal_index < cd->signalVector.count()) { + const QObjectPrivate::Connection *c = cd->signalVector.at(signal_index).first; - while (c) { - if (c->receiver == receiver) - return true; - c = c->nextConnectionList; - } + while (c) { + if (c->receiver == receiver) + return true; + c = c->nextConnectionList; } } return false; @@ -321,18 +284,17 @@ QObjectList QObjectPrivate::receiverList(const char *signal) const Q_Q(const QObject); QObjectList returnValue; int signal_index = signalIndex(signal); - if (signal_index < 0) + ConnectionData *cd = connections.load(); + if (signal_index < 0 || !cd) return returnValue; QMutexLocker locker(signalSlotLock(q)); - if (connectionLists) { - if (signal_index < connectionLists->count()) { - const QObjectPrivate::Connection *c = connectionLists->at(signal_index).first; + if (signal_index < cd->signalVector.count()) { + const QObjectPrivate::Connection *c = cd->signalVector.at(signal_index).first; - while (c) { - if (c->receiver) - returnValue << c->receiver; - c = c->nextConnectionList; - } + while (c) { + if (c->receiver) + returnValue << c->receiver; + c = c->nextConnectionList; } } return returnValue; @@ -342,9 +304,12 @@ QObjectList QObjectPrivate::receiverList(const char *signal) const QObjectList QObjectPrivate::senderList() const { QObjectList returnValue; - QMutexLocker locker(signalSlotLock(q_func())); - for (Connection *c = senders; c; c = c->next) - returnValue << c->sender; + ConnectionData *cd = connections.load(); + if (cd) { + QMutexLocker locker(signalSlotLock(q_func())); + for (Connection *c = cd->senders; c; c = c->next) + returnValue << c->sender; + } return returnValue; } @@ -361,12 +326,12 @@ QObjectList QObjectPrivate::senderList() const void QObjectPrivate::addConnection(int signal, Connection *c) { Q_ASSERT(c->sender == q_ptr); - if (!connectionLists) - connectionLists = new QObjectConnectionListVector(); - if (signal >= connectionLists->count()) - connectionLists->resize(signal + 1); + ensureConnectionData(); + ConnectionData *cd = connections.load(); + if (signal >= cd->signalVector.count()) + cd->signalVector.resize(signal + 1); - ConnectionList &connectionList = (*connectionLists)[signal]; + ConnectionList &connectionList = cd->connectionsForSignal(signal); if (connectionList.last) { connectionList.last->nextConnectionList = c; } else { @@ -376,7 +341,10 @@ void QObjectPrivate::addConnection(int signal, Connection *c) cleanConnectionLists(); - c->prev = &(QObjectPrivate::get(c->receiver)->senders); + QObjectPrivate *rd = QObjectPrivate::get(c->receiver); + rd->ensureConnectionData(); + + c->prev = &(rd->connections.load()->senders); c->next = *c->prev; *c->prev = c; if (c->next) @@ -385,11 +353,11 @@ void QObjectPrivate::addConnection(int signal, Connection *c) void QObjectPrivate::cleanConnectionLists() { - if (connectionLists->dirty && !connectionLists->inUse) { + ConnectionData *cd = connections.load(); + if (cd->dirty && !cd->inUse) { // remove broken connections - for (int signal = -1; signal < connectionLists->count(); ++signal) { - QObjectPrivate::ConnectionList &connectionList = - (*connectionLists)[signal]; + for (int signal = -1; signal < cd->signalVector.count(); ++signal) { + ConnectionList &connectionList = cd->connectionsForSignal(signal); // Set to the last entry in the connection list that was *not* // deleted. This is needed to update the list's last pointer @@ -415,7 +383,7 @@ void QObjectPrivate::cleanConnectionLists() // As conectionList.last could equal last, this could be a noop connectionList.last = last; } - connectionLists->dirty = false; + cd->dirty = false; } } @@ -430,14 +398,15 @@ bool QObjectPrivate::isSignalConnected(uint signalIndex, bool checkDeclarative) if (checkDeclarative && isDeclarativeSignalConnected(signalIndex)) return true; - if (!connectionLists) + ConnectionData *cd = connections.load(); + if (!cd) return false; - if (connectionLists->allsignals.first) + if (cd->allsignals.first) return true; - if (signalIndex < uint(connectionLists->count())) { - const QObjectPrivate::Connection *c = connectionLists->at(signalIndex).first; + if (signalIndex < uint(cd->signalVector.count())) { + const QObjectPrivate::Connection *c = cd->signalVector.at(signalIndex).first; while (c) { if (c->receiver) return true; @@ -905,60 +874,51 @@ QObject::~QObject() } } - if (d->currentSender) { - d->currentSender->receiverDeleted(); - d->currentSender = nullptr; - } + QObjectPrivate::ConnectionData *cd = d->connections.load(); + if (cd) { + if (cd->currentSender) { + cd->currentSender->receiverDeleted(); + cd->currentSender = nullptr; + } - if (d->connectionLists || d->senders) { QMutex *signalSlotMutex = signalSlotLock(this); QMutexLocker locker(signalSlotMutex); + ++cd->inUse; // disconnect all receivers - if (d->connectionLists) { - ++d->connectionLists->inUse; - int connectionListsCount = d->connectionLists->count(); - for (int signal = -1; signal < connectionListsCount; ++signal) { - QObjectPrivate::ConnectionList &connectionList = - (*d->connectionLists)[signal]; - - while (QObjectPrivate::Connection *c = connectionList.first) { - if (!c->receiver) { - connectionList.first = c->nextConnectionList; - c->deref(); - continue; - } - - QMutex *m = signalSlotLock(c->receiver); - bool needToUnlock = QOrderedMutexLocker::relock(signalSlotMutex, m); - - if (c->receiver) { - *c->prev = c->next; - if (c->next) c->next->prev = c->prev; - } - c->receiver = 0; - if (needToUnlock) - m->unlock(); + int receiverCount = cd->signalVector.count(); + for (int signal = -1; signal < receiverCount; ++signal) { + QObjectPrivate::ConnectionList &connectionList = cd->connectionsForSignal(signal); + while (QObjectPrivate::Connection *c = connectionList.first) { + if (!c->receiver) { connectionList.first = c->nextConnectionList; - - // The destroy operation must happen outside the lock - if (c->isSlotObject) { - c->isSlotObject = false; - locker.unlock(); - c->slotObj->destroyIfLastRef(); - locker.relock(); - } c->deref(); + continue; } - } - if (!--d->connectionLists->inUse) { - delete d->connectionLists; - } else { - d->connectionLists->orphaned = true; + QMutex *m = signalSlotLock(c->receiver); + bool needToUnlock = QOrderedMutexLocker::relock(signalSlotMutex, m); + + if (c->receiver) { + *c->prev = c->next; + if (c->next) c->next->prev = c->prev; + } + c->receiver = 0; + if (needToUnlock) + m->unlock(); + + connectionList.first = c->nextConnectionList; + + // The destroy operation must happen outside the lock + if (c->isSlotObject) { + c->isSlotObject = false; + locker.unlock(); + c->slotObj->destroyIfLastRef(); + locker.relock(); + } + c->deref(); } - d->connectionLists = 0; } /* Disconnect all senders: @@ -970,8 +930,9 @@ QObject::~QObject() * thread. That's why we set node->prev to &node, that way, if node is destroyed, node will * be updated. */ - QObjectPrivate::Connection *node = d->senders; + QObjectPrivate::Connection *node = cd->senders; while (node) { + Q_ASSERT(node->receiver); QObject *sender = node->sender; // Send disconnectNotify before removing the connection from sender's connection list. // This ensures any eventual destructor of sender will block on getting receiver's lock @@ -988,9 +949,9 @@ QObject::~QObject() continue; } node->receiver = 0; - QObjectConnectionListVector *senderLists = sender->d_func()->connectionLists; - if (senderLists) - senderLists->dirty = true; + QObjectPrivate::ConnectionData *senderData = sender->d_func()->connections; + if (senderData) + senderData->dirty = true; QtPrivate::QSlotObjectBase *slotObj = nullptr; if (node->isSlotObject) { @@ -1010,6 +971,13 @@ QObject::~QObject() locker.relock(); } } + + if (!--cd->inUse) { + delete cd; + } else { + cd->orphaned = true; + } + d->connections.store(nullptr); } if (!d->children.isEmpty()) @@ -1239,6 +1207,10 @@ bool QObject::event(QEvent *e) { QMetaCallEvent *mce = static_cast(e); + if (!d_func()->connections.load()) { + QMutexLocker locker(signalSlotLock(this)); + d_func()->ensureConnectionData(); + } QObjectPrivate::Sender sender(this, const_cast(mce->sender()), mce->signalId()); mce->placeMetaCall(this); @@ -1543,9 +1515,10 @@ void QObjectPrivate::setThreadData_helper(QThreadData *currentData, QThreadData } // the current emitting thread shouldn't restore currentSender after calling moveToThread() - if (currentSender) { - currentSender->receiverDeleted(); - currentSender = nullptr; + ConnectionData *cd = connections.load(); + if (cd && cd->currentSender) { + cd->currentSender->receiverDeleted(); + cd->currentSender = nullptr; } // set new thread data @@ -2354,12 +2327,13 @@ QObject *QObject::sender() const Q_D(const QObject); QMutexLocker locker(signalSlotLock(this)); - if (!d->currentSender) - return 0; + QObjectPrivate::ConnectionData *cd = d->connections.load(); + if (!cd || !cd->currentSender) + return nullptr; - for (QObjectPrivate::Connection *c = d->senders; c; c = c->next) { - if (c->sender == d->currentSender->sender) - return d->currentSender->sender; + for (QObjectPrivate::Connection *c = cd->senders; c; c = c->next) { + if (c->sender == cd->currentSender->sender) + return cd->currentSender->sender; } return 0; @@ -2395,13 +2369,14 @@ int QObject::senderSignalIndex() const Q_D(const QObject); QMutexLocker locker(signalSlotLock(this)); - if (!d->currentSender) + QObjectPrivate::ConnectionData *cd = d->connections.load(); + if (!cd || !cd->currentSender) return -1; - for (QObjectPrivate::Connection *c = d->senders; c; c = c->next) { - if (c->sender == d->currentSender->sender) { + for (QObjectPrivate::Connection *c = cd->senders; c; c = c->next) { + if (c->sender == cd->currentSender->sender) { // Convert from signal range to method range - return QMetaObjectPrivate::signal(c->sender->metaObject(), d->currentSender->signal).methodIndex(); + return QMetaObjectPrivate::signal(c->sender->metaObject(), cd->currentSender->signal).methodIndex(); } } @@ -2433,7 +2408,8 @@ int QObject::receivers(const char *signal) const { Q_D(const QObject); int receivers = 0; - if (signal) { + QObjectPrivate::ConnectionData *cd = d->connections.load(); + if (signal && cd) { QByteArray signal_name = QMetaObject::normalizedSignature(signal); signal = signal_name; #ifndef QT_NO_DEBUG @@ -2458,14 +2434,12 @@ int QObject::receivers(const char *signal) const } QMutexLocker locker(signalSlotLock(this)); - if (d->connectionLists) { - if (signal_index < d->connectionLists->count()) { - const QObjectPrivate::Connection *c = - d->connectionLists->at(signal_index).first; - while (c) { - receivers += c->receiver ? 1 : 0; - c = c->nextConnectionList; - } + if (signal_index < cd->signalVector.count()) { + const QObjectPrivate::Connection *c = + cd->signalVector.at(signal_index).first; + while (c) { + receivers += c->receiver ? 1 : 0; + c = c->nextConnectionList; } } } @@ -3269,23 +3243,21 @@ QObjectPrivate::Connection *QMetaObjectPrivate::connect(const QObject *sender, int method_offset = rmeta ? rmeta->methodOffset() : 0; Q_ASSERT(!rmeta || QMetaObjectPrivate::get(rmeta)->revision >= 6); - QObjectPrivate::StaticMetaCallFunction callFunction = - rmeta ? rmeta->d.static_metacall : 0; + QObjectPrivate::StaticMetaCallFunction callFunction = rmeta ? rmeta->d.static_metacall : nullptr; QOrderedMutexLocker locker(signalSlotLock(sender), signalSlotLock(receiver)); - if (type & Qt::UniqueConnection) { - QObjectConnectionListVector *connectionLists = QObjectPrivate::get(s)->connectionLists; - if (connectionLists && connectionLists->count() > signal_index) { - const QObjectPrivate::Connection *c2 = - (*connectionLists)[signal_index].first; + QObjectPrivate::ConnectionData *scd = QObjectPrivate::get(s)->connections.load(); + if (type & Qt::UniqueConnection && scd) { + if (scd->signalVector.count() > signal_index) { + const QObjectPrivate::Connection *c2 = scd->signalVector.at(signal_index).first; int method_index_absolute = method_index + method_offset; while (c2) { if (!c2->isSlotObject && c2->receiver == receiver && c2->method() == method_index_absolute) - return 0; + return nullptr; c2 = c2->nextConnectionList; } } @@ -3409,37 +3381,35 @@ bool QMetaObjectPrivate::disconnect(const QObject *sender, QMutex *senderMutex = signalSlotLock(sender); QMutexLocker locker(senderMutex); - QObjectConnectionListVector *connectionLists = QObjectPrivate::get(s)->connectionLists; - if (!connectionLists) + QObjectPrivate::ConnectionData *scd = QObjectPrivate::get(s)->connections.load(); + if (!scd) return false; - // prevent incoming connections changing the connectionLists while unlocked - ++connectionLists->inUse; + // prevent incoming connections changing the connections->receivers while unlocked + ++scd->inUse; bool success = false; if (signal_index < 0) { // remove from all connection lists - for (int sig_index = -1; sig_index < connectionLists->count(); ++sig_index) { - QObjectPrivate::Connection *c = - (*connectionLists)[sig_index].first; + for (int sig_index = -1; sig_index < scd->signalVector.count(); ++sig_index) { + QObjectPrivate::Connection *c = scd->connectionsForSignal(sig_index).first; if (disconnectHelper(c, receiver, method_index, slot, senderMutex, disconnectType)) { success = true; - connectionLists->dirty = true; + scd->dirty = true; } } - } else if (signal_index < connectionLists->count()) { - QObjectPrivate::Connection *c = - (*connectionLists)[signal_index].first; + } else if (signal_index < scd->signalVector.count()) { + QObjectPrivate::Connection *c = scd->signalVector.at(signal_index).first; if (disconnectHelper(c, receiver, method_index, slot, senderMutex, disconnectType)) { success = true; - connectionLists->dirty = true; + scd->dirty = true; } } - --connectionLists->inUse; - Q_ASSERT(connectionLists->inUse >= 0); - if (connectionLists->orphaned && !connectionLists->inUse) - delete connectionLists; + --scd->inUse; + Q_ASSERT(scd->inUse >= 0); + if (scd->orphaned && !scd->inUse) + delete scd; locker.unlock(); if (success) { @@ -3651,35 +3621,36 @@ void doActivate(QObject *sender, int signal_index, void **argv) { QMutexLocker locker(signalSlotLock(sender)); - struct ConnectionListsRef { - QObjectConnectionListVector *connectionLists; - ConnectionListsRef(QObjectConnectionListVector *connectionLists) : connectionLists(connectionLists) + struct ConnectionDataRef { + QObjectPrivate::ConnectionData *connections; + ConnectionDataRef(QObjectPrivate::ConnectionData *connections) : connections(connections) { - if (connectionLists) - ++connectionLists->inUse; + if (connections) + ++connections->inUse; } - ~ConnectionListsRef() + ~ConnectionDataRef() { - if (!connectionLists) + if (!connections) return; - --connectionLists->inUse; - Q_ASSERT(connectionLists->inUse >= 0); - if (connectionLists->orphaned) { - if (!connectionLists->inUse) - delete connectionLists; + --connections->inUse; + Q_ASSERT(connections->inUse >= 0); + if (connections->orphaned) { + if (!connections->inUse) + delete connections; } } - QObjectConnectionListVector *operator->() const { return connectionLists; } + QObjectPrivate::ConnectionData *operator->() const { return connections; } }; - ConnectionListsRef connectionLists = sp->connectionLists; + Q_ASSERT(sp->connections.load()); + ConnectionDataRef connections = sp->connections.load(); const QObjectPrivate::ConnectionList *list; - if (signal_index < connectionLists->count()) - list = &connectionLists->at(signal_index); + if (signal_index < connections->signalVector.count()) + list = &connections->signalVector.at(signal_index); else - list = &connectionLists->allsignals; + list = &connections->allsignals; Qt::HANDLE currentThreadId = QThread::currentThreadId(); @@ -3773,15 +3744,15 @@ void doActivate(QObject *sender, int signal_index, void **argv) locker.relock(); } - if (connectionLists->orphaned) + if (connections->orphaned) break; } while (c != last && (c = c->nextConnectionList) != 0); - if (connectionLists->orphaned) + if (connections->orphaned) break; - } while (list != &connectionLists->allsignals && + } while (list != &connections->allsignals && //start over for all signals; - ((list = &connectionLists->allsignals), true)); + ((list = &connections->allsignals), true)); } @@ -3832,7 +3803,7 @@ void QMetaObject::activate(QObject *sender, int signal_index, void **argv) /*! \internal - Returns the signal index used in the internal connectionLists vector. + Returns the signal index used in the internal connections->receivers vector. It is different from QMetaObject::indexOfSignal(): indexOfSignal is the same as indexOfMethod while QObjectPrivate::signalIndex is smaller because it doesn't give index to slots. @@ -4077,14 +4048,14 @@ void QObject::dumpObjectInfo() const // first, look for connections where this object is the sender qDebug(" SIGNALS OUT"); - if (d->connectionLists) { - for (int signal_index = 0; signal_index < d->connectionLists->count(); ++signal_index) { + QObjectPrivate::ConnectionData *cd = d->connections.load(); + if (cd && cd->signalVector.count()) { + for (int signal_index = 0; signal_index < cd->signalVector.count(); ++signal_index) { const QMetaMethod signal = QMetaObjectPrivate::signal(metaObject(), signal_index); qDebug(" signal: %s", signal.methodSignature().constData()); // receivers - const QObjectPrivate::Connection *c = - d->connectionLists->at(signal_index).first; + const QObjectPrivate::Connection *c = cd->signalVector.at(signal_index).first; while (c) { if (!c->receiver) { qDebug(" "); @@ -4112,8 +4083,8 @@ void QObject::dumpObjectInfo() const // now look for connections where this object is the receiver qDebug(" SIGNALS IN"); - if (d->senders) { - for (QObjectPrivate::Connection *s = d->senders; s; s = s->next) { + if (cd && cd->senders) { + for (QObjectPrivate::Connection *s = cd->senders; s; s = s->next) { QByteArray slotName = QByteArrayLiteral(""); if (!s->isSlotObject) { const QMetaMethod slot = metaObject()->method(s->method()); @@ -4848,11 +4819,10 @@ QMetaObject::Connection QObjectPrivate::connectImpl(const QObject *sender, int s QOrderedMutexLocker locker(signalSlotLock(sender), signalSlotLock(receiver)); - if (type & Qt::UniqueConnection && slot) { - QObjectConnectionListVector *connectionLists = QObjectPrivate::get(s)->connectionLists; - if (connectionLists && connectionLists->count() > signal_index) { - const QObjectPrivate::Connection *c2 = - (*connectionLists)[signal_index].first; + if (type & Qt::UniqueConnection && slot && QObjectPrivate::get(s)->connections.load()) { + QObjectPrivate::ConnectionData *connections = QObjectPrivate::get(s)->connections.load(); + if (connections->signalVector.count() > signal_index) { + const QObjectPrivate::Connection *c2 = connections->signalVector.at(signal_index).first; while (c2) { if (c2->receiver == receiver && c2->isSlotObject && c2->slotObj->compare(slot)) { @@ -4909,14 +4879,14 @@ bool QObject::disconnect(const QMetaObject::Connection &connection) { QOrderedMutexLocker locker(senderMutex, receiverMutex); - QObjectConnectionListVector *connectionLists = QObjectPrivate::get(c->sender)->connectionLists; - Q_ASSERT(connectionLists); - connectionLists->dirty = true; + QObjectPrivate::ConnectionData *connections = QObjectPrivate::get(c->sender)->connections.load(); + Q_ASSERT(connections); + connections->dirty = true; *c->prev = c->next; if (c->next) c->next->prev = c->prev; - c->receiver = 0; + c->receiver = nullptr; } // destroy the QSlotObject, if possible @@ -4928,7 +4898,7 @@ bool QObject::disconnect(const QMetaObject::Connection &connection) c->sender->disconnectNotify(QMetaObjectPrivate::signal(c->sender->metaObject(), c->signal_index)); - const_cast(connection).d_ptr = 0; + const_cast(connection).d_ptr = nullptr; c->deref(); // has been removed from the QMetaObject::Connection object return true; diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h index ab20064c65..64998797ac 100644 --- a/src/corelib/kernel/qobject_p.h +++ b/src/corelib/kernel/qobject_p.h @@ -171,14 +171,15 @@ public: : receiver(receiver), sender(sender), signal(signal) { if (receiver) { - previous = receiver->d_func()->currentSender; - receiver->d_func()->currentSender = this; + ConnectionData *cd = receiver->d_func()->connections.load(); + previous = cd->currentSender; + cd->currentSender = this; } } ~Sender() { if (receiver) - receiver->d_func()->currentSender = previous; + receiver->d_func()->connections.load()->currentSender = previous; } void receiverDeleted() { @@ -194,6 +195,34 @@ public: int signal; }; + /* + This contains the all connections from and to an object. + + The signalVector contains the lists of connections for a given signal. The index in the vector correspond + to the signal index. The signal index is the one returned by QObjectPrivate::signalIndex (not + QMetaObject::indexOfSignal). allsignals contains a list of special connections that will get invoked on + any signal emission. This is done by connecting to signal index -1. + + This vector is protected by the object mutex (signalSlotLock()) + + Each Connection is also part of a 'senders' linked list. This one contains all connections connected + to a slot in this object. The mutex of the receiver must be locked when touching the pointers of this + linked list. + */ + struct ConnectionData { + bool orphaned = false; //the QObject owner of this vector has been destroyed while the vector was inUse + bool dirty = false; //some Connection have been disconnected (their receiver is 0) but not removed from the list yet + int inUse = 0; //number of functions that are currently accessing this object or its connections + ConnectionList allsignals; + QVector signalVector; + Connection *senders = nullptr; + Sender *currentSender = nullptr; // object currently activating the object + + ConnectionList &connectionsForSignal(int signal) + { + return signal < 0 ? allsignals : signalVector[signal]; + } + }; QObjectPrivate(int version = QObjectPrivateVersion); virtual ~QObjectPrivate(); @@ -240,14 +269,18 @@ public: const int *types, const QMetaObject *senderMetaObject); static QMetaObject::Connection connect(const QObject *sender, int signal_index, QtPrivate::QSlotObjectBase *slotObj, Qt::ConnectionType type); static bool disconnect(const QObject *sender, int signal_index, void **slot); + + void ensureConnectionData() + { + if (connections.load()) + return; + connections.store(new ConnectionData); + } public: ExtraData *extraData; // extra data set by the user QThreadData *threadData; // id of the thread that owns the object - QObjectConnectionListVector *connectionLists; - - Connection *senders; // linked list of connections connected to this object - Sender *currentSender; // object currently activating the object + QAtomicPointer connections; union { QObject *currentChildBeingDeleted; // should only be used when QObjectData::isDeletingChildren is set -- cgit v1.2.3 From 0e534bf8b704b8ae24b87a9b1dcb5cd829c9dd2f Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Wed, 9 Jan 2019 09:48:59 +0100 Subject: Replace the ConnectionData::inUse int with a proper refcount The main difference is that QObject itself also holds on reference on the structure. Also rename the orphaned flag to objectDeleted for clarity. Change-Id: Ief9b9ff9c8b9cc3630dcfd29806ed24cd07150e4 Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/kernel/qobject.cpp | 78 ++++++++++++++---------------------------- src/corelib/kernel/qobject_p.h | 16 +++++++-- 2 files changed, 38 insertions(+), 56 deletions(-) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index b8e973a0a3..c3271b2c35 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -354,7 +354,7 @@ void QObjectPrivate::addConnection(int signal, Connection *c) void QObjectPrivate::cleanConnectionLists() { ConnectionData *cd = connections.load(); - if (cd->dirty && !cd->inUse) { + if (cd->dirty && cd->ref == 1) { // remove broken connections for (int signal = -1; signal < cd->signalVector.count(); ++signal) { ConnectionList &connectionList = cd->connectionsForSignal(signal); @@ -883,7 +883,6 @@ QObject::~QObject() QMutex *signalSlotMutex = signalSlotLock(this); QMutexLocker locker(signalSlotMutex); - ++cd->inUse; // disconnect all receivers int receiverCount = cd->signalVector.count(); @@ -949,7 +948,7 @@ QObject::~QObject() continue; } node->receiver = 0; - QObjectPrivate::ConnectionData *senderData = sender->d_func()->connections; + QObjectPrivate::ConnectionData *senderData = sender->d_func()->connections.load(); if (senderData) senderData->dirty = true; @@ -972,13 +971,11 @@ QObject::~QObject() } } - if (!--cd->inUse) { - delete cd; - } else { - cd->orphaned = true; - } - d->connections.store(nullptr); + cd->objectDeleted = true; } + if (cd && !cd->ref.deref()) + delete cd; + d->connections.store(nullptr); if (!d->children.isEmpty()) d->deleteChildren(); @@ -3385,32 +3382,29 @@ bool QMetaObjectPrivate::disconnect(const QObject *sender, if (!scd) return false; - // prevent incoming connections changing the connections->receivers while unlocked - ++scd->inUse; - bool success = false; - if (signal_index < 0) { - // remove from all connection lists - for (int sig_index = -1; sig_index < scd->signalVector.count(); ++sig_index) { - QObjectPrivate::Connection *c = scd->connectionsForSignal(sig_index).first; + { + // prevent incoming connections changing the connections->receivers while unlocked + QObjectPrivate::ConnectionDataPointer connections(scd); + + if (signal_index < 0) { + // remove from all connection lists + for (int sig_index = -1; sig_index < scd->signalVector.count(); ++sig_index) { + QObjectPrivate::Connection *c = scd->connectionsForSignal(sig_index).first; + if (disconnectHelper(c, receiver, method_index, slot, senderMutex, disconnectType)) { + success = true; + scd->dirty = true; + } + } + } else if (signal_index < scd->signalVector.count()) { + QObjectPrivate::Connection *c = scd->signalVector.at(signal_index).first; if (disconnectHelper(c, receiver, method_index, slot, senderMutex, disconnectType)) { success = true; scd->dirty = true; } } - } else if (signal_index < scd->signalVector.count()) { - QObjectPrivate::Connection *c = scd->signalVector.at(signal_index).first; - if (disconnectHelper(c, receiver, method_index, slot, senderMutex, disconnectType)) { - success = true; - scd->dirty = true; - } } - --scd->inUse; - Q_ASSERT(scd->inUse >= 0); - if (scd->orphaned && !scd->inUse) - delete scd; - locker.unlock(); if (success) { QMetaMethod smethod = QMetaObjectPrivate::signal(smeta, signal_index); @@ -3621,30 +3615,8 @@ void doActivate(QObject *sender, int signal_index, void **argv) { QMutexLocker locker(signalSlotLock(sender)); - struct ConnectionDataRef { - QObjectPrivate::ConnectionData *connections; - ConnectionDataRef(QObjectPrivate::ConnectionData *connections) : connections(connections) - { - if (connections) - ++connections->inUse; - } - ~ConnectionDataRef() - { - if (!connections) - return; - - --connections->inUse; - Q_ASSERT(connections->inUse >= 0); - if (connections->orphaned) { - if (!connections->inUse) - delete connections; - } - } - - QObjectPrivate::ConnectionData *operator->() const { return connections; } - }; - Q_ASSERT(sp->connections.load()); - ConnectionDataRef connections = sp->connections.load(); + Q_ASSERT(sp->connections); + QObjectPrivate::ConnectionDataPointer connections(sp->connections.load()); const QObjectPrivate::ConnectionList *list; if (signal_index < connections->signalVector.count()) @@ -3744,11 +3716,11 @@ void doActivate(QObject *sender, int signal_index, void **argv) locker.relock(); } - if (connections->orphaned) + if (connections->objectDeleted) break; } while (c != last && (c = c->nextConnectionList) != 0); - if (connections->orphaned) + if (connections->objectDeleted) break; } while (list != &connections->allsignals && //start over for all signals; diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h index 64998797ac..823c7a195a 100644 --- a/src/corelib/kernel/qobject_p.h +++ b/src/corelib/kernel/qobject_p.h @@ -210,9 +210,16 @@ public: linked list. */ struct ConnectionData { - bool orphaned = false; //the QObject owner of this vector has been destroyed while the vector was inUse + bool objectDeleted = false; //the QObject owner of this vector has been destroyed while the vector was inUse + struct Ref { + int _ref = 0; + void ref() { ++_ref; } + int deref() { return --_ref; } + operator int() const { return _ref; } + }; + + Ref ref; bool dirty = false; //some Connection have been disconnected (their receiver is 0) but not removed from the list yet - int inUse = 0; //number of functions that are currently accessing this object or its connections ConnectionList allsignals; QVector signalVector; Connection *senders = nullptr; @@ -274,12 +281,15 @@ public: { if (connections.load()) return; - connections.store(new ConnectionData); + ConnectionData *cd = new ConnectionData; + cd->ref.ref(); + connections.store(cd); } public: ExtraData *extraData; // extra data set by the user QThreadData *threadData; // id of the thread that owns the object + using ConnectionDataPointer = QExplicitlySharedDataPointer; QAtomicPointer connections; union { -- cgit v1.2.3 From aea500d5d76864bb1a3918e338ca6806e1766e41 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Wed, 9 Jan 2019 11:00:01 +0100 Subject: Use QBasicMutex instead of QMutex in the signalSlockLock() Add a simple private QBasicMutexLocker class, and let the QOrderedMutexLocker operate on a QBasicMutex. This allows the compiler to inline more things when handling connections and speeds up activate() a bit more. without change with change string based connect: 3621 3368 pointer based connect: 4341 3919 not connected: 433 437 disconnected: 551 538 Change-Id: If979337891178aaeb0b3340b6d4f68b6f86b0260 Reviewed-by: Qt CI Bot Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/kernel/qmetaobject_p.h | 4 ++-- src/corelib/kernel/qobject.cpp | 47 +++++++++++++++++++------------------- 2 files changed, 25 insertions(+), 26 deletions(-) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qmetaobject_p.h b/src/corelib/kernel/qmetaobject_p.h index 522bd78e42..5b412b5140 100644 --- a/src/corelib/kernel/qmetaobject_p.h +++ b/src/corelib/kernel/qmetaobject_p.h @@ -54,6 +54,7 @@ #include #include +#include #ifndef QT_NO_QOBJECT #include // For QObjectPrivate::Connection #endif @@ -168,7 +169,6 @@ Q_DECLARE_TYPEINFO(QArgumentType, Q_MOVABLE_TYPE); typedef QVarLengthArray QArgumentTypeArray; class QMetaMethodPrivate; -class QMutex; struct QMetaObjectPrivate { @@ -234,7 +234,7 @@ struct QMetaObjectPrivate DisconnectType = DisconnectAll); static inline bool disconnectHelper(QObjectPrivate::Connection *c, const QObject *receiver, int method_index, void **slot, - QMutex *senderMutex, DisconnectType = DisconnectAll); + QBasicMutex *senderMutex, DisconnectType = DisconnectAll); #endif }; diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index c3271b2c35..3db43ba1c4 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -152,10 +152,9 @@ static QBasicMutex _q_ObjectMutexPool[131]; * \internal * mutex to be locked when accessing the connectionlists or the senders list */ -static inline QMutex *signalSlotLock(const QObject *o) +static inline QBasicMutex *signalSlotLock(const QObject *o) { - return static_cast(&_q_ObjectMutexPool[ - uint(quintptr(o)) % sizeof(_q_ObjectMutexPool)/sizeof(QBasicMutex)]); + return &_q_ObjectMutexPool[uint(quintptr(o)) % sizeof(_q_ObjectMutexPool)/sizeof(QBasicMutex)]; } #if QT_VERSION < 0x60000 @@ -265,7 +264,7 @@ bool QObjectPrivate::isSender(const QObject *receiver, const char *signal) const ConnectionData *cd = connections.load(); if (signal_index < 0 || !cd) return false; - QMutexLocker locker(signalSlotLock(q)); + QBasicMutexLocker locker(signalSlotLock(q)); if (signal_index < cd->signalVector.count()) { const QObjectPrivate::Connection *c = cd->signalVector.at(signal_index).first; @@ -287,7 +286,7 @@ QObjectList QObjectPrivate::receiverList(const char *signal) const ConnectionData *cd = connections.load(); if (signal_index < 0 || !cd) return returnValue; - QMutexLocker locker(signalSlotLock(q)); + QBasicMutexLocker locker(signalSlotLock(q)); if (signal_index < cd->signalVector.count()) { const QObjectPrivate::Connection *c = cd->signalVector.at(signal_index).first; @@ -306,7 +305,7 @@ QObjectList QObjectPrivate::senderList() const QObjectList returnValue; ConnectionData *cd = connections.load(); if (cd) { - QMutexLocker locker(signalSlotLock(q_func())); + QBasicMutexLocker locker(signalSlotLock(q_func())); for (Connection *c = cd->senders; c; c = c->next) returnValue << c->sender; } @@ -881,8 +880,8 @@ QObject::~QObject() cd->currentSender = nullptr; } - QMutex *signalSlotMutex = signalSlotLock(this); - QMutexLocker locker(signalSlotMutex); + QBasicMutex *signalSlotMutex = signalSlotLock(this); + QBasicMutexLocker locker(signalSlotMutex); // disconnect all receivers int receiverCount = cd->signalVector.count(); @@ -896,7 +895,7 @@ QObject::~QObject() continue; } - QMutex *m = signalSlotLock(c->receiver); + QBasicMutex *m = signalSlotLock(c->receiver); bool needToUnlock = QOrderedMutexLocker::relock(signalSlotMutex, m); if (c->receiver) { @@ -937,7 +936,7 @@ QObject::~QObject() // This ensures any eventual destructor of sender will block on getting receiver's lock // and not finish until we release it. sender->disconnectNotify(QMetaObjectPrivate::signal(sender->metaObject(), node->signal_index)); - QMutex *m = signalSlotLock(sender); + QBasicMutex *m = signalSlotLock(sender); node->prev = &node; bool needToUnlock = QOrderedMutexLocker::relock(signalSlotMutex, m); //the node has maybe been removed while the mutex was unlocked in relock? @@ -1205,7 +1204,7 @@ bool QObject::event(QEvent *e) QMetaCallEvent *mce = static_cast(e); if (!d_func()->connections.load()) { - QMutexLocker locker(signalSlotLock(this)); + QBasicMutexLocker locker(signalSlotLock(this)); d_func()->ensureConnectionData(); } QObjectPrivate::Sender sender(this, const_cast(mce->sender()), mce->signalId()); @@ -2323,7 +2322,7 @@ QObject *QObject::sender() const { Q_D(const QObject); - QMutexLocker locker(signalSlotLock(this)); + QBasicMutexLocker locker(signalSlotLock(this)); QObjectPrivate::ConnectionData *cd = d->connections.load(); if (!cd || !cd->currentSender) return nullptr; @@ -2365,7 +2364,7 @@ int QObject::senderSignalIndex() const { Q_D(const QObject); - QMutexLocker locker(signalSlotLock(this)); + QBasicMutexLocker locker(signalSlotLock(this)); QObjectPrivate::ConnectionData *cd = d->connections.load(); if (!cd || !cd->currentSender) return -1; @@ -2430,7 +2429,7 @@ int QObject::receivers(const char *signal) const signal_index); } - QMutexLocker locker(signalSlotLock(this)); + QBasicMutexLocker locker(signalSlotLock(this)); if (signal_index < cd->signalVector.count()) { const QObjectPrivate::Connection *c = cd->signalVector.at(signal_index).first; @@ -2476,7 +2475,7 @@ bool QObject::isSignalConnected(const QMetaMethod &signal) const signalIndex += QMetaObjectPrivate::signalOffset(signal.mobj); - QMutexLocker locker(signalSlotLock(this)); + QBasicMutexLocker locker(signalSlotLock(this)); return d->isSignalConnected(signalIndex, true); } @@ -3318,7 +3317,7 @@ bool QMetaObject::disconnectOne(const QObject *sender, int signal_index, */ bool QMetaObjectPrivate::disconnectHelper(QObjectPrivate::Connection *c, const QObject *receiver, int method_index, void **slot, - QMutex *senderMutex, DisconnectType disconnectType) + QBasicMutex *senderMutex, DisconnectType disconnectType) { bool success = false; while (c) { @@ -3327,7 +3326,7 @@ bool QMetaObjectPrivate::disconnectHelper(QObjectPrivate::Connection *c, && (method_index < 0 || (!c->isSlotObject && c->method() == method_index)) && (slot == 0 || (c->isSlotObject && c->slotObj->compare(slot)))))) { bool needToUnlock = false; - QMutex *receiverMutex = 0; + QBasicMutex *receiverMutex = nullptr; if (c->receiver) { receiverMutex = signalSlotLock(c->receiver); // need to relock this receiver and sender in the correct order @@ -3375,8 +3374,8 @@ bool QMetaObjectPrivate::disconnect(const QObject *sender, QObject *s = const_cast(sender); - QMutex *senderMutex = signalSlotLock(sender); - QMutexLocker locker(senderMutex); + QBasicMutex *senderMutex = signalSlotLock(sender); + QBasicMutexLocker locker(senderMutex); QObjectPrivate::ConnectionData *scd = QObjectPrivate::get(s)->connections.load(); if (!scd) @@ -3523,7 +3522,7 @@ void QMetaObject::connectSlotsByName(QObject *o) \a signal must be in the signal index range (see QObjectPrivate::signalIndex()). */ static void queued_activate(QObject *sender, int signal, QObjectPrivate::Connection *c, void **argv, - QMutexLocker &locker) + QBasicMutexLocker &locker) { const int *argumentTypes = c->argumentTypes.load(); if (!argumentTypes) { @@ -3614,7 +3613,7 @@ void doActivate(QObject *sender, int signal_index, void **argv) Q_TRACE(QMetaObject_activate_begin_signal, sender, signal_index); { - QMutexLocker locker(signalSlotLock(sender)); + QBasicMutexLocker locker(signalSlotLock(sender)); Q_ASSERT(sp->connections); QObjectPrivate::ConnectionDataPointer connections(sp->connections.load()); @@ -4015,7 +4014,7 @@ void QObject::dumpObjectInfo() const objectName().isEmpty() ? "unnamed" : objectName().toLocal8Bit().data()); Q_D(const QObject); - QMutexLocker locker(signalSlotLock(this)); + QBasicMutexLocker locker(signalSlotLock(this)); // first, look for connections where this object is the sender qDebug(" SIGNALS OUT"); @@ -4845,8 +4844,8 @@ bool QObject::disconnect(const QMetaObject::Connection &connection) if (!c || !c->receiver) return false; - QMutex *senderMutex = signalSlotLock(c->sender); - QMutex *receiverMutex = signalSlotLock(c->receiver); + QBasicMutex *senderMutex = signalSlotLock(c->sender); + QBasicMutex *receiverMutex = signalSlotLock(c->receiver); { QOrderedMutexLocker locker(senderMutex, receiverMutex); -- cgit v1.2.3 From 568bc974d7d89f8d12bc4877c59e4291fe582e8b Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Mon, 11 Feb 2019 12:18:35 +0100 Subject: Remove eval mode The evaluation mode of Qt hasn't been used since quite some time. Let's just remove the remaining logic from the code base. Change-Id: I61a2c432cbae78bf973f882848b3732e27431351 Reviewed-by: Joerg Bornemann Reviewed-by: Iikka Eklund Reviewed-by: Thiago Macieira --- src/corelib/kernel/qcoreapplication.cpp | 5 - src/corelib/kernel/qtcore_eval.cpp | 560 -------------------------------- 2 files changed, 565 deletions(-) delete mode 100644 src/corelib/kernel/qtcore_eval.cpp (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index e6d1d26f3c..7524d2e6c4 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -857,11 +857,6 @@ void QCoreApplicationPrivate::init() eventDispatcherReady(); #endif -#ifdef QT_EVAL - extern void qt_core_eval_init(QCoreApplicationPrivate::Type); - qt_core_eval_init(application_type); -#endif - processCommandLineArguments(); qt_call_pre_routines(); diff --git a/src/corelib/kernel/qtcore_eval.cpp b/src/corelib/kernel/qtcore_eval.cpp deleted file mode 100644 index 5437210699..0000000000 --- a/src/corelib/kernel/qtcore_eval.cpp +++ /dev/null @@ -1,560 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include -#include -#include -#include -#include -#include - -#include "stdio.h" -#include "stdlib.h" - -QT_BEGIN_NAMESPACE - -#include "qconfig_eval.cpp" - -static const char boilerplate_supported_but_time_limited[] = - "\nQt %1 Evaluation License\n" - "Copyright (C) 2016 The Qt Company Ltd.\n" - "This trial version may only be used for evaluation purposes\n" - "and will shut down after 120 minutes.\n" - "Registered to:\n" - " Licensee: %2\n\n" - "The evaluation expires in %4 days\n\n" - "Contact http://www.qt.io/contact-us for pricing and purchasing information.\n"; - -static const char boilerplate_supported[] = - "\nQt %1 Evaluation License\n" - "Copyright (C) 2016 The Qt Company Ltd.\n" - "This trial version may only be used for evaluation purposes\n" - "Registered to:\n" - " Licensee: %2\n\n" - "The evaluation expires in %4 days\n\n" - "Contact http://www.qt.io/contact-us for pricing and purchasing information.\n"; - -static const char boilerplate_expired[] = - "This software is using the trial version of the Qt GUI toolkit.\n" - "The trial period has expired. If you need more time to\n" - "evaluate Qt, or if you have any questions about Qt, contact us\n" - "at: http://www.qt.io/contact-us.\n\n"; - -static const char will_shutdown_1min[] = - "\nThe evaluation of Qt will SHUT DOWN in 1 minute.\n" - "Contact http://www.qt.io/contact-us for pricing and purchasing information.\n"; - -static const char will_shutdown_now[] = - "\nThe evaluation of Qt has now reached its automatic\n" - "timeout and will shut down.\n" - "Contact http://www.qt.io/contact-us for pricing and purchasing information.\n"; - -enum EvaluationStatus { - EvaluationNotSupported = 0, - EvaluationSupportedButTimeLimited, - EvaluationSupported -}; - -static EvaluationStatus qt_eval_is_supported() -{ - const volatile char *const license_key = qt_eval_key_data + 12; - - // fast fail - if (!qt_eval_key_data[0] || !*license_key) - return EvaluationNotSupported; - - // is this an unsupported evaluation? - const volatile char *typecode = license_key; - int field = 2; - for ( ; field && *typecode; ++typecode) - if (*typecode == '-') - --field; - - if (!field && typecode[1] == '4' && typecode[2] == 'M') { - if (typecode[0] == 'Q') - return EvaluationSupportedButTimeLimited; - else if (typecode[0] == 'R' || typecode[0] == 'Z') - return EvaluationSupported; - } - return EvaluationNotSupported; -} - -static int qt_eval_days_left() -{ - const volatile char *const expiry_date = qt_eval_expiry_date + 12; - - QDate today = QDate::currentDate(); - QDate lastday = QDate::fromString( - QString::fromLatin1(const_cast(expiry_date)), Qt::ISODate); - return today.daysTo(lastday); -} - -static bool qt_eval_is_expired() -{ - return qt_eval_days_left() < 0; -} - -static QString qt_eval_string() -{ - const char *msg; - switch (qt_eval_is_supported()) { - case EvaluationSupportedButTimeLimited: - msg = boilerplate_supported_but_time_limited; - break; - case EvaluationSupported: - msg = boilerplate_supported; - break; - default: - return QString(); - } - - return QString::fromLatin1(msg) - .arg(QLatin1String(QT_VERSION_STR)) - .arg(QLibraryInfo::licensee()) - .arg(qt_eval_days_left()); -} - -#define WARN_TIMEOUT 60 * 1000 * 119 -#define KILL_DELAY 60 * 1000 * 1 - -class QCoreFuriCuri : public QObject -{ -public: - - int warn; - int kill; - - QCoreFuriCuri() : QObject(), warn(-1), kill(-1) - { - if (qt_eval_is_supported() == EvaluationSupportedButTimeLimited) { - warn = startTimer(WARN_TIMEOUT); - kill = 0; - } - } - - void timerEvent(QTimerEvent *e) override { - if (e->timerId() == warn) { - killTimer(warn); - fprintf(stderr, "%s\n", will_shutdown_1min); - kill = startTimer(KILL_DELAY); - } else if (e->timerId() == kill) { - fprintf(stderr, "%s\n", will_shutdown_now); - QCoreApplication::instance()->quit(); - } - } -}; - -#if defined(QT_BUILD_CORE_LIB) || defined (QT_BOOTSTRAPPED) - -void qt_core_eval_init(QCoreApplicationPrivate::Type type) -{ - if (type != QCoreApplicationPrivate::Tty) - return; - - if (!qt_eval_is_supported()) - return; - - if (qt_eval_is_expired()) { - fprintf(stderr, "%s\n", boilerplate_expired); - exit(0); - } else { - fprintf(stderr, "%s\n", qPrintable(qt_eval_string())); - Q_UNUSED(new QCoreFuriCuri()); - } -} -#endif - -#ifdef QT_BUILD_WIDGETS_LIB - -QT_BEGIN_INCLUDE_NAMESPACE -#include -#include -#include -#include -#if QT_CONFIG(pushbutton) -#include -#endif -#include -#include -QT_END_INCLUDE_NAMESPACE - - -static const char * const qtlogo_eval_xpm[] = { -/* columns rows colors chars-per-pixel */ -"46 55 174 2", -" c #002E02", -". c #00370D", -"X c #003A0E", -"o c #003710", -"O c #013C13", -"+ c #043E1A", -"@ c #084F0A", -"# c #0B520C", -"$ c #054413", -"% c #0C4C17", -"& c #07421D", -"* c #09451D", -"= c #0D491E", -"- c #125515", -"; c #13541A", -": c #17591B", -"> c #1B5C1D", -", c #1F611F", -"< c #20621E", -"1 c #337B1E", -"2 c #0B4521", -"3 c #0F4923", -"4 c #114B24", -"5 c #154D2A", -"6 c #175323", -"7 c #1C5924", -"8 c #1C532F", -"9 c #1E5432", -"0 c #245936", -"q c #265938", -"w c #295C3B", -"e c #246324", -"r c #266823", -"t c #2A6C24", -"y c #276628", -"u c #2D7026", -"i c #327427", -"p c #367927", -"a c #37782A", -"s c #397C2A", -"d c #2E613E", -"f c #336C37", -"g c #2F6040", -"h c #356545", -"j c #3C6B4E", -"k c #3F6C51", -"l c #406E4F", -"z c #406D52", -"x c #477457", -"c c #497557", -"v c #4B7857", -"b c #517B5E", -"n c #3C8423", -"m c #3E812C", -"M c #53A61D", -"N c #41862C", -"B c #458A2D", -"V c #498F2D", -"C c #479324", -"Z c #489226", -"A c #4D952C", -"S c #478B30", -"D c #488C30", -"F c #4D9232", -"G c #509632", -"H c #549A33", -"J c #589F35", -"K c #56A526", -"L c #57A821", -"P c #5BAA27", -"I c #57A32A", -"U c #5CA72E", -"Y c #5DAB2A", -"T c #5CA336", -"R c #60AD2E", -"E c #63B12D", -"W c #65AF35", -"Q c #62A53F", -"! c #65AE39", -"~ c #66B036", -"^ c #6AB437", -"/ c #67B138", -"( c #6AB339", -") c #6DB838", -"_ c #70BA3C", -"` c #4D8545", -"' c #4E8942", -"] c #548851", -"[ c #6FAF4A", -"{ c #6DB243", -"} c #71B546", -"| c #70B840", -" . c #73B648", -".. c #79BA4E", -"X. c #7CBB53", -"o. c #598266", -"O. c #62886D", -"+. c #6A8F75", -"@. c #6B9173", -"#. c #70937A", -"$. c #799F79", -"%. c #7BAF66", -"&. c #81BD5B", -"*. c #85BF60", -"=. c #85AC7F", -"-. c #8DBA7B", -";. c #87C061", -":. c #8AC364", -">. c #8DC46A", -",. c #90C56E", -"<. c #93C771", -"1. c #96CA73", -"2. c #9ACB7C", -"3. c #9FD07D", -"4. c #779981", -"5. c #7F9F89", -"6. c #809F88", -"7. c #82A18B", -"8. c #86A192", -"9. c #8DA994", -"0. c #8FA998", -"q. c #94AF9B", -"w. c #97B991", -"e. c #97B19E", -"r. c #9DB6A3", -"t. c #A3BCA7", -"y. c #A6BCAB", -"u. c #A9BEB1", -"i. c #9ECD81", -"p. c #A2CF85", -"a. c #A5D284", -"s. c #A6D189", -"d. c #A9D28E", -"f. c #ABD491", -"g. c #B1D797", -"h. c #B1D699", -"j. c #B5D89E", -"k. c #ADC5AC", -"l. c #B1CAAE", -"z. c #B9DAA3", -"x. c #BDDDA8", -"c. c #ADC1B4", -"v. c #B2C6B6", -"b. c #B5C6BC", -"n. c #B6C9BA", -"m. c #BCD1BA", -"M. c #C6E1B4", -"N. c #CDE5BD", -"B. c #C2D2C6", -"V. c #CADEC2", -"C. c #C6D3CC", -"Z. c #C8D7CB", -"A. c #CEDAD2", -"S. c #D2DDD4", -"D. c #D3E9C6", -"F. c #D7EBC9", -"G. c #D9EBCD", -"H. c #DEEED4", -"J. c #D6E0D9", -"K. c #DAE4DC", -"L. c #E0EFD7", -"P. c #E5F2DD", -"I. c #DFE8E0", -"U. c #E4EBE5", -"Y. c #E9EFEA", -"T. c #EDF4EB", -"R. c #F0FAE6", -"E. c #F1F8EC", -"W. c #EDF0F0", -"Q. c #F4F7F3", -"!. c #F6F9F4", -"~. c #F8FAF7", -"^. c #FEFEFE", -"/. c None", -/* pixels */ -"/././././.c h ' Q / W _ &.p././././././././././././././././././././././././././././././././.", -"/././.4 O % Z ~ ~ W ~ W R U R R ( X.>.p././././././././././././././././././././././././././.", -"/./.. * = J _ ~ ~ ~ ~ ~ / / / / W W U P P U W .;.2././././././././././././././././././././.", -"/.= = & a ) W ~ ~ ~ ~ ~ / W / ~ ~ ~ ^ ( ( ^ ~ R R U P Y ~ .;.2././././././././././././././.", -"O.O = = T ^ W ~ ~ ~ ~ ~ ~ W W / W ~ ~ ~ ~ ~ ~ ~ ( ( ( ( ~ W Y Y Y Y W { &.1././././././././.", -"0 = * 7 ~ ~ ~ ~ ~ ~ ~ ~ ~ / / W ~ ~ ~ ~ ~ ~ ~ ~ W W W ~ ~ ~ ~ ( ( ( W W R U P U W { X.1.f./.", -"= = & e ^ W ~ ~ ~ ~ ~ ~ ~ ~ / / ~ ~ ~ ~ ~ ~ ~ ~ W ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ^ ( ( / ~ W R U U Y ", -"= = & e ^ W ~ ~ ~ ~ ~ ~ ~ ~ W W ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ W ( W ~ ~ ~ ^ ^ ( ", -"= = * e ^ W ~ ~ ~ ~ ~ ~ / W / W ! ( / ~ W ^ ( ( ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ W ~ W W ~ ~ ~ ~ ~ ~ ", -"= = & e ^ ! ~ ~ ~ ~ ~ ~ W W ^ _ ~ K Y W W R P Y W ( ~ ~ ~ ~ ~ ~ ~ W / ~ ~ ~ ^ W ~ ~ ~ ~ ~ ~ ", -"= = & e ^ W ~ ~ ~ ~ ~ ~ W ) W 1 ` w.V.L.H.D.z.,.~ Y ^ ~ ~ ~ ~ ~ W ~ ~ ~ ( ~ W W ~ ~ ~ ~ ~ ~ ", -"= = & e ^ W ~ ~ ~ ~ ~ W ) V = 8.~.^.^.^.^.^.^.^.U.<.Y ~ ~ ~ ~ ~ W W ! ~ Y W ^ W ~ ~ ~ ~ ~ ~ ", -"= = & e ^ W ~ ~ ~ ~ W ^ B O u.^.~.^.^.^.^.~.~.^.^.^.h.Y ^ ~ ~ ^ F $ k.R.G.1.Y / ~ ~ ~ ~ ~ ~ ", -"= = & e ^ ~ ~ ~ / W ( J X 7.^.~.^.^.^.^.^.^.^.^.^.^.^.s.Y / W ) a 2 U.^.^.d.U ( ~ ~ ~ ~ ~ ~ ", -"= = & e ^ W / ~ ~ ~ ^ > w ~.^.^.^.^.^.F.%.v c.^.^.^.^.~.X.W ~ ^ > h ^.^.^.d.P ( ~ ~ ~ ~ ~ ~ ", -"= = & e ^ W ~ ~ W ^ H o e.^.^.^.^.^.G.Y E n . y.^.^.^.^.M.Y ( ! $ @.^.~.^.f.U ( / ~ ~ W ~ ~ ", -"= = & e ^ W ~ W ! ) t 4 U.^.^.^.^.^.>.U ( _ , 9 ~.^.^.^.~...^ A y.^.~.^.s.M W Y ~ ~ ~ ~ ~ ", -"= 3 & e ^ W ~ ( ^ ( $ c ^.^.^.^.^.E.) ~ ~ ^ S o n.^.^.^.^.=.- l.v.Y.^.^.^.M.:.:.X.~ ~ ~ ~ ~ ", -"= = & e ^ ! W W ( J X 7.^.^.^.^.^.F.Y ( W ^ T X 6.^.^.~.^.c.. J.^.^.^.^.^.^.^.^.P.~ ~ ~ ~ ~ ", -"= = & r ^ W / W ) B o v.^.~.^.^.^.M.U / ~ ~ ! $ o.^.^.^.^.K.* S.^.^.^.^.^.^.^.^.P.~ ~ ~ ~ ~ ", -"= = & e ^ ! ~ W ) a + S.^.^.^.^.^.z.P ( W ~ ( % z ^.^.^.^.~.f t.U.^.^.^.^.~.^.^.P.~ ~ ~ ~ ~ ", -"* = & e ^ W ~ W ) t 3 Y.^.^.^.^.^.f.P ( ~ ~ ^ ; h ^.^.^.^.^.:.@ j ^.^.^.^.h.{ X.&.~ ~ ~ ~ ~ ", -"3 = & e ^ W ~ ~ ^ e 8 Q.^.^.^.^.^.s.P ~ ~ W ^ > 0 ~.^.^.^.^.1.# z ^.^.^.^.d.L W R ~ ~ ~ ~ ~ ", -"= = & e ^ W ~ ~ ^ > q ~.^.^.^.^.^.p.U ^ ~ W ) e 9 ~.^.^.^.^.3.# k ^.^.^.^.f.Y ( / ~ ~ ~ ~ ~ ", -"= = & e ^ W / W ^ > w ~.^.^.^.^.^.i.Y / ~ W ^ e 8 Q.^.^.^.^.a.# z ^.^.^.^.f.Y / ~ ~ ~ ~ ~ ~ ", -"= = & e ^ W / W ^ > w ^.^.^.^.^.^.2.Y / ~ ~ ) e 8 Q.^.^.^.^.s.# z ^.^.^.^.d.P ( ~ ~ ~ ~ ~ ~ ", -"= = & e ^ W W W ^ > q ^.^.^.^.^.^.p.Y / ~ ~ ^ e 9 Q.^.^.^.^.a.@ z ^.^.^.^.f.U / ~ ~ ~ ~ ~ ~ ", -"= = & e ^ W / W ) 7 9 Q.^.^.^.^.^.a.P / ~ W ) , 9 Q.^.^.^.^.3.# z ^.^.~.^.f.P ^ ~ ~ ~ ~ ~ ~ ", -"= = & e ^ W / W ) r 5 T.^.^.^.^.^.d.Y / ~ W ) > q ~.^.^.^.^.1.# k ^.^.^.^.f.Y ( ~ ~ ~ ~ ~ ~ ", -"= = & e ^ / / W ) i 2 I.^.^.^.^.^.h.P ( ~ W ( > g ^.^.^.^.^.:.# z ^.^.^.^.f.P / ~ ~ ~ ~ ~ ~ ", -"= = & e ( W / W ) m O Z.^.^.^.^.^.x.P / ~ ~ ( ; j ^.^.^.^.~.&.- k ^.^.~.^.f.P / ~ ~ ~ ~ ~ ~ ", -"= = & e ( W / W ) F o y.^.~.^.^.^.N.U ( ~ ~ W $ b ^.^.^.^.R._ - k ^.^.^.^.f.Y ( ~ ~ ~ ~ ~ ~ ", -"= = & e ^ W ~ ~ ^ J X 4.^.^.^.^.^.L.~ ~ W ^ T X #.^.^.^.^.F.~ ; j ^.^.^.^.f.U ( ~ ~ ~ ~ ~ ~ ", -"= = & e ^ ~ ~ ~ / ^ % l ^.^.^.^.^.!. .R ^ ^ G . r.^.~.^.^.j.E : j ^.^.^.^.f.P ) ( ~ ~ ~ ~ ~ ", -"= = & e ^ W ~ ~ W ) u = U.^.^.^.^.^.1.Y ! ) a & K.^.^.^.^.;.~ : j ^.^.~.^.z.M I I / ~ ~ W ~ ", -"= = & e ( W ~ ~ W ( G . q.^.^.^.^.^.D.U ^ ! X o.^.^.^.^.P.~ ^ > g ^.^.^.^.E.-.$.m.X.W ~ ~ ~ ", -"= = & e ^ / ~ ~ ^ ! ( > w ~.^.^.^.^.^.h.T > j T.^.^.~.^.a.Y _ i 3 U.^.^.^.^.^.^.^.X.R ~ ~ ~ ", -"= = & e ^ / ~ ~ W W ^ H . 9.^.~.^.^.^.^.K.C.~.^.^.^.^.H.W W ^ T . q.^.~.^.^.^.^.^.X.R ~ ~ ~ ", -"= = + e ^ W / ~ W W W ) m + B.^.~.^.^.^.^.^.^.^.^.^.E.X.Y ( W ^ B 6 y.^.^.^.E.D.2.( ~ ~ ~ ~ ", -"= = * e ^ ! / ! W ^ W W ) a 4 b.^.^.^.^.^.^.^.^.^.P...Y ( ! W ! ^ W Z [ *.X.{ Y U ~ ~ ~ ~ ~ ", -"= = & e ( W ~ ~ W / W / W ) A < +.A.~.^.^.^.^.!.p.W R ~ ~ ~ ~ ~ W / ) E U W W / ^ ~ ~ ~ ~ ~ ", -"= = & e ^ W ~ ~ / W / / / W ( _ Z X 6.^.^.^.^.E.W ~ ^ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ / ~ ~ ~ ~ ~ ~ ~ ~ ", -"= = & e ^ ~ ~ ~ W W / W ~ ~ ~ ~ ) ; h ^.^.^.^.^.d.M U ~ / ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ W ", -"= = & e ^ W ~ ~ ^ W W / ~ ~ ~ W ) p + S.^.^.^.^.~.M.f. .W ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ .", -"= = & e ^ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ W ( T O +.^.~.^.^.^.^.^.&.Y ( ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ W ( Y 2.", -"= = & e ( W ~ ~ ~ ~ ~ ~ ~ ~ ~ / W ) N + b.^.^.^.^.^.^.&.R ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ W /.", -"= = & e ^ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ W ^ N 7 r.W.^.^.^.!.X.W ~ ~ W ~ W ~ ~ ~ ~ ~ ~ / ( ( K p./.", -"= = & e ( W ~ ~ W ~ ~ ~ ~ ~ ~ ~ ~ ~ W ( W C Q &.:.X.| ~ ~ ~ ~ W ~ / ~ ( / ( ~ W E U P 1././.", -"= = + e ^ / / / ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ W / ) ^ R Y W W ~ ~ ( / ( / W R Y Y U R ( X.,././././.", -"= = * e ( / ~ / ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ W W W ! ( ( ( W W E U P Y W ( X.,.d./././././././././.", -"= = * e ( W ~ ~ ~ ~ W ! ~ W ~ W ~ ( ( / ^ W W U Y P W ( X.,.d./././././././././././././././.", -"8 $ * e ( W ~ ~ ~ ! ( ( ( / ( W R Y Y Y R ( X.>.d./././././././././././././././././././././.", -"/.d . y ^ / / / ( W Y Y P P W ( X.>.d./././././././././././././././././././././././././././.", -"/./.h : ^ R R R W ( X.<.f./././././././././././././././././././././././././././././././././.", -"/././.] _ *.3./././././././././././././././././././././././././././././././././././././././." -}; - -class EvalMessageBox : public QDialog -{ -public: - EvalMessageBox(bool expired) - { - setWindowTitle(QLatin1String(" ")); - - QString str = expired ? QLatin1String(boilerplate_expired) : qt_eval_string(); - str = str.trimmed(); - - QFrame *border = new QFrame(this); - - QLabel *pixmap_label = new QLabel(border); - pixmap_label->setPixmap(QPixmap(qtlogo_eval_xpm)); - pixmap_label->setAlignment(Qt::AlignTop); - - QLabel *text_label = new QLabel(str, border); - - QHBoxLayout *pm_and_text_layout = new QHBoxLayout(); - pm_and_text_layout->addWidget(pixmap_label); - pm_and_text_layout->addWidget(text_label); - - QVBoxLayout *master_layout = new QVBoxLayout(border); - master_layout->addLayout(pm_and_text_layout); - - QVBoxLayout *border_layout = new QVBoxLayout(this); - border_layout->setMargin(0); - border_layout->addWidget(border); - - if (expired) { - QPushButton *cmd = new QPushButton(QLatin1String("OK"), border); - cmd->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); - cmd->setDefault(true); - - QHBoxLayout *button_layout = new QHBoxLayout(); - master_layout->addLayout(button_layout); - button_layout->addWidget(cmd); - - connect(cmd, SIGNAL(clicked()), this, SLOT(close())); - } else { - border->setFrameShape(QFrame::WinPanel); - border->setFrameShadow(QFrame::Raised); - setParent(parentWidget(), Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint); - QTimer::singleShot(7000, this, SLOT(close())); - setAttribute(Qt::WA_DeleteOnClose); - setAttribute(Qt::WA_QuitOnClose, false); - } - - setFixedSize(sizeHint()); - } -}; - -class QGuiFuriCuri : public QCoreFuriCuri -{ -public: - void timerEvent(QTimerEvent *e) { - if (e->timerId() == warn) { - killTimer(warn); - QMessageBox::information(0, QLatin1String("Automatic Timeout"), QLatin1String(will_shutdown_1min)); - kill = startTimer(KILL_DELAY); - } else if (e->timerId() == kill) { - killTimer(kill); - QMessageBox::information(0, QLatin1String("Automatic Timeout"), QLatin1String(will_shutdown_now)); - qApp->quit(); - } - } -}; - - -void qt_gui_eval_init(QCoreApplicationPrivate::Type type) -{ - Q_UNUSED(type); - - if (!qt_eval_is_supported()) - return; - - if (qt_eval_is_expired()) { - EvalMessageBox box(true); - box.exec(); - ::exit(0); - } else { - Q_UNUSED(new QGuiFuriCuri()); - } -} - -static QString qt_eval_title_prefix() -{ - return QLatin1String("[Qt Evaluation] "); -} - -QString qt_eval_adapt_window_title(const QString &title) -{ - if (!qt_eval_is_supported()) - return title; - return qt_eval_title_prefix() + title; -} - -void qt_eval_init_widget(QWidget *w) -{ - if (!qt_eval_is_supported()) - return; - if (w->isTopLevel() && w->windowTitle().isEmpty() && w->windowType() != Qt::Desktop ) { - w->setWindowTitle(QLatin1String(" ")); - } -} -#endif - -QT_END_NAMESPACE -- cgit v1.2.3 From ae94ab264ba29a41beac81a61fb39c0d4f669270 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Tue, 12 Feb 2019 14:04:04 +0100 Subject: Add developer documentation on how to debug missing auto-release pools MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Ie3942210ab5bafea22d65d6f7c9a099e40ee6b73 Reviewed-by: Morten Johan Sørvig --- src/corelib/kernel/qcore_mac_objc.mm | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qcore_mac_objc.mm b/src/corelib/kernel/qcore_mac_objc.mm index bc23e821fd..140c60a080 100644 --- a/src/corelib/kernel/qcore_mac_objc.mm +++ b/src/corelib/kernel/qcore_mac_objc.mm @@ -129,6 +129,16 @@ QT_USE_NAMESPACE QT_NAMESPACE_ALIAS_OBJC_CLASS(QMacAutoReleasePoolTracker); QT_BEGIN_NAMESPACE + +/* + Manages a scoped auto-release pool. + + To track autoreleases without any pools in place, such as in main() + before the runloop has started, export OBJC_DEBUG_MISSING_POOLS=YES + and break in objc_autoreleaseNoPool, e.g.: + + br set -n objc_autoreleaseNoPool -c "[((NSObject*)$r14) class] == [QNSWindow class]" +*/ QMacAutoReleasePool::QMacAutoReleasePool() : pool([[NSAutoreleasePool alloc] init]) { -- cgit v1.2.3 From e1d42a40a2fabefdc57c40e25dbf7b923332ba5d Mon Sep 17 00:00:00 2001 From: Alessandro Portale Date: Mon, 11 Feb 2019 00:02:37 +0100 Subject: Add missing "override" specifiers Annotate this function with 'override' or (rarely) 'final' [modernize-use-override] Change-Id: If31ab03b46f885e4984ba3aaaf1ad8d46aae9d9c Reviewed-by: Friedemann Kleint --- src/corelib/kernel/qeventdispatcher_win_p.h | 34 ++++++++++++++--------------- 1 file changed, 17 insertions(+), 17 deletions(-) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qeventdispatcher_win_p.h b/src/corelib/kernel/qeventdispatcher_win_p.h index a7ed8dda8a..707bc79407 100644 --- a/src/corelib/kernel/qeventdispatcher_win_p.h +++ b/src/corelib/kernel/qeventdispatcher_win_p.h @@ -80,31 +80,31 @@ public: explicit QEventDispatcherWin32(QObject *parent = 0); ~QEventDispatcherWin32(); - bool QT_ENSURE_STACK_ALIGNED_FOR_SSE processEvents(QEventLoop::ProcessEventsFlags flags); - bool hasPendingEvents(); + bool QT_ENSURE_STACK_ALIGNED_FOR_SSE processEvents(QEventLoop::ProcessEventsFlags flags) override; + bool hasPendingEvents() override; - void registerSocketNotifier(QSocketNotifier *notifier); - void unregisterSocketNotifier(QSocketNotifier *notifier); + void registerSocketNotifier(QSocketNotifier *notifier) override; + void unregisterSocketNotifier(QSocketNotifier *notifier) override; - void registerTimer(int timerId, int interval, Qt::TimerType timerType, QObject *object); - bool unregisterTimer(int timerId); - bool unregisterTimers(QObject *object); - QList registeredTimers(QObject *object) const; + void registerTimer(int timerId, int interval, Qt::TimerType timerType, QObject *object) override; + bool unregisterTimer(int timerId) override; + bool unregisterTimers(QObject *object) override; + QList registeredTimers(QObject *object) const override; - bool registerEventNotifier(QWinEventNotifier *notifier); - void unregisterEventNotifier(QWinEventNotifier *notifier); + bool registerEventNotifier(QWinEventNotifier *notifier) override; + void unregisterEventNotifier(QWinEventNotifier *notifier) override; void activateEventNotifiers(); - int remainingTime(int timerId); + int remainingTime(int timerId) override; - void wakeUp(); - void interrupt(); - void flush(); + void wakeUp() override; + void interrupt() override; + void flush() override; - void startingUp(); - void closingDown(); + void startingUp() override; + void closingDown() override; - bool event(QEvent *e); + bool event(QEvent *e) override; HWND internalHwnd(); -- cgit v1.2.3 From 6c18f86af7affc60a571c65f0b335d7ee8947100 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Tue, 12 Feb 2019 13:02:48 +0100 Subject: Track call sites of QMacAutoReleasePools for debugging pool usage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Printing pools by calling [NSAutoreleasePool showPools] will now give a more detailed view of where the various pools in the stack were created, eg: AUTORELEASE POOLS for thread 0x1000be5c0 17 releases pending. [0x107802000] ................ PAGE (hot) (cold) [0x107802038] ################ POOL 0x107802038 [0x107802040] 0x107791c70 ^-- allocated in function: main [0x107802048] ################ POOL 0x107802048 [0x107802050] 0x1073b2e80 ^-- allocated in function: QCocoaWindow::initialize() [0x107802058] 0x107111ed0 NSCompositeAppearance [0x107802060] 0x107111ed0 NSCompositeAppearance [0x107802068] 0x107111ed0 NSCompositeAppearance [0x107802070] 0x1073bbe10 __NSCFString [0x107802078] 0x1073bbde0 _NSViewBackingLayer [0x107802080] 0x1073bc100 NSWeakObjectValue [0x107802088] 0x1073bbe40 QNSView [0x107802090] 0x1073bbe40 QNSView [0x107802098] 0x107111ed0 NSCompositeAppearance [0x1078020a0] 0x107111ed0 NSCompositeAppearance [0x1078020a8] 0x1073bbe40 QNSView [0x1078020b0] ################ POOL 0x1078020b0 [0x1078020b8] 0x1073bbe30 ^-- allocated in function: QCocoaWindow::recreateWindowIfNeeded() Change-Id: I97faf30db5835fea2f05320435b1b8c334a478d1 Reviewed-by: Morten Johan Sørvig Reviewed-by: Tor Arne Vestbø --- src/corelib/kernel/qcore_mac_objc.mm | 59 +++++++++++++++++++++++++++++------- 1 file changed, 48 insertions(+), 11 deletions(-) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qcore_mac_objc.mm b/src/corelib/kernel/qcore_mac_objc.mm index 140c60a080..4550891e2a 100644 --- a/src/corelib/kernel/qcore_mac_objc.mm +++ b/src/corelib/kernel/qcore_mac_objc.mm @@ -48,6 +48,11 @@ #include #endif +#include +#include +#include +#include + #include QT_BEGIN_NAMESPACE @@ -127,22 +132,54 @@ QT_USE_NAMESPACE } @end QT_NAMESPACE_ALIAS_OBJC_CLASS(QMacAutoReleasePoolTracker); -QT_BEGIN_NAMESPACE - -/* - Manages a scoped auto-release pool. - - To track autoreleases without any pools in place, such as in main() - before the runloop has started, export OBJC_DEBUG_MISSING_POOLS=YES - and break in objc_autoreleaseNoPool, e.g.: +QT_BEGIN_NAMESPACE - br set -n objc_autoreleaseNoPool -c "[((NSObject*)$r14) class] == [QNSWindow class]" -*/ QMacAutoReleasePool::QMacAutoReleasePool() : pool([[NSAutoreleasePool alloc] init]) { - [[[QMacAutoReleasePoolTracker alloc] initWithPool: + Class trackerClass = [QMacAutoReleasePoolTracker class]; + +#ifdef QT_DEBUG + void *poolFrame = nullptr; + if (__builtin_available(macOS 10.14, iOS 12.0, tvOS 12.0, watchOS 5.0, *)) { + void *frame; + if (backtrace_from_fp(__builtin_frame_address(0), &frame, 1)) + poolFrame = frame; + } else { + static const int maxFrames = 3; + void *callstack[maxFrames]; + if (backtrace(callstack, maxFrames) == maxFrames) + poolFrame = callstack[maxFrames - 1]; + } + + if (poolFrame) { + Dl_info info; + if (dladdr(poolFrame, &info) && info.dli_sname) { + const char *symbolName = info.dli_sname; + if (symbolName[0] == '_') { + int status; + if (char *demangled = abi::__cxa_demangle(info.dli_sname, nullptr, 0, &status)) + symbolName = demangled; + } + + char *className = nullptr; + asprintf(&className, " ^-- allocated in function: %s", symbolName); + + if (Class existingClass = objc_getClass(className)) + trackerClass = existingClass; + else + trackerClass = objc_duplicateClass(trackerClass, className, 0); + + free(className); + + if (symbolName != info.dli_sname) + free((char*)symbolName); + } + } +#endif + + [[[trackerClass alloc] initWithPool: reinterpret_cast(&pool)] autorelease]; } -- cgit v1.2.3 From 91deac4a65a31141764cd2739066166475f024d8 Mon Sep 17 00:00:00 2001 From: Christian Ehrlicher Date: Fri, 15 Feb 2019 21:21:20 +0100 Subject: QtCore: replace null and nullptr with \nullptr in documentation Replace null and '\c nullptr' with \nullptr in the documentation. Change-Id: Ib9e0cfc2eb2830b213e6523773603d56180b0998 Reviewed-by: Friedemann Kleint --- src/corelib/kernel/qcoreapplication.cpp | 19 ++++++++++--------- src/corelib/kernel/qmetaobject.cpp | 2 +- src/corelib/kernel/qmetatype.cpp | 2 +- src/corelib/kernel/qobject.cpp | 4 ++-- src/corelib/kernel/qvariant.cpp | 4 ++-- 5 files changed, 16 insertions(+), 15 deletions(-) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index e5098b8415..db66157a0e 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -1636,14 +1636,15 @@ bool QCoreApplication::compressEvent(QEvent *event, QObject *receiver, QPostEven /*! Immediately dispatches all events which have been previously queued - with QCoreApplication::postEvent() and which are for the object \a receiver - and have the event type \a event_type. + with QCoreApplication::postEvent() and which are for the object \a + receiver and have the event type \a event_type. Events from the window system are \e not dispatched by this function, but by processEvents(). - If \a receiver is null, the events of \a event_type are sent for all - objects. If \a event_type is 0, all the events are sent for \a receiver. + If \a receiver is \nullptr, the events of \a event_type are sent for + all objects. If \a event_type is 0, all the events are sent for + \a receiver. \note This method must be called from the thread in which its QObject parameter, \a receiver, lives. @@ -1824,10 +1825,10 @@ void QCoreApplicationPrivate::sendPostedEvents(QObject *receiver, int event_type call it, be aware that killing events may cause \a receiver to break one or more invariants. - If \a receiver is null, the events of \a eventType are removed for - all objects. If \a eventType is 0, all the events are removed for - \a receiver. You should never call this function with \a eventType - of 0. + If \a receiver is \nullptr, the events of \a eventType are removed + for all objects. If \a eventType is 0, all the events are removed + for \a receiver. You should never call this function with \a + eventType of 0. \threadsafe */ @@ -2140,7 +2141,7 @@ static void replacePercentN(QString *result, int n) \a disambiguation is an identifying string, for when the same \a sourceText is used in different roles within the same context. By - default, it is null. + default, it is \nullptr. See the \l QTranslator and \l QObject::tr() documentation for more information about contexts, disambiguations and comments. diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp index 8082b7fe9b..c15a9f7b0f 100644 --- a/src/corelib/kernel/qmetaobject.cpp +++ b/src/corelib/kernel/qmetaobject.cpp @@ -3522,7 +3522,7 @@ bool QMetaProperty::isStored(const QObject *object) const false. e.g., the \c text property is the \c USER editable property of a QLineEdit. - If \a object is null, the function returns \c false if the \c + If \a object is \nullptr, the function returns \c false if the \c {Q_PROPERTY()}'s \c USER attribute is false. Otherwise it returns true. diff --git a/src/corelib/kernel/qmetatype.cpp b/src/corelib/kernel/qmetatype.cpp index a1d53be197..45d0b5df6c 100644 --- a/src/corelib/kernel/qmetatype.cpp +++ b/src/corelib/kernel/qmetatype.cpp @@ -432,7 +432,7 @@ struct DefinedTypesFilter { \since 5.0 Returns a copy of \a copy, assuming it is of the type that this - QMetaType instance was created for. If \a copy is null, creates + QMetaType instance was created for. If \a copy is \nullptr, creates a default constructed instance. \sa QMetaType::destroy() diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 2cdb9eaaa6..77f507ff3f 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -3284,7 +3284,7 @@ QMetaObject::Connection QMetaObject::connect(const QObject *sender, int signal_i \internal Same as the QMetaObject::connect, but \a signal_index must be the result of QObjectPrivate::signalIndex - method_index is relative to the rmeta metaobject, if rmeta is null, then it is absolute index + method_index is relative to the rmeta metaobject, if rmeta is \nullptr, then it is absolute index the QObjectPrivate::Connection* has a refcount of 2, so it must be passed to a QMetaObject::Connection */ @@ -3856,7 +3856,7 @@ void QMetaObject::activate(QObject *sender, int signal_index, void **argv) It is different from QMetaObject::indexOfSignal(): indexOfSignal is the same as indexOfMethod while QObjectPrivate::signalIndex is smaller because it doesn't give index to slots. - If \a meta is not 0, it is set to the meta-object where the signal was found. + If \a meta is not \nullptr, it is set to the meta-object where the signal was found. */ int QObjectPrivate::signalIndex(const char *signalName, const QMetaObject **meta) const diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp index 090436a3c7..18c7f7648d 100644 --- a/src/corelib/kernel/qvariant.cpp +++ b/src/corelib/kernel/qvariant.cpp @@ -1768,7 +1768,7 @@ Q_CORE_EXPORT void QVariantPrivate::registerHandler(const int /* Modules::Names \fn QVariant::QVariant(int typeId, const void *copy) Constructs variant of type \a typeId, and initializes with - \a copy if \a copy is not 0. + \a copy if \a copy is not \nullptr. Note that you have to pass the address of the variable you want stored. @@ -1797,7 +1797,7 @@ Q_CORE_EXPORT void QVariantPrivate::registerHandler(const int /* Modules::Names \internal Constructs a variant private of type \a type, and initializes with \a copy if - \a copy is not 0. + \a copy is not \nullptr. */ void QVariant::create(int type, const void *copy) -- cgit v1.2.3 From 46589056c399191e1afe0b2ddb1e2f0570fa8ddc Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Tue, 12 Feb 2019 12:45:50 +0100 Subject: QObject: count declarative receivers also if there are no C++ ones Change-Id: If998cdd5eeb8a3ae85cd540cc9c1fd0c051e1d4b Fixes: QTBUG-73753 Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/kernel/qobject.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 257575e141..7b9689f1cf 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -2404,8 +2404,7 @@ int QObject::receivers(const char *signal) const { Q_D(const QObject); int receivers = 0; - QObjectPrivate::ConnectionData *cd = d->connections.load(); - if (signal && cd) { + if (signal) { QByteArray signal_name = QMetaObject::normalizedSignature(signal); signal = signal_name; #ifndef QT_NO_DEBUG @@ -2429,8 +2428,9 @@ int QObject::receivers(const char *signal) const signal_index); } + QObjectPrivate::ConnectionData *cd = d->connections.load(); QBasicMutexLocker locker(signalSlotLock(this)); - if (signal_index < cd->signalVector.count()) { + if (cd && signal_index < cd->signalVector.count()) { const QObjectPrivate::Connection *c = cd->signalVector.at(signal_index).first; while (c) { -- cgit v1.2.3 From 85b0ce8ca36d52db71b519ee8d2a1ce369c53a81 Mon Sep 17 00:00:00 2001 From: Robert Loehning Date: Mon, 25 Feb 2019 13:54:26 +0100 Subject: Fix can not -> cannot Change-Id: Ie9992f67ca59aff662a4be046ace08640e7c2714 Reviewed-by: Paul Wicking --- src/corelib/kernel/qcore_mac_objc.mm | 2 +- src/corelib/kernel/qeventdispatcher_unix.cpp | 2 +- src/corelib/kernel/qobject.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qcore_mac_objc.mm b/src/corelib/kernel/qcore_mac_objc.mm index 4550891e2a..6687eb88a5 100644 --- a/src/corelib/kernel/qcore_mac_objc.mm +++ b/src/corelib/kernel/qcore_mac_objc.mm @@ -501,7 +501,7 @@ void qt_apple_check_os_version() if (!applicationName) applicationName = NSProcessInfo.processInfo.processName; - fprintf(stderr, "Sorry, \"%s\" can not be run on this version of %s. " + fprintf(stderr, "Sorry, \"%s\" cannot be run on this version of %s. " "Qt requires %s %ld.%ld.%ld or later, you have %s %ld.%ld.%ld.\n", applicationName.UTF8String, os, os, long(required.majorVersion), long(required.minorVersion), long(required.patchVersion), diff --git a/src/corelib/kernel/qeventdispatcher_unix.cpp b/src/corelib/kernel/qeventdispatcher_unix.cpp index 535f86fefe..df0cac0239 100644 --- a/src/corelib/kernel/qeventdispatcher_unix.cpp +++ b/src/corelib/kernel/qeventdispatcher_unix.cpp @@ -225,7 +225,7 @@ int QThreadPipe::check(const pollfd &pfd) QEventDispatcherUNIXPrivate::QEventDispatcherUNIXPrivate() { if (Q_UNLIKELY(threadPipe.init() == false)) - qFatal("QEventDispatcherUNIXPrivate(): Can not continue without a thread pipe"); + qFatal("QEventDispatcherUNIXPrivate(): Cannot continue without a thread pipe"); } QEventDispatcherUNIXPrivate::~QEventDispatcherUNIXPrivate() diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 77f507ff3f..e67b2306c2 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -2152,7 +2152,7 @@ void QObject::removeEventFilter(QObject *obj) This signal is emitted immediately before the object \a obj is destroyed, after any instances of QPointer have been notified, - and can not be blocked. + and cannot be blocked. All the objects's children are destroyed immediately after this signal is emitted. -- cgit v1.2.3 From 197029b3d23237e61311019de1b63e3ce6720ed5 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Mon, 10 Dec 2018 19:18:57 -0800 Subject: Make the QEventDispatcherWin32Private::interrupt flag atomic Not entirely sure that this solves the problem reported in the bug report, but here's the theory: the loop 633 while (!d->interrupt) { ... 710 } has few calls that recurse back, so the compiler optimizer can assume that the variable remains unchanged (not interrupted) in most of the branches. Additionally, it can assume the variable did not change from there to 712 // still nothing - wait for message or signalled objects 713 canWait = (!retVal 714 && !d->interrupt 715 && (flags & QEventLoop::WaitForMoreEvents)); Which causes canWait to be true, despite having been interrupted by another thread. Changing to an atomic does not force the reloading of the variable (strictly speaking, would need volatile, but all atomic implementations do reload now), but it solves the problem of data race, which was UB. The equivalent variable in the Unix event dispatcher is atomic (commit 49d7e71f77f899c05e4b5187e8834dfcbddf4505 from 2013). I've reordered the bool members so they're all together and reduce the amount of padding in this class. Fixes: QTBUG-72438 Change-Id: I4ac1156702324f0fb814fffd156f290df94dc4c7 Reviewed-by: Joerg Bornemann Reviewed-by: Thiago Macieira --- src/corelib/kernel/qeventdispatcher_win.cpp | 10 +++++----- src/corelib/kernel/qeventdispatcher_win_p.h | 7 ++++--- 2 files changed, 9 insertions(+), 8 deletions(-) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qeventdispatcher_win.cpp b/src/corelib/kernel/qeventdispatcher_win.cpp index 0bddf89b15..b3b6b1be20 100644 --- a/src/corelib/kernel/qeventdispatcher_win.cpp +++ b/src/corelib/kernel/qeventdispatcher_win.cpp @@ -95,7 +95,7 @@ class QEventDispatcherWin32Private; LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp); QEventDispatcherWin32Private::QEventDispatcherWin32Private() - : threadId(GetCurrentThreadId()), interrupt(false), closingDown(false), internalHwnd(0), + : threadId(GetCurrentThreadId()), interrupt(false), internalHwnd(0), getMessageHook(0), serialNumber(0), lastSerialNumber(0), sendPostedEventsWindowsTimerId(0), wakeUps(0), activateNotifiersPosted(false), winEventNotifierActivatedEvent(NULL) { @@ -552,7 +552,7 @@ bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags) wakeUp(); // trigger a call to sendPostedEvents() } - d->interrupt = false; + d->interrupt.store(false); emit awake(); bool canWait; @@ -568,7 +568,7 @@ bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags) pHandles = &d->winEventNotifierActivatedEvent; } QVarLengthArray processedTimers; - while (!d->interrupt) { + while (!d->interrupt.load()) { MSG msg; bool haveMessage; @@ -649,7 +649,7 @@ bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags) // still nothing - wait for message or signalled objects canWait = (!retVal - && !d->interrupt + && !d->interrupt.load() && (flags & QEventLoop::WaitForMoreEvents)); if (canWait) { emit aboutToBlock(); @@ -1016,7 +1016,7 @@ void QEventDispatcherWin32::wakeUp() void QEventDispatcherWin32::interrupt() { Q_D(QEventDispatcherWin32); - d->interrupt = true; + d->interrupt.store(true); wakeUp(); } diff --git a/src/corelib/kernel/qeventdispatcher_win_p.h b/src/corelib/kernel/qeventdispatcher_win_p.h index a7ed8dda8a..3bb618153b 100644 --- a/src/corelib/kernel/qeventdispatcher_win_p.h +++ b/src/corelib/kernel/qeventdispatcher_win_p.h @@ -165,8 +165,7 @@ public: DWORD threadId; - bool interrupt; - bool closingDown; + QAtomicInt interrupt; // internal window handle used for socketnotifiers/timers/etc HWND internalHwnd; @@ -193,9 +192,11 @@ public: void postActivateSocketNotifiers(); void doWsaAsyncSelect(int socket, long event); + bool closingDown = false; + + bool winEventNotifierListModified = false; HANDLE winEventNotifierActivatedEvent; QList winEventNotifierList; - bool winEventNotifierListModified = false; void activateEventNotifier(QWinEventNotifier * wen); QList queuedUserInputEvents; -- cgit v1.2.3 From 99566f68755449dbabb7345da5b5876e82f159f1 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 22 Jan 2019 10:52:57 -0800 Subject: Use qEnvironmentVariable for QT_PLUGIN_PATHS This is required for non-ANSI paths on Windows. Change-Id: Id98140e1c2f0426cabbefffd157c4065c3bdfd40 Reviewed-by: Friedemann Kleint --- src/corelib/kernel/qcoreapplication.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index b6b4da3885..c637f0c1c9 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -2668,9 +2668,9 @@ QStringList QCoreApplication::libraryPaths() QStringList *app_libpaths = new QStringList; coreappdata()->app_libpaths.reset(app_libpaths); - const QByteArray libPathEnv = qgetenv("QT_PLUGIN_PATH"); + QString libPathEnv = qEnvironmentVariable("QT_PLUGIN_PATH"); if (!libPathEnv.isEmpty()) { - QStringList paths = QFile::decodeName(libPathEnv).split(QDir::listSeparator(), QString::SkipEmptyParts); + QStringList paths = libPathEnv.split(QDir::listSeparator(), QString::SkipEmptyParts); for (QStringList::const_iterator it = paths.constBegin(); it != paths.constEnd(); ++it) { QString canonicalPath = QDir(*it).canonicalPath(); if (!canonicalPath.isEmpty() -- cgit v1.2.3 From 96404f7ac89244c944adaa7533c6292e7a614311 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Sat, 2 Feb 2019 08:00:15 -0800 Subject: Doc: update the note about nested deleteLater() If you enter a nested event loop, cause a deleteLater(), exit that event loop, then enter a new one, the nesting count will be the same so those are legitimate targets for deletion. Task-number: QTBUG-73432 Change-Id: Id98140e1c2f0426cabbefffd157f975b5e291ccd Reviewed-by: Paul Wicking Reviewed-by: Thiago Macieira --- src/corelib/kernel/qobject.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index b4e885e407..cf838b6947 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -2171,8 +2171,10 @@ void QObject::removeEventFilter(QObject *obj) Note that entering and leaving a new event loop (e.g., by opening a modal dialog) will \e not perform the deferred deletion; for the object to be - deleted, the control must return to the event loop from which - deleteLater() was called. + deleted, the control must return to the event loop from which deleteLater() + was called. This does not apply to objects deleted while a previous, nested + event loop was still running: the Qt event loop will delete those objects + as soon as the new nested event loop starts. \b{Note:} It is safe to call this function more than once; when the first deferred deletion event is delivered, any pending events for the -- cgit v1.2.3 From 2ec47d6cb53066b052c13d088e249a44f8a04c79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A5rten=20Nordheim?= Date: Tue, 26 Feb 2019 12:57:00 +0100 Subject: Fix crash in QTest's signal dumper It Q_ASSERTs that argv is not a nullptr, so it would fail when an unconnected signal with 0 arguments was emitted. Change-Id: I5dd810fbeea5b6b511eff4705efdaa6a55739604 Reviewed-by: Thiago Macieira --- src/corelib/kernel/qobject.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 1382015d76..63bb386107 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -3593,6 +3593,10 @@ void doActivate(QObject *sender, int signal_index, void **argv) const QSignalSpyCallbackSet *signal_spy_set = callbacks_enabled ? qt_signal_spy_callback_set.load() : nullptr; + void *empty_argv[] = { nullptr }; + if (!argv) + argv = empty_argv; + if (!sp->isSignalConnected(signal_index, false)) { // The possible declarative connection is done, and nothing else is connected if (callbacks_enabled && signal_spy_set->signal_begin_callback != nullptr) @@ -3604,10 +3608,6 @@ void doActivate(QObject *sender, int signal_index, void **argv) return; } - void *empty_argv[] = { nullptr }; - if (!argv) - argv = empty_argv; - if (callbacks_enabled && signal_spy_set->signal_begin_callback != nullptr) signal_spy_set->signal_begin_callback(sender, signal_index, argv); Q_TRACE(QMetaObject_activate_begin_signal, sender, signal_index); -- cgit v1.2.3 From 1270aeb0f96547ad32512c92ee2e69adb1f27011 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Fri, 22 Feb 2019 15:53:01 +0100 Subject: Fix typos in deprecation messages, noticed during code review Missing Q on the front of RegularExpression. Poor wording in QPixmap::fill() messages; and stray spaces at their starts. Task-number: QTBUG-73484 Change-Id: Ib953114c047afc37f0a903fcaaebfbc172079cbc Reviewed-by: Shawn Rutledge --- src/corelib/kernel/qobject.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qobject.h b/src/corelib/kernel/qobject.h index 52c1b8e555..63c5a9ad73 100644 --- a/src/corelib/kernel/qobject.h +++ b/src/corelib/kernel/qobject.h @@ -178,7 +178,7 @@ public: #ifndef QT_NO_REGEXP #if QT_DEPRECATED_SINCE(5, 13) template - QT_DEPRECATED_X("Use findChildren(const RegularExpression &, ...) instead.") + QT_DEPRECATED_X("Use findChildren(const QRegularExpression &, ...) instead.") inline QList findChildren(const QRegExp &re, Qt::FindChildOptions options = Qt::FindChildrenRecursively) const { typedef typename std::remove_cv::type>::type ObjType; -- cgit v1.2.3 From 18da1dac20c7d27342e987586a16d125e39197c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Thu, 17 Jan 2019 16:03:03 +0100 Subject: testlib: Prevent Apple test logger from stomping on other loggers We were potentially adding the Apple test logger multiple times, and we didn't consider whether the existing loggers were logging to file or not when circumventing them. We now don't use the Apple logger if it would touch stderr and some other logger is using stdout. In the case of no explicit logger being specified on the command line, we allow the Apple logger to take priority over the default plain test logger. Change-Id: I31bbec4f4b3ab84ba9a2be35e8e5db08fee071a7 Reviewed-by: Edward Welbourne --- src/corelib/kernel/qcore_mac.cpp | 23 ++++++++++++++--------- src/corelib/kernel/qcore_mac_p.h | 1 + 2 files changed, 15 insertions(+), 9 deletions(-) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qcore_mac.cpp b/src/corelib/kernel/qcore_mac.cpp index e78b2d1171..b048576f5b 100644 --- a/src/corelib/kernel/qcore_mac.cpp +++ b/src/corelib/kernel/qcore_mac.cpp @@ -65,6 +65,19 @@ QCFString::operator CFStringRef() const #if defined(QT_USE_APPLE_UNIFIED_LOGGING) +bool AppleUnifiedLogger::willMirrorToStderr() +{ + // When running under Xcode or LLDB, one or more of these variables will + // be set, which triggers libsystem_trace.dyld to log messages to stderr + // as well, via_os_log_impl_mirror_to_stderr. Un-setting these variables + // is not an option, as that would silence normal NSLog or os_log calls, + // so instead we skip our own stderr output. See rdar://36919139. + static bool willMirror = qEnvironmentVariableIsSet("OS_ACTIVITY_DT_MODE") + || qEnvironmentVariableIsSet("ACTIVITY_LOG_STDERR") + || qEnvironmentVariableIsSet("CFLOG_FORCE_STDERR"); + return willMirror; +} + QT_MAC_WEAK_IMPORT(_os_log_default); bool AppleUnifiedLogger::messageHandler(QtMsgType msgType, const QMessageLogContext &context, const QString &message, const QString &optionalSubsystem) @@ -103,15 +116,7 @@ bool AppleUnifiedLogger::messageHandler(QtMsgType msgType, const QMessageLogCont // system from redacting our log message. os_log_with_type(log, logType, "%{public}s", qPrintable(message)); - // When running under Xcode or LLDB, one or more of these variables will - // be set, which triggers libsystem_trace.dyld to log messages to stderr - // as well, via_os_log_impl_mirror_to_stderr. Un-setting these variables - // is not an option, as that would silence normal NSLog or os_log calls, - // so instead we skip our own stderr output. See rdar://36919139. - static bool mirroredToStderr = qEnvironmentVariableIsSet("OS_ACTIVITY_DT_MODE") - || qEnvironmentVariableIsSet("ACTIVITY_LOG_STDERR") - || qEnvironmentVariableIsSet("CFLOG_FORCE_STDERR"); - return mirroredToStderr; + return willMirrorToStderr(); } os_log_type_t AppleUnifiedLogger::logTypeForMessageType(QtMsgType msgType) diff --git a/src/corelib/kernel/qcore_mac_p.h b/src/corelib/kernel/qcore_mac_p.h index acb87f8a3c..f96e7358a2 100644 --- a/src/corelib/kernel/qcore_mac_p.h +++ b/src/corelib/kernel/qcore_mac_p.h @@ -202,6 +202,7 @@ class Q_CORE_EXPORT AppleUnifiedLogger public: static bool messageHandler(QtMsgType msgType, const QMessageLogContext &context, const QString &message, const QString &subsystem = QString()); + static bool willMirrorToStderr(); private: static os_log_type_t logTypeForMessageType(QtMsgType msgType); static os_log_t cachedLog(const QString &subsystem, const QString &category); -- cgit v1.2.3 From fed9fa171496fd24b264ef66e3e517d988fa3105 Mon Sep 17 00:00:00 2001 From: Christian Ehrlicher Date: Mon, 11 Mar 2019 22:00:27 +0100 Subject: Doc: replace 0 with \nullptr in documentation Replace some more 0 with \nullptr. Change-Id: I2af91bf3712eef5161b11da0c44614bc039ade03 Reviewed-by: Paul Wicking --- src/corelib/kernel/qobject.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 3a3eb726fa..15955e1665 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -2934,8 +2934,8 @@ QMetaObject::Connection QObject::connect(const QObject *sender, const QMetaMetho 0 may be used as a wildcard, meaning "any signal", "any receiving object", or "any slot in the receiving object", respectively. - The \a sender may never be 0. (You cannot disconnect signals from - more than one object in a single call.) + The \a sender may never be \nullptr. (You cannot disconnect signals + from more than one object in a single call.) If \a signal is 0, it disconnects \a receiver and \a method from any signal. If not, only the specified signal is disconnected. @@ -2946,8 +2946,8 @@ QMetaObject::Connection QObject::connect(const QObject *sender, const QMetaMetho If \a method is 0, it disconnects anything that is connected to \a receiver. If not, only slots named \a method will be disconnected, - and all other slots are left alone. The \a method must be 0 if \a - receiver is left out, so you cannot disconnect a + and all other slots are left alone. The \a method must be \nullptr + if \a receiver is left out, so you cannot disconnect a specifically-named slot on all objects. \sa connect() @@ -4991,8 +4991,8 @@ bool QObject::disconnect(const QMetaObject::Connection &connection) 0 may be used as a wildcard, meaning "any signal", "any receiving object", or "any slot in the receiving object", respectively. - The \a sender may never be 0. (You cannot disconnect signals from - more than one object in a single call.) + The \a sender may never be \nullptr. (You cannot disconnect signals + from more than one object in a single call.) If \a signal is 0, it disconnects \a receiver and \a method from any signal. If not, only the specified signal is disconnected. @@ -5003,8 +5003,8 @@ bool QObject::disconnect(const QMetaObject::Connection &connection) If \a method is 0, it disconnects anything that is connected to \a receiver. If not, only slots named \a method will be disconnected, - and all other slots are left alone. The \a method must be 0 if \a - receiver is left out, so you cannot disconnect a + and all other slots are left alone. The \a method must be \nullptr + if \a receiver is left out, so you cannot disconnect a specifically-named slot on all objects. \note It is not possible to use this overload to diconnect signals -- cgit v1.2.3 From 41e7b71c410b77a81d09d3cc2e169ffd7975b4d2 Mon Sep 17 00:00:00 2001 From: Kevin Funk Date: Tue, 12 Mar 2019 11:46:26 +0100 Subject: More nullptr usage in headers Diff generated by running clang-tidy's modernize-use-nullptr checker on the CMake-based Qt version. Skipping src/3rdparty, examples/, tests/ Change-Id: Ib182074e2e2fd52f63093f73b3e2e4c0cb7af188 Reviewed-by: Friedemann Kleint Reviewed-by: Simon Hausmann --- src/corelib/kernel/qcore_unix_p.h | 2 +- src/corelib/kernel/qcoreapplication_p.h | 2 +- src/corelib/kernel/qeventdispatcher_glib_p.h | 6 +++--- src/corelib/kernel/qeventdispatcher_unix_p.h | 10 +++++----- src/corelib/kernel/qmetaobject_moc_p.h | 4 ++-- src/corelib/kernel/qmetaobject_p.h | 4 ++-- src/corelib/kernel/qmetaobjectbuilder_p.h | 8 ++++---- src/corelib/kernel/qsharedmemory_p.h | 2 +- src/corelib/kernel/qvariant_p.h | 10 +++++----- 9 files changed, 24 insertions(+), 24 deletions(-) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qcore_unix_p.h b/src/corelib/kernel/qcore_unix_p.h index 5a2a29a327..32ef6408c2 100644 --- a/src/corelib/kernel/qcore_unix_p.h +++ b/src/corelib/kernel/qcore_unix_p.h @@ -171,7 +171,7 @@ inline void qt_ignore_sigpipe() struct sigaction noaction; memset(&noaction, 0, sizeof(noaction)); noaction.sa_handler = SIG_IGN; - ::sigaction(SIGPIPE, &noaction, 0); + ::sigaction(SIGPIPE, &noaction, nullptr); atom.store(1); } } diff --git a/src/corelib/kernel/qcoreapplication_p.h b/src/corelib/kernel/qcoreapplication_p.h index b3479414ab..14ca3efd7f 100644 --- a/src/corelib/kernel/qcoreapplication_p.h +++ b/src/corelib/kernel/qcoreapplication_p.h @@ -149,7 +149,7 @@ public: QString cachedApplicationDirPath; static QString *cachedApplicationFilePath; static void setApplicationFilePath(const QString &path); - static inline void clearApplicationFilePath() { delete cachedApplicationFilePath; cachedApplicationFilePath = 0; } + static inline void clearApplicationFilePath() { delete cachedApplicationFilePath; cachedApplicationFilePath = nullptr; } #ifndef QT_NO_QOBJECT void execCleanup(); diff --git a/src/corelib/kernel/qeventdispatcher_glib_p.h b/src/corelib/kernel/qeventdispatcher_glib_p.h index 88ff316ee5..313825d0a7 100644 --- a/src/corelib/kernel/qeventdispatcher_glib_p.h +++ b/src/corelib/kernel/qeventdispatcher_glib_p.h @@ -66,8 +66,8 @@ class Q_CORE_EXPORT QEventDispatcherGlib : public QAbstractEventDispatcher Q_DECLARE_PRIVATE(QEventDispatcherGlib) public: - explicit QEventDispatcherGlib(QObject *parent = 0); - explicit QEventDispatcherGlib(GMainContext *context, QObject *parent = 0); + explicit QEventDispatcherGlib(QObject *parent = nullptr); + explicit QEventDispatcherGlib(GMainContext *context, QObject *parent = nullptr); ~QEventDispatcherGlib(); bool processEvents(QEventLoop::ProcessEventsFlags flags) override; @@ -102,7 +102,7 @@ class Q_CORE_EXPORT QEventDispatcherGlibPrivate : public QAbstractEventDispatche { public: - QEventDispatcherGlibPrivate(GMainContext *context = 0); + QEventDispatcherGlibPrivate(GMainContext *context = nullptr); GMainContext *mainContext; GPostEventSource *postEventSource; GSocketNotifierSource *socketNotifierSource; diff --git a/src/corelib/kernel/qeventdispatcher_unix_p.h b/src/corelib/kernel/qeventdispatcher_unix_p.h index 0fd068b074..8cfa4bbdf7 100644 --- a/src/corelib/kernel/qeventdispatcher_unix_p.h +++ b/src/corelib/kernel/qeventdispatcher_unix_p.h @@ -102,7 +102,7 @@ class Q_CORE_EXPORT QEventDispatcherUNIX : public QAbstractEventDispatcher Q_DECLARE_PRIVATE(QEventDispatcherUNIX) public: - explicit QEventDispatcherUNIX(QObject *parent = 0); + explicit QEventDispatcherUNIX(QObject *parent = nullptr); ~QEventDispatcherUNIX(); bool processEvents(QEventLoop::ProcessEventsFlags flags) override; @@ -123,7 +123,7 @@ public: void flush() override; protected: - QEventDispatcherUNIX(QEventDispatcherUNIXPrivate &dd, QObject *parent = 0); + QEventDispatcherUNIX(QEventDispatcherUNIXPrivate &dd, QObject *parent = nullptr); }; class Q_CORE_EXPORT QEventDispatcherUNIXPrivate : public QAbstractEventDispatcherPrivate @@ -152,9 +152,9 @@ public: inline QSocketNotifierSetUNIX::QSocketNotifierSetUNIX() Q_DECL_NOTHROW { - notifiers[0] = 0; - notifiers[1] = 0; - notifiers[2] = 0; + notifiers[0] = nullptr; + notifiers[1] = nullptr; + notifiers[2] = nullptr; } inline bool QSocketNotifierSetUNIX::isEmpty() const Q_DECL_NOTHROW diff --git a/src/corelib/kernel/qmetaobject_moc_p.h b/src/corelib/kernel/qmetaobject_moc_p.h index ad258acfcd..8c7900767b 100644 --- a/src/corelib/kernel/qmetaobject_moc_p.h +++ b/src/corelib/kernel/qmetaobject_moc_p.h @@ -138,7 +138,7 @@ static QByteArray normalizeTypeInternal(const char *t, const char *e, bool fixSc { "struct ", 7 }, { "class ", 6 }, { "enum ", 5 }, - { 0, 0 } + { nullptr, 0 } }; int i = 0; do { @@ -146,7 +146,7 @@ static QByteArray normalizeTypeInternal(const char *t, const char *e, bool fixSc t += optional[i].len; break; } - } while (optional[++i].keyword != 0); + } while (optional[++i].keyword != nullptr); } bool star = false; diff --git a/src/corelib/kernel/qmetaobject_p.h b/src/corelib/kernel/qmetaobject_p.h index 5b412b5140..26d86fdf14 100644 --- a/src/corelib/kernel/qmetaobject_p.h +++ b/src/corelib/kernel/qmetaobject_p.h @@ -226,8 +226,8 @@ struct QMetaObjectPrivate static QObjectPrivate::Connection *connect(const QObject *sender, int signal_index, const QMetaObject *smeta, const QObject *receiver, int method_index_relative, - const QMetaObject *rmeta = 0, - int type = 0, int *types = 0); + const QMetaObject *rmeta = nullptr, + int type = 0, int *types = nullptr); static bool disconnect(const QObject *sender, int signal_index, const QMetaObject *smeta, const QObject *receiver, int method_index, void **slot, diff --git a/src/corelib/kernel/qmetaobjectbuilder_p.h b/src/corelib/kernel/qmetaobjectbuilder_p.h index 6100835bad..6d43be7811 100644 --- a/src/corelib/kernel/qmetaobjectbuilder_p.h +++ b/src/corelib/kernel/qmetaobjectbuilder_p.h @@ -173,7 +173,7 @@ public: void setStaticMetacallFunction(QMetaObjectBuilder::StaticMetacallFunction value); QMetaObject *toMetaObject() const; - QByteArray toRelocatableData(bool * = 0) const; + QByteArray toRelocatableData(bool * = nullptr) const; static void fromRelocatableData(QMetaObject *, const QMetaObject *, const QByteArray &); #ifndef QT_NO_DATASTREAM @@ -196,7 +196,7 @@ private: class Q_CORE_EXPORT QMetaMethodBuilder { public: - QMetaMethodBuilder() : _mobj(0), _index(0) {} + QMetaMethodBuilder() : _mobj(nullptr), _index(0) {} int index() const; @@ -238,7 +238,7 @@ private: class Q_CORE_EXPORT QMetaPropertyBuilder { public: - QMetaPropertyBuilder() : _mobj(0), _index(0) {} + QMetaPropertyBuilder() : _mobj(nullptr), _index(0) {} int index() const { return _index; } @@ -294,7 +294,7 @@ private: class Q_CORE_EXPORT QMetaEnumBuilder { public: - QMetaEnumBuilder() : _mobj(0), _index(0) {} + QMetaEnumBuilder() : _mobj(nullptr), _index(0) {} int index() const { return _index; } diff --git a/src/corelib/kernel/qsharedmemory_p.h b/src/corelib/kernel/qsharedmemory_p.h index 95fe0d1083..59802eb6ce 100644 --- a/src/corelib/kernel/qsharedmemory_p.h +++ b/src/corelib/kernel/qsharedmemory_p.h @@ -98,7 +98,7 @@ public: { if (q_sm && q_sm->lock()) return true; - q_sm = 0; + q_sm = nullptr; return false; } diff --git a/src/corelib/kernel/qvariant_p.h b/src/corelib/kernel/qvariant_p.h index b22b7c231e..3d87beac83 100644 --- a/src/corelib/kernel/qvariant_p.h +++ b/src/corelib/kernel/qvariant_p.h @@ -88,7 +88,7 @@ inline T *v_cast(const QVariant::Private *nd, T * = 0) #else // every other compiler in this world template -inline const T *v_cast(const QVariant::Private *d, T * = 0) +inline const T *v_cast(const QVariant::Private *d, T * = nullptr) { return !QVariantIntegrator::CanUseInternalSpace ? static_cast(d->data.shared->ptr) @@ -96,7 +96,7 @@ inline const T *v_cast(const QVariant::Private *d, T * = 0) } template -inline T *v_cast(QVariant::Private *d, T * = 0) +inline T *v_cast(QVariant::Private *d, T * = nullptr) { return !QVariantIntegrator::CanUseInternalSpace ? static_cast(d->data.shared->ptr) @@ -154,7 +154,7 @@ inline void v_construct(QVariant::Private *x, const T &t) // constructs a new variant if copy is 0, otherwise copy-constructs template -inline void v_construct(QVariant::Private *x, const void *copy, T * = 0) +inline void v_construct(QVariant::Private *x, const void *copy, T * = nullptr) { if (copy) v_construct(x, *static_cast(copy)); @@ -164,7 +164,7 @@ inline void v_construct(QVariant::Private *x, const void *copy, T * = 0) // deletes the internal structures template -inline void v_clear(QVariant::Private *d, T* = 0) +inline void v_clear(QVariant::Private *d, T* = nullptr) { if (!QVariantIntegrator::CanUseInternalSpace) { @@ -264,7 +264,7 @@ class QVariantIsNull struct No { char unused[2]; }; Q_STATIC_ASSERT(sizeof(Yes) != sizeof(No)); - template static decltype(static_cast(0)->isNull(), Yes()) test(int); + template static decltype(static_cast(nullptr)->isNull(), Yes()) test(int); template static No test(...); public: static const bool Value = (sizeof(test(0)) == sizeof(Yes)); -- cgit v1.2.3 From c0b265662e618f0d953ed2c389bad9f50ac24f7f Mon Sep 17 00:00:00 2001 From: Anton Kudryavtsev Date: Mon, 15 Oct 2018 20:36:06 +0300 Subject: QTranslator: avoid unhandled exception Add std::nothrow param to avoid exception and to check pointer against nullptr. Change-Id: I505abb1ca15b8c10a80b0cd3784a6b0c4c6bcc1c Reviewed-by: Edward Welbourne Reviewed-by: Oswald Buddenhagen Reviewed-by: Allan Sandfeld Jensen --- src/corelib/kernel/qtranslator.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qtranslator.cpp b/src/corelib/kernel/qtranslator.cpp index 744bbfbff5..929554f6bc 100644 --- a/src/corelib/kernel/qtranslator.cpp +++ b/src/corelib/kernel/qtranslator.cpp @@ -72,6 +72,7 @@ #endif #include +#include #include "qobject_p.h" @@ -592,7 +593,7 @@ bool QTranslatorPrivate::do_load(const QString &realname, const QString &directo #endif // QT_USE_MMAP if (!ok) { - d->unmapPointer = new char[d->unmapLength]; + d->unmapPointer = new (std::nothrow) char[d->unmapLength]; if (d->unmapPointer) { file.seek(0); qint64 readResult = file.read(d->unmapPointer, d->unmapLength); -- cgit v1.2.3 From 84aea6c091d020a37c2b452a6f56ca27b3b2c7cb Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Wed, 13 Mar 2019 18:49:04 +0100 Subject: Add qFpClassify() to mirror std::fpclassify() The rules of std don't permit us to add an overload for fpclassify(qfloat16), so we need our own equivalent that we *can* overload. Deploy it in the few places we use fpclassify(). Extended qnumeric's testing to cover qFpClassify(). Change-Id: Ie5a0a5cc24599d1571404c573d33c682b0d305a5 Reviewed-by: Thiago Macieira Reviewed-by: Paul Wicking --- src/corelib/kernel/qvariant.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp index 18c7f7648d..deba977f77 100644 --- a/src/corelib/kernel/qvariant.cpp +++ b/src/corelib/kernel/qvariant.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2019 The Qt Company Ltd. ** Copyright (C) 2018 Intel Corporation. ** Copyright (C) 2015 Olivier Goffart ** Contact: https://www.qt.io/licensing/ @@ -4002,8 +4002,8 @@ static int numericCompare(const QVariant::Private *d1, const QVariant::Private * return 0; // only do fuzzy comparisons for finite, non-zero numbers - int c1 = std::fpclassify(r1); - int c2 = std::fpclassify(r2); + int c1 = qFpClassify(r1); + int c2 = qFpClassify(r2); if ((c1 == FP_NORMAL || c1 == FP_SUBNORMAL) && (c2 == FP_NORMAL || c2 == FP_SUBNORMAL)) { if (qFuzzyCompare(r1, r2)) return 0; -- cgit v1.2.3 From 758151d077536eb8fe2cd1a3252dec5619b9789f Mon Sep 17 00:00:00 2001 From: Timo Lang Date: Wed, 20 Mar 2019 09:50:51 +0100 Subject: QVariant: Fix isNull() == true after downcasting QObject* MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ChangeLog][QtCore][QVariant] Fixed a bug that caused isNull() to be true after downcasting a QObject* payload using convert(). Fixes: QTBUG-73196 Change-Id: Ifda15952f873d7142c95609b69ac424bbf16b723 Reviewed-by: Thiago Macieira Reviewed-by: Jędrzej Nowacki --- src/corelib/kernel/qvariant.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp index deba977f77..77d2c8cbe1 100644 --- a/src/corelib/kernel/qvariant.cpp +++ b/src/corelib/kernel/qvariant.cpp @@ -1462,6 +1462,7 @@ static void customConstruct(QVariant::Private *d, const void *copy) if (size <= sizeof(QVariant::Private::Data) && (type.flags() & (QMetaType::MovableType | QMetaType::IsEnumeration))) { type.construct(&d->data.ptr, copy); + d->is_null = d->data.ptr == nullptr; d->is_shared = false; } else { // Private::Data contains long long, and long double is the biggest standard type. @@ -1472,6 +1473,7 @@ static void customConstruct(QVariant::Private *d, const void *copy) void *data = operator new(offset + size); void *ptr = static_cast(data) + offset; type.construct(ptr, copy); + d->is_null = ptr == nullptr; d->is_shared = true; d->data.shared = new (data) QVariant::PrivateShared(ptr); } -- cgit v1.2.3 From 12bc039baa2672c98518277ea146bedec3a92ac0 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Thu, 21 Mar 2019 13:03:21 +0100 Subject: Don't iterate over the connections without holding a lock When checking whether a slot is connected to a signal, we need to hold the signalSlotLock to be sure about the answer, or we can get crashes when a connection gets removed while doing the check. The check in activate() can handle some uncertainty as it's only a shortcut to the longer path. Fixes: QTBUG-74604 Change-Id: I3fc822455fbadc0223ef68632f5fb3df3ff3e86d Reviewed-by: Aapo Keskimolo --- src/corelib/kernel/qobject.cpp | 18 +++++++++++++++++- src/corelib/kernel/qobject_p.h | 1 + 2 files changed, 18 insertions(+), 1 deletion(-) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 759ccaacd8..268f3949fd 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -415,6 +415,22 @@ bool QObjectPrivate::isSignalConnected(uint signalIndex, bool checkDeclarative) return false; } +bool QObjectPrivate::maybeSignalConnected(uint signalIndex) const +{ + ConnectionData *cd = connections.load(); + if (!cd) + return false; + + if (cd->allsignals.first) + return true; + + if (signalIndex < uint(cd->signalVector.count())) { + const QObjectPrivate::Connection *c = cd->signalVector.at(signalIndex).first; + return c != nullptr; + } + return false; +} + /*! \internal @@ -3599,7 +3615,7 @@ void doActivate(QObject *sender, int signal_index, void **argv) if (!argv) argv = empty_argv; - if (!sp->isSignalConnected(signal_index, false)) { + if (!sp->maybeSignalConnected(signal_index)) { // The possible declarative connection is done, and nothing else is connected if (callbacks_enabled && signal_spy_set->signal_begin_callback != nullptr) signal_spy_set->signal_begin_callback(sender, signal_index, argv); diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h index 823c7a195a..863689fddd 100644 --- a/src/corelib/kernel/qobject_p.h +++ b/src/corelib/kernel/qobject_p.h @@ -254,6 +254,7 @@ public: int signalIndex(const char *signalName, const QMetaObject **meta = nullptr) const; bool isSignalConnected(uint signalIdx, bool checkDeclarative = true) const; + bool maybeSignalConnected(uint signalIndex) const; inline bool isDeclarativeSignalConnected(uint signalIdx) const; // To allow abitrary objects to call connectNotify()/disconnectNotify() without making -- cgit v1.2.3 From 3b38c73c7ffa71c00c172cf0e05742835a304300 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 22 Mar 2019 11:20:31 +0100 Subject: Widen out parameter "result" of the native event filters for Qt 6 LRESULT on Windows 64 is a 64bit type, adapt filter functions of QAbstractNativeEventFilter and QAbstractEventDispatcher accordingly. Fixes: QTBUG-72968 Change-Id: Ie53193e355f0b8e9bd59fa377f43e2b4664a2ded Reviewed-by: Thiago Macieira --- src/corelib/kernel/qabstracteventdispatcher.cpp | 4 ++++ src/corelib/kernel/qabstracteventdispatcher.h | 4 ++++ src/corelib/kernel/qabstractnativeeventfilter.cpp | 1 + src/corelib/kernel/qabstractnativeeventfilter.h | 4 ++++ src/corelib/kernel/qeventdispatcher_win.cpp | 4 ++++ 5 files changed, 17 insertions(+) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qabstracteventdispatcher.cpp b/src/corelib/kernel/qabstracteventdispatcher.cpp index 8e1b560874..0ecfc7a8c7 100644 --- a/src/corelib/kernel/qabstracteventdispatcher.cpp +++ b/src/corelib/kernel/qabstracteventdispatcher.cpp @@ -470,7 +470,11 @@ void QAbstractEventDispatcher::removeNativeEventFilter(QAbstractNativeEventFilte \sa installNativeEventFilter(), QAbstractNativeEventFilter::nativeEventFilter() \since 5.0 */ +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) +bool QAbstractEventDispatcher::filterNativeEvent(const QByteArray &eventType, void *message, qintptr *result) +#else bool QAbstractEventDispatcher::filterNativeEvent(const QByteArray &eventType, void *message, long *result) +#endif { Q_D(QAbstractEventDispatcher); if (!d->eventFilters.isEmpty()) { diff --git a/src/corelib/kernel/qabstracteventdispatcher.h b/src/corelib/kernel/qabstracteventdispatcher.h index bd8da5c35d..4ef9c068df 100644 --- a/src/corelib/kernel/qabstracteventdispatcher.h +++ b/src/corelib/kernel/qabstracteventdispatcher.h @@ -110,7 +110,11 @@ public: void installNativeEventFilter(QAbstractNativeEventFilter *filterObj); void removeNativeEventFilter(QAbstractNativeEventFilter *filterObj); +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + bool filterNativeEvent(const QByteArray &eventType, void *message, qintptr *result); +#else bool filterNativeEvent(const QByteArray &eventType, void *message, long *result); +#endif #if QT_DEPRECATED_SINCE(5, 0) QT_DEPRECATED bool filterEvent(void *message) { return filterNativeEvent("", message, nullptr); } diff --git a/src/corelib/kernel/qabstractnativeeventfilter.cpp b/src/corelib/kernel/qabstractnativeeventfilter.cpp index dcbb92f044..eaadea4c12 100644 --- a/src/corelib/kernel/qabstractnativeeventfilter.cpp +++ b/src/corelib/kernel/qabstractnativeeventfilter.cpp @@ -74,6 +74,7 @@ QAbstractNativeEventFilter::~QAbstractNativeEventFilter() eventDispatcher->removeNativeEventFilter(this); } +// ### fixme Qt 6: result will be qintptr * /*! \fn bool QAbstractNativeEventFilter::nativeEventFilter(const QByteArray &eventType, void *message, long *result) diff --git a/src/corelib/kernel/qabstractnativeeventfilter.h b/src/corelib/kernel/qabstractnativeeventfilter.h index d7baa42513..a468bffd61 100644 --- a/src/corelib/kernel/qabstractnativeeventfilter.h +++ b/src/corelib/kernel/qabstractnativeeventfilter.h @@ -52,7 +52,11 @@ public: QAbstractNativeEventFilter(); virtual ~QAbstractNativeEventFilter(); +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + virtual bool nativeEventFilter(const QByteArray &eventType, void *message, qintptr *result) = 0; +#else virtual bool nativeEventFilter(const QByteArray &eventType, void *message, long *result) = 0; +#endif private: Q_DISABLE_COPY(QAbstractNativeEventFilter) diff --git a/src/corelib/kernel/qeventdispatcher_win.cpp b/src/corelib/kernel/qeventdispatcher_win.cpp index 685d765adb..84378454ca 100644 --- a/src/corelib/kernel/qeventdispatcher_win.cpp +++ b/src/corelib/kernel/qeventdispatcher_win.cpp @@ -136,7 +136,11 @@ LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPA msg.wParam = wp; msg.lParam = lp; QAbstractEventDispatcher* dispatcher = QAbstractEventDispatcher::instance(); +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + qintptr result; +#else long result; +#endif if (!dispatcher) { if (message == WM_TIMER) KillTimer(hwnd, wp); -- cgit v1.2.3 From aec284dfc9179088e34fcb7e4bc9cbce71cb68db Mon Sep 17 00:00:00 2001 From: Albert Astals Cid Date: Mon, 25 Mar 2019 10:17:21 +0100 Subject: Doc: mention what is the suggested replacement for QSignalMapper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I0f230c8b59eae4b2b63a73b8223ed99545be44ec Reviewed-by: Jędrzej Nowacki --- src/corelib/kernel/qsignalmapper.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qsignalmapper.cpp b/src/corelib/kernel/qsignalmapper.cpp index d56965281e..02a1281f92 100644 --- a/src/corelib/kernel/qsignalmapper.cpp +++ b/src/corelib/kernel/qsignalmapper.cpp @@ -61,7 +61,7 @@ public: /*! \class QSignalMapper \inmodule QtCore - \obsolete + \obsolete The recommended solution is connecting the signal to a lambda. \brief The QSignalMapper class bundles signals from identifiable senders. \ingroup objectmodel -- cgit v1.2.3 From 6e0b5dadc7e91be786411809f1f9667c239168e2 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Wed, 9 Jan 2019 19:12:46 +0100 Subject: Change cleanup mechanism for orphaned connections Put all connections that get disconnected into a singly linked orphaned list. Whenever the refcount on the connectionData drops down to one, this list can safely be cleared, even with the planned removal of locking in activate(). Use an id integer in the connection to acoid activating newly added connections. Fixes: QTBUG-72649 Change-Id: Ide3d116ae7fc9ca497598c1c2b71d43b4339c92d Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/kernel/qmetaobject_p.h | 2 +- src/corelib/kernel/qobject.cpp | 185 +++++++++++++------------------------ src/corelib/kernel/qobject_p.h | 109 ++++++++++++++++++++-- 3 files changed, 165 insertions(+), 131 deletions(-) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qmetaobject_p.h b/src/corelib/kernel/qmetaobject_p.h index 26d86fdf14..0cd9da2eac 100644 --- a/src/corelib/kernel/qmetaobject_p.h +++ b/src/corelib/kernel/qmetaobject_p.h @@ -232,7 +232,7 @@ struct QMetaObjectPrivate const QMetaObject *smeta, const QObject *receiver, int method_index, void **slot, DisconnectType = DisconnectAll); - static inline bool disconnectHelper(QObjectPrivate::Connection *c, + static inline bool disconnectHelper(QObjectPrivate::ConnectionData *connections, int signalIndex, const QObject *receiver, int method_index, void **slot, QBasicMutex *senderMutex, DisconnectType = DisconnectAll); #endif diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 268f3949fd..77e58abfa2 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2019 The Qt Company Ltd. ** Copyright (C) 2016 Intel Corporation. ** Copyright (C) 2013 Olivier Goffart ** Contact: https://www.qt.io/licensing/ @@ -332,14 +332,15 @@ void QObjectPrivate::addConnection(int signal, Connection *c) ConnectionList &connectionList = cd->connectionsForSignal(signal); if (connectionList.last) { + Q_ASSERT(connectionList.last->receiver); connectionList.last->nextConnectionList = c; } else { connectionList.first = c; } + c->id = ++cd->currentConnectionId; + c->prevConnectionList = connectionList.last; connectionList.last = c; - cleanConnectionLists(); - QObjectPrivate *rd = QObjectPrivate::get(c->receiver); rd->ensureConnectionData(); @@ -350,39 +351,27 @@ void QObjectPrivate::addConnection(int signal, Connection *c) c->next->prev = &c->next; } -void QObjectPrivate::cleanConnectionLists() +void QObjectPrivate::ConnectionData::cleanOrphanedConnectionsImpl(QObject *sender) { - ConnectionData *cd = connections.load(); - if (cd->dirty && cd->ref == 1) { - // remove broken connections - for (int signal = -1; signal < cd->signalVector.count(); ++signal) { - ConnectionList &connectionList = cd->connectionsForSignal(signal); - - // Set to the last entry in the connection list that was *not* - // deleted. This is needed to update the list's last pointer - // at the end of the cleanup. - QObjectPrivate::Connection *last = 0; - - QObjectPrivate::Connection **prev = &connectionList.first; - QObjectPrivate::Connection *c = *prev; - while (c) { - if (c->receiver) { - last = c; - prev = &c->nextConnectionList; - c = *prev; - } else { - QObjectPrivate::Connection *next = c->nextConnectionList; - *prev = next; - c->deref(); - c = next; - } - } + Connection *c = nullptr; + { + QBasicMutexLocker l(signalSlotLock(sender)); + if (ref > 1) + return; - // Correct the connection list's last pointer. - // As conectionList.last could equal last, this could be a noop - connectionList.last = last; - } - cd->dirty = false; + // Since ref == 1, no activate() is in process since we locked the mutex. That implies, + // that nothing can reference the orphaned connection objects anymore and they can + // be safely deleted + c = orphaned.load(); + orphaned.store(nullptr); + } + while (c) { + Q_ASSERT(!c->receiver); + Q_ASSERT(!c->prev); + QObjectPrivate::Connection *next = c->nextInOrphanList; + c->freeSlotObject(); + c->deref(); + c = next; } } @@ -905,47 +894,22 @@ QObject::~QObject() QObjectPrivate::ConnectionList &connectionList = cd->connectionsForSignal(signal); while (QObjectPrivate::Connection *c = connectionList.first) { - if (!c->receiver) { - connectionList.first = c->nextConnectionList; - c->deref(); - continue; - } + Q_ASSERT(c->receiver); QBasicMutex *m = signalSlotLock(c->receiver); bool needToUnlock = QOrderedMutexLocker::relock(signalSlotMutex, m); - if (c->receiver) { - *c->prev = c->next; - if (c->next) c->next->prev = c->prev; + cd->removeConnection(c); + Q_ASSERT(connectionList.first != c); } - c->receiver = 0; if (needToUnlock) m->unlock(); - - connectionList.first = c->nextConnectionList; - - // The destroy operation must happen outside the lock - if (c->isSlotObject) { - c->isSlotObject = false; - locker.unlock(); - c->slotObj->destroyIfLastRef(); - locker.relock(); - } - c->deref(); } } /* Disconnect all senders: - * This loop basically just does - * for (node = d->senders; node; node = node->next) { ... } - * - * We need to temporarily unlock the receiver mutex to destroy the functors or to lock the - * sender's mutex. And when the mutex is released, node->next might be destroyed by another - * thread. That's why we set node->prev to &node, that way, if node is destroyed, node will - * be updated. */ - QObjectPrivate::Connection *node = cd->senders; - while (node) { + while (QObjectPrivate::Connection *node = cd->senders) { Q_ASSERT(node->receiver); QObject *sender = node->sender; // Send disconnectNotify before removing the connection from sender's connection list. @@ -953,19 +917,17 @@ QObject::~QObject() // and not finish until we release it. sender->disconnectNotify(QMetaObjectPrivate::signal(sender->metaObject(), node->signal_index)); QBasicMutex *m = signalSlotLock(sender); - node->prev = &node; bool needToUnlock = QOrderedMutexLocker::relock(signalSlotMutex, m); //the node has maybe been removed while the mutex was unlocked in relock? - if (!node || node->sender != sender) { + if (node != cd->senders) { // We hold the wrong mutex Q_ASSERT(needToUnlock); m->unlock(); continue; } - node->receiver = 0; + QObjectPrivate::ConnectionData *senderData = sender->d_func()->connections.load(); - if (senderData) - senderData->dirty = true; + Q_ASSERT(senderData); QtPrivate::QSlotObjectBase *slotObj = nullptr; if (node->isSlotObject) { @@ -973,20 +935,20 @@ QObject::~QObject() node->isSlotObject = false; } - node = node->next; + senderData->removeConnection(node); if (needToUnlock) m->unlock(); if (slotObj) { - if (node) - node->prev = &node; locker.unlock(); slotObj->destroyIfLastRef(); locker.relock(); } } - cd->objectDeleted = true; + // invalidate all connections on the object and make sure + // activate() will skip them + cd->currentConnectionId.store(0); } if (cd && !cd->ref.deref()) delete cd; @@ -3333,16 +3295,19 @@ bool QMetaObject::disconnectOne(const QObject *sender, int signal_index, \internal Helper function to remove the connection from the senders list and setting the receivers to 0 */ -bool QMetaObjectPrivate::disconnectHelper(QObjectPrivate::Connection *c, +bool QMetaObjectPrivate::disconnectHelper(QObjectPrivate::ConnectionData *connections, int signalIndex, const QObject *receiver, int method_index, void **slot, QBasicMutex *senderMutex, DisconnectType disconnectType) { bool success = false; + + auto &connectionList = connections->connectionsForSignal(signalIndex); + auto *c = connectionList.first; while (c) { if (c->receiver - && (receiver == 0 || (c->receiver == receiver + && (receiver == nullptr || (c->receiver == receiver && (method_index < 0 || (!c->isSlotObject && c->method() == method_index)) - && (slot == 0 || (c->isSlotObject && c->slotObj->compare(slot)))))) { + && (slot == nullptr || (c->isSlotObject && c->slotObj->compare(slot)))))) { bool needToUnlock = false; QBasicMutex *receiverMutex = nullptr; if (c->receiver) { @@ -3350,24 +3315,12 @@ bool QMetaObjectPrivate::disconnectHelper(QObjectPrivate::Connection *c, // need to relock this receiver and sender in the correct order needToUnlock = QOrderedMutexLocker::relock(senderMutex, receiverMutex); } - if (c->receiver) { - *c->prev = c->next; - if (c->next) - c->next->prev = c->prev; - } + if (c->receiver) + connections->removeConnection(c); if (needToUnlock) receiverMutex->unlock(); - c->receiver = 0; - - if (c->isSlotObject) { - c->isSlotObject = false; - senderMutex->unlock(); - c->slotObj->destroyIfLastRef(); - senderMutex->lock(); - } - success = true; if (disconnectType == DisconnectOne) @@ -3407,23 +3360,19 @@ bool QMetaObjectPrivate::disconnect(const QObject *sender, if (signal_index < 0) { // remove from all connection lists for (int sig_index = -1; sig_index < scd->signalVector.count(); ++sig_index) { - QObjectPrivate::Connection *c = scd->connectionsForSignal(sig_index).first; - if (disconnectHelper(c, receiver, method_index, slot, senderMutex, disconnectType)) { + if (disconnectHelper(connections.data(), sig_index, receiver, method_index, slot, senderMutex, disconnectType)) success = true; - scd->dirty = true; - } } } else if (signal_index < scd->signalVector.count()) { - QObjectPrivate::Connection *c = scd->signalVector.at(signal_index).first; - if (disconnectHelper(c, receiver, method_index, slot, senderMutex, disconnectType)) { + if (disconnectHelper(connections.data(), signal_index, receiver, method_index, slot, senderMutex, disconnectType)) success = true; - scd->dirty = true; - } } } locker.unlock(); if (success) { + scd->cleanOrphanedConnections(s); + QMetaMethod smethod = QMetaObjectPrivate::signal(smeta, signal_index); if (smethod.isValid()) s->disconnectNotify(smethod); @@ -3630,6 +3579,7 @@ void doActivate(QObject *sender, int signal_index, void **argv) signal_spy_set->signal_begin_callback(sender, signal_index, argv); Q_TRACE(QMetaObject_activate_begin_signal, sender, signal_index); + bool senderDeleted = false; { QBasicMutexLocker locker(signalSlotLock(sender)); Q_ASSERT(sp->connections); @@ -3643,12 +3593,13 @@ void doActivate(QObject *sender, int signal_index, void **argv) Qt::HANDLE currentThreadId = QThread::currentThreadId(); + // We need to check against the highest connection id to ensure that signals added + // during the signal emission are not emitted in this emission. + uint highestConnectionId = connections->currentConnectionId.load(); do { QObjectPrivate::Connection *c = list->first; - if (!c) continue; - // We need to check against last here to ensure that signals added - // during the signal emission are not emitted in this emission. - QObjectPrivate::Connection *last = list->last; + if (!c) + continue; do { if (!c->receiver) @@ -3732,18 +3683,17 @@ void doActivate(QObject *sender, int signal_index, void **argv) locker.relock(); } + } while ((c = c->nextConnectionList) != 0 && c->id <= highestConnectionId); - if (connections->objectDeleted) - break; - } while (c != last && (c = c->nextConnectionList) != 0); - - if (connections->objectDeleted) - break; } while (list != &connections->allsignals && //start over for all signals; ((list = &connections->allsignals), true)); + if (connections->currentConnectionId.load() == 0) + senderDeleted = true; } + if (!senderDeleted) + sp->connections.load()->cleanOrphanedConnections(sender); if (callbacks_enabled && signal_spy_set->signal_end_callback != nullptr) signal_spy_set->signal_end_callback(sender, signal_index); @@ -4859,30 +4809,25 @@ bool QObject::disconnect(const QMetaObject::Connection &connection) { QObjectPrivate::Connection *c = static_cast(connection.d_ptr); - if (!c || !c->receiver) + if (!c) return false; QBasicMutex *senderMutex = signalSlotLock(c->sender); QBasicMutex *receiverMutex = signalSlotLock(c->receiver); + QObjectPrivate::ConnectionData *connections; { QOrderedMutexLocker locker(senderMutex, receiverMutex); - QObjectPrivate::ConnectionData *connections = QObjectPrivate::get(c->sender)->connections.load(); - Q_ASSERT(connections); - connections->dirty = true; + if (!c->receiver) + return false; - *c->prev = c->next; - if (c->next) - c->next->prev = c->prev; - c->receiver = nullptr; + connections = QObjectPrivate::get(c->sender)->connections.load(); + Q_ASSERT(connections); + connections->removeConnection(c); } - // destroy the QSlotObject, if possible - if (c->isSlotObject) { - c->slotObj->destroyIfLastRef(); - c->isSlotObject = false; - } + connections->cleanOrphanedConnections(c->sender); c->sender->disconnectNotify(QMetaObjectPrivate::signal(c->sender->metaObject(), c->signal_index)); diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h index 863689fddd..2c1502c2a0 100644 --- a/src/corelib/kernel/qobject_p.h +++ b/src/corelib/kernel/qobject_p.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2017 The Qt Company Ltd. +** Copyright (C) 2019 The Qt Company Ltd. ** Copyright (C) 2013 Olivier Goffart ** Contact: https://www.qt.io/licensing/ ** @@ -126,22 +126,29 @@ public: typedef void (*StaticMetaCallFunction)(QObject *, QMetaObject::Call, int, void **); struct Connection { + union { + // linked list of orphaned connections that need cleaning up + Connection *nextInOrphanList; + // linked list of connections connected to slots in this object + Connection *next; + }; + Connection **prev; + // linked list of connections connected to signals in this object + Connection *nextConnectionList; + Connection *prevConnectionList; + QObject *sender; QObject *receiver; union { StaticMetaCallFunction callFunction; QtPrivate::QSlotObjectBase *slotObj; }; - // The next pointer for the singly-linked ConnectionList - Connection *nextConnectionList; - //senders linked list - Connection *next; - Connection **prev; QAtomicPointer argumentTypes; QAtomicInt ref_; + uint id = 0; ushort method_offset; ushort method_relative; - uint signal_index : 27; // In signal range (see QObjectPrivate::signalIndex()) + int signal_index : 27; // In signal range (see QObjectPrivate::signalIndex()) ushort connectionType : 3; // 0 == auto, 1 == direct, 2 == queued, 4 == blocking ushort isSlotObject : 1; ushort ownArgumentTypes : 1; @@ -151,9 +158,17 @@ public: ~Connection(); int method() const { Q_ASSERT(!isSlotObject); return method_offset + method_relative; } void ref() { ref_.ref(); } + void freeSlotObject() + { + if (isSlotObject) { + slotObj->destroyIfLastRef(); + isSlotObject = false; + } + } void deref() { if (!ref_.deref()) { Q_ASSERT(!receiver); + Q_ASSERT(!isSlotObject); delete this; } } @@ -210,7 +225,9 @@ public: linked list. */ struct ConnectionData { - bool objectDeleted = false; //the QObject owner of this vector has been destroyed while the vector was inUse + // the id below is used to avoid activating new connections. When the object gets + // deleted it's set to 0, so that signal emission stops + QAtomicInteger currentConnectionId; struct Ref { int _ref = 0; void ref() { ++_ref; } @@ -219,11 +236,84 @@ public: }; Ref ref; - bool dirty = false; //some Connection have been disconnected (their receiver is 0) but not removed from the list yet ConnectionList allsignals; QVector signalVector; Connection *senders = nullptr; Sender *currentSender = nullptr; // object currently activating the object + QAtomicPointer orphaned; + + ~ConnectionData() + { + Connection *c = orphaned.load(); + while (c) { + Q_ASSERT(!c->receiver); + QObjectPrivate::Connection *next = c->nextInOrphanList; + c->freeSlotObject(); + c->deref(); + c = next; + } + } + + // must be called on the senders connection data + // assumes the senders and receivers lock are held + void removeConnection(Connection *c) + { + Q_ASSERT(c->receiver); + ConnectionList &connections = connectionsForSignal(c->signal_index); + c->receiver = nullptr; + +#ifndef QT_NO_DEBUG + bool found = false; + for (Connection *cc = connections.first; cc; cc = cc->nextConnectionList) { + if (cc == c) { + found = true; + break; + } + } + Q_ASSERT(found); +#endif + + // remove from the senders linked list + *c->prev = c->next; + if (c->next) + c->next->prev = c->prev; + c->prev = nullptr; + + if (connections.first == c) + connections.first = c->nextConnectionList; + if (connections.last == c) + connections.last = c->prevConnectionList; + + // keep c->nextConnectionList intact, as it might still get accessed by activate + if (c->nextConnectionList) + c->nextConnectionList->prevConnectionList = c->prevConnectionList; + if (c->prevConnectionList) + c->prevConnectionList->nextConnectionList = c->nextConnectionList; + c->prevConnectionList = nullptr; + + Q_ASSERT(c != orphaned.load()); + // add c to orphanedConnections + c->nextInOrphanList = orphaned.load(); + orphaned.store(c); + +#ifndef QT_NO_DEBUG + found = false; + for (Connection *cc = connections.first; cc; cc = cc->nextConnectionList) { + if (cc == c) { + found = true; + break; + } + } + Q_ASSERT(!found); +#endif + + } + void cleanOrphanedConnections(QObject *sender) + { + if (orphaned.load() && ref == 1) + cleanOrphanedConnectionsImpl(sender); + } + void cleanOrphanedConnectionsImpl(QObject *sender); ConnectionList &connectionsForSignal(int signal) { @@ -245,7 +335,6 @@ public: QObjectList senderList() const; void addConnection(int signal, Connection *c); - void cleanConnectionLists(); static QObjectPrivate *get(QObject *o) { return o->d_func(); -- cgit v1.2.3 From 999c26dd83ad37fcd7a2b2fc62c0281f38c8e6e0 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Fri, 1 Feb 2019 12:49:16 +0100 Subject: Add a QAbstractMetaCallEvent And use it to clean up the reimplementations in Qt DBus. Change-Id: I8e3fe35e8db6405cbcbfb45b42a8f2efecc1cef0 Reviewed-by: Thiago Macieira Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/kernel/qobject.cpp | 26 ++++++++++++++++---------- src/corelib/kernel/qobject_p.h | 30 ++++++++++++++++++++++-------- 2 files changed, 38 insertions(+), 18 deletions(-) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 77e58abfa2..a0e4450d28 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -420,6 +420,16 @@ bool QObjectPrivate::maybeSignalConnected(uint signalIndex) const return false; } +/*! + \internal + */ +QAbstractMetaCallEvent::~QAbstractMetaCallEvent() +{ +#if QT_CONFIG(thread) + if (semaphore_) + semaphore_->release(); +#endif +} /*! \internal @@ -427,8 +437,8 @@ bool QObjectPrivate::maybeSignalConnected(uint signalIndex) const QMetaCallEvent::QMetaCallEvent(ushort method_offset, ushort method_relative, QObjectPrivate::StaticMetaCallFunction callFunction, const QObject *sender, int signalId, int nargs, int *types, void **args, QSemaphore *semaphore) - : QEvent(MetaCall), slotObj_(0), sender_(sender), signalId_(signalId), - nargs_(nargs), types_(types), args_(args), semaphore_(semaphore), + : QAbstractMetaCallEvent(sender, signalId, semaphore), + slotObj_(nullptr), nargs_(nargs), types_(types), args_(args), callFunction_(callFunction), method_offset_(method_offset), method_relative_(method_relative) { } @@ -437,9 +447,9 @@ QMetaCallEvent::QMetaCallEvent(ushort method_offset, ushort method_relative, QOb */ QMetaCallEvent::QMetaCallEvent(QtPrivate::QSlotObjectBase *slotO, const QObject *sender, int signalId, int nargs, int *types, void **args, QSemaphore *semaphore) - : QEvent(MetaCall), slotObj_(slotO), sender_(sender), signalId_(signalId), - nargs_(nargs), types_(types), args_(args), semaphore_(semaphore), - callFunction_(0), method_offset_(0), method_relative_(ushort(-1)) + : QAbstractMetaCallEvent(sender, signalId, semaphore), + slotObj_(slotO), nargs_(nargs), types_(types), args_(args), + callFunction_(nullptr), method_offset_(0), method_relative_(ushort(-1)) { if (slotObj_) slotObj_->ref(); @@ -458,10 +468,6 @@ QMetaCallEvent::~QMetaCallEvent() free(types_); free(args_); } -#if QT_CONFIG(thread) - if (semaphore_) - semaphore_->release(); -#endif if (slotObj_) slotObj_->destroyIfLastRef(); } @@ -1179,7 +1185,7 @@ bool QObject::event(QEvent *e) case QEvent::MetaCall: { - QMetaCallEvent *mce = static_cast(e); + QAbstractMetaCallEvent *mce = static_cast(e); if (!d_func()->connections.load()) { QBasicMutexLocker locker(signalSlotLock(this)); diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h index 2c1502c2a0..da3d035087 100644 --- a/src/corelib/kernel/qobject_p.h +++ b/src/corelib/kernel/qobject_p.h @@ -485,7 +485,26 @@ Q_DECLARE_TYPEINFO(QObjectPrivate::Connection, Q_MOVABLE_TYPE); Q_DECLARE_TYPEINFO(QObjectPrivate::Sender, Q_MOVABLE_TYPE); class QSemaphore; -class Q_CORE_EXPORT QMetaCallEvent : public QEvent +class Q_CORE_EXPORT QAbstractMetaCallEvent : public QEvent +{ +public: + QAbstractMetaCallEvent(const QObject *sender, int signalId, QSemaphore *semaphore = nullptr) + : QEvent(MetaCall), signalId_(signalId), sender_(sender), semaphore_(semaphore) + {} + ~QAbstractMetaCallEvent(); + + virtual void placeMetaCall(QObject *object) = 0; + + inline const QObject *sender() const { return sender_; } + inline int signalId() const { return signalId_; } + +private: + int signalId_; + const QObject *sender_; + QSemaphore *semaphore_; +}; + +class Q_CORE_EXPORT QMetaCallEvent : public QAbstractMetaCallEvent { public: QMetaCallEvent(ushort method_offset, ushort method_relative, QObjectPrivate::StaticMetaCallFunction callFunction , const QObject *sender, int signalId, @@ -496,23 +515,18 @@ public: QMetaCallEvent(QtPrivate::QSlotObjectBase *slotObj, const QObject *sender, int signalId, int nargs = 0, int *types = nullptr, void **args = nullptr, QSemaphore *semaphore = nullptr); - ~QMetaCallEvent(); + ~QMetaCallEvent() override; inline int id() const { return method_offset_ + method_relative_; } - inline const QObject *sender() const { return sender_; } - inline int signalId() const { return signalId_; } inline void **args() const { return args_; } - virtual void placeMetaCall(QObject *object); + virtual void placeMetaCall(QObject *object) override; private: QtPrivate::QSlotObjectBase *slotObj_; - const QObject *sender_; - int signalId_; int nargs_; int *types_; void **args_; - QSemaphore *semaphore_; QObjectPrivate::StaticMetaCallFunction callFunction_; ushort method_offset_; ushort method_relative_; -- cgit v1.2.3 From 13ab090977439cf432c7b99dbdd2b1263b4d8cd4 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Wed, 9 Jan 2019 22:17:51 +0100 Subject: Add safe way to resize the signalVector Change-Id: Ib55da020f22e981bc379af3b4cf3431bf0fa0c20 Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/kernel/qobject.cpp | 92 ++++++++++++++++++++++++------------------ src/corelib/kernel/qobject_p.h | 85 +++++++++++++++++++++++++++++++------- 2 files changed, 122 insertions(+), 55 deletions(-) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index a0e4450d28..158d92799c 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -265,8 +265,8 @@ bool QObjectPrivate::isSender(const QObject *receiver, const char *signal) const if (signal_index < 0 || !cd) return false; QBasicMutexLocker locker(signalSlotLock(q)); - if (signal_index < cd->signalVector.count()) { - const QObjectPrivate::Connection *c = cd->signalVector.at(signal_index).first; + if (signal_index < cd->signalVectorCount()) { + const QObjectPrivate::Connection *c = cd->signalVector->at(signal_index).first; while (c) { if (c->receiver == receiver) @@ -287,8 +287,8 @@ QObjectList QObjectPrivate::receiverList(const char *signal) const if (signal_index < 0 || !cd) return returnValue; QBasicMutexLocker locker(signalSlotLock(q)); - if (signal_index < cd->signalVector.count()) { - const QObjectPrivate::Connection *c = cd->signalVector.at(signal_index).first; + if (signal_index < cd->signalVectorCount()) { + const QObjectPrivate::Connection *c = cd->signalVector->at(signal_index).first; while (c) { if (c->receiver) @@ -327,8 +327,7 @@ void QObjectPrivate::addConnection(int signal, Connection *c) Q_ASSERT(c->sender == q_ptr); ensureConnectionData(); ConnectionData *cd = connections.load(); - if (signal >= cd->signalVector.count()) - cd->signalVector.resize(signal + 1); + cd->resizeSignalVector(signal + 1); ConnectionList &connectionList = cd->connectionsForSignal(signal); if (connectionList.last) { @@ -353,7 +352,7 @@ void QObjectPrivate::addConnection(int signal, Connection *c) void QObjectPrivate::ConnectionData::cleanOrphanedConnectionsImpl(QObject *sender) { - Connection *c = nullptr; + ConnectionOrSignalVector *c = nullptr; { QBasicMutexLocker l(signalSlotLock(sender)); if (ref > 1) @@ -365,13 +364,25 @@ void QObjectPrivate::ConnectionData::cleanOrphanedConnectionsImpl(QObject *sende c = orphaned.load(); orphaned.store(nullptr); } - while (c) { - Q_ASSERT(!c->receiver); - Q_ASSERT(!c->prev); - QObjectPrivate::Connection *next = c->nextInOrphanList; - c->freeSlotObject(); - c->deref(); - c = next; + deleteOrphaned(c); +} + +void QObjectPrivate::ConnectionData::deleteOrphaned(QObjectPrivate::ConnectionOrSignalVector *o) +{ + while (o) { + QObjectPrivate::ConnectionOrSignalVector *next = nullptr; + if (SignalVector *v = ConnectionOrSignalVector::asSignalVector(o)) { + next = v->nextInOrphanList; + free(v); + } else { + QObjectPrivate::Connection *c = static_cast(o); + next = c->nextInOrphanList; + Q_ASSERT(!c->receiver); + Q_ASSERT(!c->prev); + c->freeSlotObject(); + c->deref(); + } + o = next; } } @@ -387,14 +398,14 @@ bool QObjectPrivate::isSignalConnected(uint signalIndex, bool checkDeclarative) return true; ConnectionData *cd = connections.load(); - if (!cd) + if (!cd || !cd->signalVector) return false; - if (cd->allsignals.first) + if (cd->signalVector->at(-1).first) return true; - if (signalIndex < uint(cd->signalVector.count())) { - const QObjectPrivate::Connection *c = cd->signalVector.at(signalIndex).first; + if (signalIndex < uint(cd->signalVectorCount())) { + const QObjectPrivate::Connection *c = cd->signalVector->at(signalIndex).first; while (c) { if (c->receiver) return true; @@ -407,14 +418,14 @@ bool QObjectPrivate::isSignalConnected(uint signalIndex, bool checkDeclarative) bool QObjectPrivate::maybeSignalConnected(uint signalIndex) const { ConnectionData *cd = connections.load(); - if (!cd) + if (!cd || !cd->signalVector) return false; - if (cd->allsignals.first) + if (cd->signalVector->at(-1).first) return true; - if (signalIndex < uint(cd->signalVector.count())) { - const QObjectPrivate::Connection *c = cd->signalVector.at(signalIndex).first; + if (signalIndex < uint(cd->signalVectorCount())) { + const QObjectPrivate::Connection *c = cd->signalVector->at(signalIndex).first; return c != nullptr; } return false; @@ -895,7 +906,7 @@ QObject::~QObject() QBasicMutexLocker locker(signalSlotMutex); // disconnect all receivers - int receiverCount = cd->signalVector.count(); + int receiverCount = cd->signalVectorCount(); for (int signal = -1; signal < receiverCount; ++signal) { QObjectPrivate::ConnectionList &connectionList = cd->connectionsForSignal(signal); @@ -2416,9 +2427,8 @@ int QObject::receivers(const char *signal) const QObjectPrivate::ConnectionData *cd = d->connections.load(); QBasicMutexLocker locker(signalSlotLock(this)); - if (cd && signal_index < cd->signalVector.count()) { - const QObjectPrivate::Connection *c = - cd->signalVector.at(signal_index).first; + if (cd && signal_index < cd->signalVectorCount()) { + const QObjectPrivate::Connection *c = cd->signalVector->at(signal_index).first; while (c) { receivers += c->receiver ? 1 : 0; c = c->nextConnectionList; @@ -3232,8 +3242,8 @@ QObjectPrivate::Connection *QMetaObjectPrivate::connect(const QObject *sender, QObjectPrivate::ConnectionData *scd = QObjectPrivate::get(s)->connections.load(); if (type & Qt::UniqueConnection && scd) { - if (scd->signalVector.count() > signal_index) { - const QObjectPrivate::Connection *c2 = scd->signalVector.at(signal_index).first; + if (scd->signalVectorCount() > signal_index) { + const QObjectPrivate::Connection *c2 = scd->signalVector->at(signal_index).first; int method_index_absolute = method_index + method_offset; @@ -3365,11 +3375,11 @@ bool QMetaObjectPrivate::disconnect(const QObject *sender, if (signal_index < 0) { // remove from all connection lists - for (int sig_index = -1; sig_index < scd->signalVector.count(); ++sig_index) { + for (int sig_index = -1; sig_index < scd->signalVectorCount(); ++sig_index) { if (disconnectHelper(connections.data(), sig_index, receiver, method_index, slot, senderMutex, disconnectType)) success = true; } - } else if (signal_index < scd->signalVector.count()) { + } else if (signal_index < scd->signalVectorCount()) { if (disconnectHelper(connections.data(), signal_index, receiver, method_index, slot, senderMutex, disconnectType)) success = true; } @@ -3592,10 +3602,10 @@ void doActivate(QObject *sender, int signal_index, void **argv) QObjectPrivate::ConnectionDataPointer connections(sp->connections.load()); const QObjectPrivate::ConnectionList *list; - if (signal_index < connections->signalVector.count()) - list = &connections->signalVector.at(signal_index); + if (signal_index < connections->signalVector->count()) + list = &connections->signalVector->at(signal_index); else - list = &connections->allsignals; + list = &connections->signalVector->at(-1); Qt::HANDLE currentThreadId = QThread::currentThreadId(); @@ -3691,9 +3701,9 @@ void doActivate(QObject *sender, int signal_index, void **argv) } } while ((c = c->nextConnectionList) != 0 && c->id <= highestConnectionId); - } while (list != &connections->allsignals && + } while (list != &connections->signalVector->at(-1) && //start over for all signals; - ((list = &connections->allsignals), true)); + ((list = &connections->signalVector->at(-1)), true)); if (connections->currentConnectionId.load() == 0) senderDeleted = true; @@ -3994,13 +4004,15 @@ void QObject::dumpObjectInfo() const qDebug(" SIGNALS OUT"); QObjectPrivate::ConnectionData *cd = d->connections.load(); - if (cd && cd->signalVector.count()) { - for (int signal_index = 0; signal_index < cd->signalVector.count(); ++signal_index) { + if (cd && cd->signalVectorCount()) { + for (int signal_index = 0; signal_index < cd->signalVectorCount(); ++signal_index) { + const QObjectPrivate::Connection *c = cd->signalVector->at(signal_index).first; + if (!c) + continue; const QMetaMethod signal = QMetaObjectPrivate::signal(metaObject(), signal_index); qDebug(" signal: %s", signal.methodSignature().constData()); // receivers - const QObjectPrivate::Connection *c = cd->signalVector.at(signal_index).first; while (c) { if (!c->receiver) { qDebug(" "); @@ -4766,8 +4778,8 @@ QMetaObject::Connection QObjectPrivate::connectImpl(const QObject *sender, int s if (type & Qt::UniqueConnection && slot && QObjectPrivate::get(s)->connections.load()) { QObjectPrivate::ConnectionData *connections = QObjectPrivate::get(s)->connections.load(); - if (connections->signalVector.count() > signal_index) { - const QObjectPrivate::Connection *c2 = connections->signalVector.at(signal_index).first; + if (connections->signalVectorCount() > signal_index) { + const QObjectPrivate::Connection *c2 = connections->signalVector->at(signal_index).first; while (c2) { if (c2->receiver == receiver && c2->isSlotObject && c2->slotObj->compare(slot)) { diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h index da3d035087..f01b709faa 100644 --- a/src/corelib/kernel/qobject_p.h +++ b/src/corelib/kernel/qobject_p.h @@ -124,14 +124,30 @@ public: }; typedef void (*StaticMetaCallFunction)(QObject *, QMetaObject::Call, int, void **); - struct Connection - { + struct Connection; + struct SignalVector; + + struct ConnectionOrSignalVector { union { // linked list of orphaned connections that need cleaning up - Connection *nextInOrphanList; + ConnectionOrSignalVector *nextInOrphanList; // linked list of connections connected to slots in this object Connection *next; }; + + static SignalVector *asSignalVector(ConnectionOrSignalVector *c) { + if (reinterpret_cast(c) & 1) + return reinterpret_cast(reinterpret_cast(c) & ~quintptr(1u)); + return nullptr; + } + static Connection *fromSignalVector(SignalVector *v) { + return reinterpret_cast(reinterpret_cast(v) | quintptr(1u)); + } + }; + + struct Connection : public ConnectionOrSignalVector + { + // linked list of connections connected to slots in this object, next is in base class Connection **prev; // linked list of connections connected to signals in this object Connection *nextConnectionList; @@ -210,6 +226,22 @@ public: int signal; }; + struct SignalVector : public ConnectionOrSignalVector { + quintptr allocated; + // ConnectionList signals[] + ConnectionList &at(int i) + { + return reinterpret_cast(this + 1)[i + 1]; + } + const ConnectionList &at(int i) const + { + return reinterpret_cast(this + 1)[i + 1]; + } + int count() { return static_cast(allocated); } + }; + + + /* This contains the all connections from and to an object. @@ -236,22 +268,16 @@ public: }; Ref ref; - ConnectionList allsignals; - QVector signalVector; + SignalVector *signalVector = nullptr; Connection *senders = nullptr; Sender *currentSender = nullptr; // object currently activating the object QAtomicPointer orphaned; ~ConnectionData() { - Connection *c = orphaned.load(); - while (c) { - Q_ASSERT(!c->receiver); - QObjectPrivate::Connection *next = c->nextInOrphanList; - c->freeSlotObject(); - c->deref(); - c = next; - } + deleteOrphaned(orphaned.load()); + if (signalVector) + free(signalVector); } // must be called on the senders connection data @@ -259,7 +285,7 @@ public: void removeConnection(Connection *c) { Q_ASSERT(c->receiver); - ConnectionList &connections = connectionsForSignal(c->signal_index); + ConnectionList &connections = signalVector->at(c->signal_index); c->receiver = nullptr; #ifndef QT_NO_DEBUG @@ -283,6 +309,8 @@ public: connections.first = c->nextConnectionList; if (connections.last == c) connections.last = c->prevConnectionList; + Q_ASSERT(signalVector->at(c->signal_index).first != c); + Q_ASSERT(signalVector->at(c->signal_index).last != c); // keep c->nextConnectionList intact, as it might still get accessed by activate if (c->nextConnectionList) @@ -317,8 +345,35 @@ public: ConnectionList &connectionsForSignal(int signal) { - return signal < 0 ? allsignals : signalVector[signal]; + return signalVector->at(signal); } + + void resizeSignalVector(uint size) { + if (signalVector && signalVector->allocated > size) + return; + size = (size + 7) & ~7; + SignalVector *v = reinterpret_cast(malloc(sizeof(SignalVector) + (size + 1) * sizeof(ConnectionList))); + int start = -1; + if (signalVector) { + memcpy(v, signalVector, sizeof(SignalVector) + (signalVector->allocated + 1) * sizeof(ConnectionList)); + start = signalVector->count(); + } + for (int i = start; i < int(size); ++i) + v->at(i) = ConnectionList(); + v->next = nullptr; + v->allocated = size; + + qSwap(v, signalVector); + if (v) { + v->next = orphaned.load(); + orphaned.store(ConnectionOrSignalVector::fromSignalVector(v)); + } + } + int signalVectorCount() const { + return signalVector ? signalVector->count() : -1; + } + + static void deleteOrphaned(ConnectionOrSignalVector *c); }; QObjectPrivate(int version = QObjectPrivateVersion); -- cgit v1.2.3 From 993b049adfa9aaa22324761ce41fe2569184079a Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Wed, 9 Jan 2019 22:23:23 +0100 Subject: Get rid of the locking in activate() Removing connections and resizing the signal vector now happens in a way that will not interfere with activate(), as the old objects won't get deleted if we are somewhere inside a signal emission. This means that we don't need to lock the senders mutex in activate anymore, as long as the reference counting on the ConnectionData is atomic and we are in the senders thread. This implies that we now need to lock the receivers mutex in queued_activate() abd blocking queued activation to ensure it hasn't been deleted while we are emitting. In addition, some precautions need to be taken to not read from the receiver without holding the lock, as it could get deleted while we're activating (if it's in a different thread). To make that possible store the receivers thread id in the connection data. Use atomic pointers for all variables that can get modified with the signalSlotLock() held and that are being read without the lock being held. This gives us a very nice additional speed improvement for signal emissions. without change with change string based connect: 3287 2436 pointer based connect: 3941 3265 not connected: 403 400 disconnected: 460 489 5 slots connected: 9112 4515 Change-Id: Ib7324bb74c389dcc3b6581a03c31469a6e589fc2 Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/kernel/qobject.cpp | 315 +++++++++++++++++++++++++++-------------- src/corelib/kernel/qobject_p.h | 116 ++++----------- 2 files changed, 236 insertions(+), 195 deletions(-) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 158d92799c..45e88a2082 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -266,12 +266,12 @@ bool QObjectPrivate::isSender(const QObject *receiver, const char *signal) const return false; QBasicMutexLocker locker(signalSlotLock(q)); if (signal_index < cd->signalVectorCount()) { - const QObjectPrivate::Connection *c = cd->signalVector->at(signal_index).first; + const QObjectPrivate::Connection *c = cd->signalVector.load()->at(signal_index).first.load(); while (c) { - if (c->receiver == receiver) + if (c->receiver.load() == receiver) return true; - c = c->nextConnectionList; + c = c->nextConnectionList.load(); } } return false; @@ -280,20 +280,19 @@ bool QObjectPrivate::isSender(const QObject *receiver, const char *signal) const // Used by QAccessibleWidget QObjectList QObjectPrivate::receiverList(const char *signal) const { - Q_Q(const QObject); QObjectList returnValue; int signal_index = signalIndex(signal); ConnectionData *cd = connections.load(); if (signal_index < 0 || !cd) return returnValue; - QBasicMutexLocker locker(signalSlotLock(q)); if (signal_index < cd->signalVectorCount()) { - const QObjectPrivate::Connection *c = cd->signalVector->at(signal_index).first; + const QObjectPrivate::Connection *c = cd->signalVector.load()->at(signal_index).first.load(); while (c) { - if (c->receiver) - returnValue << c->receiver; - c = c->nextConnectionList; + QObject *r = c->receiver.load(); + if (r) + returnValue << r; + c = c->nextConnectionList.load(); } } return returnValue; @@ -330,17 +329,17 @@ void QObjectPrivate::addConnection(int signal, Connection *c) cd->resizeSignalVector(signal + 1); ConnectionList &connectionList = cd->connectionsForSignal(signal); - if (connectionList.last) { - Q_ASSERT(connectionList.last->receiver); - connectionList.last->nextConnectionList = c; + if (connectionList.last.load()) { + Q_ASSERT(connectionList.last.load()->receiver.load()); + connectionList.last.load()->nextConnectionList.store(c); } else { - connectionList.first = c; + connectionList.first.store(c); } c->id = ++cd->currentConnectionId; - c->prevConnectionList = connectionList.last; - connectionList.last = c; + c->prevConnectionList = connectionList.last.load(); + connectionList.last.store(c); - QObjectPrivate *rd = QObjectPrivate::get(c->receiver); + QObjectPrivate *rd = QObjectPrivate::get(c->receiver.load()); rd->ensureConnectionData(); c->prev = &(rd->connections.load()->senders); @@ -350,6 +349,66 @@ void QObjectPrivate::addConnection(int signal, Connection *c) c->next->prev = &c->next; } +void QObjectPrivate::ConnectionData::removeConnection(QObjectPrivate::Connection *c) +{ + Q_ASSERT(c->receiver.load()); + ConnectionList &connections = signalVector.load()->at(c->signal_index); + c->receiver.store(nullptr); + QThreadData *td = c->receiverThreadData.load(); + if (td) + td->deref(); + c->receiverThreadData.store(nullptr); + +#ifndef QT_NO_DEBUG + bool found = false; + for (Connection *cc = connections.first.load(); cc; cc = cc->nextConnectionList.load()) { + if (cc == c) { + found = true; + break; + } + } + Q_ASSERT(found); +#endif + + // remove from the senders linked list + *c->prev = c->next; + if (c->next) + c->next->prev = c->prev; + c->prev = nullptr; + + if (connections.first.load() == c) + connections.first.store(c->nextConnectionList.load()); + if (connections.last.load() == c) + connections.last.store(c->prevConnectionList); + Q_ASSERT(signalVector.load()->at(c->signal_index).first.load() != c); + Q_ASSERT(signalVector.load()->at(c->signal_index).last.load() != c); + + // keep c->nextConnectionList intact, as it might still get accessed by activate + Connection *n = c->nextConnectionList.load(); + if (n) + n->prevConnectionList = c->prevConnectionList; + if (c->prevConnectionList) + c->prevConnectionList->nextConnectionList.store(n); + c->prevConnectionList = nullptr; + + Q_ASSERT(c != orphaned.load()); + // add c to orphanedConnections + c->nextInOrphanList = orphaned.load(); + orphaned.store(c); + +#ifndef QT_NO_DEBUG + found = false; + for (Connection *cc = connections.first.load(); cc; cc = cc->nextConnectionList.load()) { + if (cc == c) { + found = true; + break; + } + } + Q_ASSERT(!found); +#endif + +} + void QObjectPrivate::ConnectionData::cleanOrphanedConnectionsImpl(QObject *sender) { ConnectionOrSignalVector *c = nullptr; @@ -377,7 +436,7 @@ void QObjectPrivate::ConnectionData::deleteOrphaned(QObjectPrivate::ConnectionOr } else { QObjectPrivate::Connection *c = static_cast(o); next = c->nextInOrphanList; - Q_ASSERT(!c->receiver); + Q_ASSERT(!c->receiver.load()); Q_ASSERT(!c->prev); c->freeSlotObject(); c->deref(); @@ -398,18 +457,21 @@ bool QObjectPrivate::isSignalConnected(uint signalIndex, bool checkDeclarative) return true; ConnectionData *cd = connections.load(); - if (!cd || !cd->signalVector) + if (!cd) + return false; + SignalVector *signalVector = cd->signalVector.load(); + if (!signalVector) return false; - if (cd->signalVector->at(-1).first) + if (signalVector->at(-1).first.load()) return true; if (signalIndex < uint(cd->signalVectorCount())) { - const QObjectPrivate::Connection *c = cd->signalVector->at(signalIndex).first; + const QObjectPrivate::Connection *c = signalVector->at(signalIndex).first.load(); while (c) { - if (c->receiver) + if (c->receiver.load()) return true; - c = c->nextConnectionList; + c = c->nextConnectionList.load(); } } return false; @@ -418,14 +480,17 @@ bool QObjectPrivate::isSignalConnected(uint signalIndex, bool checkDeclarative) bool QObjectPrivate::maybeSignalConnected(uint signalIndex) const { ConnectionData *cd = connections.load(); - if (!cd || !cd->signalVector) + if (!cd) + return false; + SignalVector *signalVector = cd->signalVector.load(); + if (!signalVector) return false; - if (cd->signalVector->at(-1).first) + if (signalVector->at(-1).first) return true; if (signalIndex < uint(cd->signalVectorCount())) { - const QObjectPrivate::Connection *c = cd->signalVector->at(signalIndex).first; + const QObjectPrivate::Connection *c = signalVector->at(signalIndex).first; return c != nullptr; } return false; @@ -910,14 +975,14 @@ QObject::~QObject() for (int signal = -1; signal < receiverCount; ++signal) { QObjectPrivate::ConnectionList &connectionList = cd->connectionsForSignal(signal); - while (QObjectPrivate::Connection *c = connectionList.first) { + while (QObjectPrivate::Connection *c = connectionList.first.load()) { Q_ASSERT(c->receiver); - QBasicMutex *m = signalSlotLock(c->receiver); + QBasicMutex *m = signalSlotLock(c->receiver.load()); bool needToUnlock = QOrderedMutexLocker::relock(signalSlotMutex, m); if (c->receiver) { cd->removeConnection(c); - Q_ASSERT(connectionList.first != c); + Q_ASSERT(connectionList.first.load() != c); } if (needToUnlock) m->unlock(); @@ -1457,6 +1522,9 @@ void QObject::moveToThread(QThread *targetThread) if (!targetData) targetData = new QThreadData(0); + // make sure nobody adds/removes connections to this object while we're moving it + QMutexLocker l(signalSlotLock(this)); + QOrderedMutexLocker locker(¤tData->postEventList.mutex, &targetData->postEventList.mutex); @@ -1507,9 +1575,29 @@ void QObjectPrivate::setThreadData_helper(QThreadData *currentData, QThreadData // the current emitting thread shouldn't restore currentSender after calling moveToThread() ConnectionData *cd = connections.load(); - if (cd && cd->currentSender) { - cd->currentSender->receiverDeleted(); - cd->currentSender = nullptr; + if (cd) { + if (cd->currentSender) { + cd->currentSender->receiverDeleted(); + cd->currentSender = nullptr; + } + + // adjust the receiverThreadId values in the Connections + if (cd) { + auto *c = cd->senders; + while (c) { + QObject *r = c->receiver.load(); + if (r) { + Q_ASSERT(r == q); + targetData->ref(); + QThreadData *old = c->receiverThreadData.load(); + if (old) + old->deref(); + c->receiverThreadData.store(targetData); + } + c = c->next; + } + } + } // set new thread data @@ -2428,10 +2516,10 @@ int QObject::receivers(const char *signal) const QObjectPrivate::ConnectionData *cd = d->connections.load(); QBasicMutexLocker locker(signalSlotLock(this)); if (cd && signal_index < cd->signalVectorCount()) { - const QObjectPrivate::Connection *c = cd->signalVector->at(signal_index).first; + const QObjectPrivate::Connection *c = cd->signalVector.load()->at(signal_index).first.load(); while (c) { - receivers += c->receiver ? 1 : 0; - c = c->nextConnectionList; + receivers += c->receiver.load() ? 1 : 0; + c = c->nextConnectionList.load(); } } } @@ -3243,14 +3331,14 @@ QObjectPrivate::Connection *QMetaObjectPrivate::connect(const QObject *sender, QObjectPrivate::ConnectionData *scd = QObjectPrivate::get(s)->connections.load(); if (type & Qt::UniqueConnection && scd) { if (scd->signalVectorCount() > signal_index) { - const QObjectPrivate::Connection *c2 = scd->signalVector->at(signal_index).first; + const QObjectPrivate::Connection *c2 = scd->signalVector.load()->at(signal_index).first.load(); int method_index_absolute = method_index + method_offset; while (c2) { - if (!c2->isSlotObject && c2->receiver == receiver && c2->method() == method_index_absolute) + if (!c2->isSlotObject && c2->receiver.load() == receiver && c2->method() == method_index_absolute) return nullptr; - c2 = c2->nextConnectionList; + c2 = c2->nextConnectionList.load(); } } type &= Qt::UniqueConnection - 1; @@ -3259,13 +3347,15 @@ QObjectPrivate::Connection *QMetaObjectPrivate::connect(const QObject *sender, QScopedPointer c(new QObjectPrivate::Connection); c->sender = s; c->signal_index = signal_index; - c->receiver = r; + c->receiver.store(r); + QThreadData *td = r->d_func()->threadData; + td->ref(); + c->receiverThreadData.store(td); c->method_relative = method_index; c->method_offset = method_offset; c->connectionType = type; c->isSlotObject = false; c->argumentTypes.store(types); - c->nextConnectionList = 0; c->callFunction = callFunction; QObjectPrivate::get(s)->addConnection(signal_index, c.data()); @@ -3318,20 +3408,20 @@ bool QMetaObjectPrivate::disconnectHelper(QObjectPrivate::ConnectionData *connec bool success = false; auto &connectionList = connections->connectionsForSignal(signalIndex); - auto *c = connectionList.first; + auto *c = connectionList.first.load(); while (c) { - if (c->receiver - && (receiver == nullptr || (c->receiver == receiver + QObject *r = c->receiver.load(); + if (r && (receiver == nullptr || (r == receiver && (method_index < 0 || (!c->isSlotObject && c->method() == method_index)) && (slot == nullptr || (c->isSlotObject && c->slotObj->compare(slot)))))) { bool needToUnlock = false; QBasicMutex *receiverMutex = nullptr; - if (c->receiver) { - receiverMutex = signalSlotLock(c->receiver); + if (r) { + receiverMutex = signalSlotLock(r); // need to relock this receiver and sender in the correct order needToUnlock = QOrderedMutexLocker::relock(senderMutex, receiverMutex); } - if (c->receiver) + if (c->receiver.load()) connections->removeConnection(c); if (needToUnlock) @@ -3342,7 +3432,7 @@ bool QMetaObjectPrivate::disconnectHelper(QObjectPrivate::ConnectionData *connec if (disconnectType == DisconnectOne) return success; } - c = c->nextConnectionList; + c = c->nextConnectionList.load(); } return success; } @@ -3504,8 +3594,7 @@ void QMetaObject::connectSlotsByName(QObject *o) \a signal must be in the signal index range (see QObjectPrivate::signalIndex()). */ -static void queued_activate(QObject *sender, int signal, QObjectPrivate::Connection *c, void **argv, - QBasicMutexLocker &locker) +static void queued_activate(QObject *sender, int signal, QObjectPrivate::Connection *c, void **argv) { const int *argumentTypes = c->argumentTypes.load(); if (!argumentTypes) { @@ -3535,27 +3624,25 @@ static void queued_activate(QObject *sender, int signal, QObjectPrivate::Connect for (int n = 1; n < nargs; ++n) types[n] = argumentTypes[n-1]; - locker.unlock(); for (int n = 1; n < nargs; ++n) args[n] = QMetaType::create(types[n], argv[n]); - locker.relock(); - - if (!c->receiver) { - locker.unlock(); - // we have been disconnected while the mutex was unlocked - for (int n = 1; n < nargs; ++n) - QMetaType::destroy(types[n], args[n]); - free(types); - free(args); - locker.relock(); - return; - } + } + + QBasicMutexLocker locker(signalSlotLock(c->receiver.load())); + if (!c->receiver.load()) { + // the connection has been disconnected before we got the lock + locker.unlock(); + for (int n = 1; n < nargs; ++n) + QMetaType::destroy(types[n], args[n]); + free(types); + free(args); + 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, ev); + QCoreApplication::postEvent(c->receiver.load(), ev); } template @@ -3597,38 +3684,51 @@ void doActivate(QObject *sender, int signal_index, void **argv) bool senderDeleted = false; { - QBasicMutexLocker locker(signalSlotLock(sender)); Q_ASSERT(sp->connections); QObjectPrivate::ConnectionDataPointer connections(sp->connections.load()); + QObjectPrivate::SignalVector *signalVector = connections->signalVector.load(); const QObjectPrivate::ConnectionList *list; - if (signal_index < connections->signalVector->count()) - list = &connections->signalVector->at(signal_index); + if (signal_index < signalVector->count()) + list = &signalVector->at(signal_index); else - list = &connections->signalVector->at(-1); + list = &signalVector->at(-1); Qt::HANDLE currentThreadId = QThread::currentThreadId(); + bool inSenderThread = currentThreadId == QObjectPrivate::get(sender)->threadData->threadId.load(); // We need to check against the highest connection id to ensure that signals added // during the signal emission are not emitted in this emission. uint highestConnectionId = connections->currentConnectionId.load(); do { - QObjectPrivate::Connection *c = list->first; + QObjectPrivate::Connection *c = list->first.load(); if (!c) continue; do { - if (!c->receiver) + QObject * const receiver = c->receiver.load(); + if (!receiver) continue; - QObject * const receiver = c->receiver; - const bool receiverInSameThread = currentThreadId == QObjectPrivate::get(receiver)->threadData->threadId.load(); + QThreadData *td = c->receiverThreadData.load(); + if (!td) + continue; + + bool receiverInSameThread; + if (inSenderThread) { + receiverInSameThread = currentThreadId == td->threadId.load(); + } else { + // need to lock before reading the threadId, because moveToThread() could interfere + QMutexLocker lock(signalSlotLock(receiver)); + receiverInSameThread = currentThreadId == td->threadId.load(); + } + // determine if this connection should be sent immediately or // put into the event queue if ((c->connectionType == Qt::AutoConnection && !receiverInSameThread) || (c->connectionType == Qt::QueuedConnection)) { - queued_activate(sender, signal_index, c, argv, locker); + queued_activate(sender, signal_index, c, argv); continue; #if QT_CONFIG(thread) } else if (c->connectionType == Qt::BlockingQueuedConnection) { @@ -3639,13 +3739,16 @@ void doActivate(QObject *sender, int signal_index, void **argv) receiver->metaObject()->className(), receiver); } QSemaphore semaphore; - 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); - QCoreApplication::postEvent(receiver, ev); - locker.unlock(); + { + QBasicMutexLocker locker(signalSlotLock(sender)); + if (!c->receiver) + 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); + QCoreApplication::postEvent(receiver, ev); + } semaphore.acquire(); - locker.relock(); continue; #endif } @@ -3655,22 +3758,13 @@ void doActivate(QObject *sender, int signal_index, void **argv) if (c->isSlotObject) { c->slotObj->ref(); QScopedPointer obj(c->slotObj); - locker.unlock(); Q_TRACE(QMetaObject_activate_begin_slot_functor, obj.data()); obj->call(receiver, argv); Q_TRACE(QMetaObject_activate_end_slot_functor, obj.data()); - - // Make sure the slot object gets destroyed before the mutex is locked again, as the - // destructor of the slot object might also lock a mutex from the signalSlotLock() mutex pool, - // and that would deadlock if the pool happens to return the same mutex. - obj.reset(); - - locker.relock(); } else if (c->callFunction && c->method_offset <= receiver->metaObject()->methodOffset()) { //we compare the vtable to make sure we are not in the destructor of the object. const int method_relative = c->method_relative; const auto callFunction = c->callFunction; - locker.unlock(); const int methodIndex = (Q_HAS_TRACEPOINTS || callbacks_enabled) ? c->method() : 0; if (callbacks_enabled && signal_spy_set->slot_begin_callback != nullptr) signal_spy_set->slot_begin_callback(receiver, methodIndex, argv); @@ -3681,10 +3775,8 @@ void doActivate(QObject *sender, int signal_index, void **argv) Q_TRACE(QMetaObject_activate_end_slot, receiver, methodIndex); if (callbacks_enabled && signal_spy_set->slot_end_callback != nullptr) signal_spy_set->slot_end_callback(receiver, methodIndex); - locker.relock(); } else { const int method = c->method_relative + c->method_offset; - locker.unlock(); if (callbacks_enabled && signal_spy_set->slot_begin_callback != nullptr) { signal_spy_set->slot_begin_callback(receiver, method, argv); @@ -3696,14 +3788,12 @@ void doActivate(QObject *sender, int signal_index, void **argv) Q_TRACE(QMetaObject_activate_end_slot, receiver, method); if (callbacks_enabled && signal_spy_set->slot_end_callback != nullptr) signal_spy_set->slot_end_callback(receiver, method); - - locker.relock(); } - } while ((c = c->nextConnectionList) != 0 && c->id <= highestConnectionId); + } while ((c = c->nextConnectionList.load()) != nullptr && c->id <= highestConnectionId); - } while (list != &connections->signalVector->at(-1) && + } while (list != &signalVector->at(-1) && //start over for all signals; - ((list = &connections->signalVector->at(-1)), true)); + ((list = &signalVector->at(-1)), true)); if (connections->currentConnectionId.load() == 0) senderDeleted = true; @@ -4005,8 +4095,9 @@ void QObject::dumpObjectInfo() const QObjectPrivate::ConnectionData *cd = d->connections.load(); if (cd && cd->signalVectorCount()) { - for (int signal_index = 0; signal_index < cd->signalVectorCount(); ++signal_index) { - const QObjectPrivate::Connection *c = cd->signalVector->at(signal_index).first; + QObjectPrivate::SignalVector *signalVector = cd->signalVector.load(); + for (int signal_index = 0; signal_index < signalVector->count(); ++signal_index) { + const QObjectPrivate::Connection *c = signalVector->at(signal_index).first.load(); if (!c) continue; const QMetaMethod signal = QMetaObjectPrivate::signal(metaObject(), signal_index); @@ -4014,23 +4105,23 @@ void QObject::dumpObjectInfo() const // receivers while (c) { - if (!c->receiver) { + if (!c->receiver.load()) { qDebug(" "); - c = c->nextConnectionList; + c = c->nextConnectionList.load(); continue; } if (c->isSlotObject) { qDebug(" "); - c = c->nextConnectionList; + c = c->nextConnectionList.load(); continue; } - const QMetaObject *receiverMetaObject = c->receiver->metaObject(); + const QMetaObject *receiverMetaObject = c->receiver.load()->metaObject(); const QMetaMethod method = receiverMetaObject->method(c->method()); qDebug(" --> %s::%s %s", receiverMetaObject->className(), - c->receiver->objectName().isEmpty() ? "unnamed" : qPrintable(c->receiver->objectName()), + c->receiver.load()->objectName().isEmpty() ? "unnamed" : qPrintable(c->receiver.load()->objectName()), method.methodSignature().constData()); - c = c->nextConnectionList; + c = c->nextConnectionList.load(); } } } else { @@ -4779,14 +4870,14 @@ QMetaObject::Connection QObjectPrivate::connectImpl(const QObject *sender, int s if (type & Qt::UniqueConnection && slot && QObjectPrivate::get(s)->connections.load()) { QObjectPrivate::ConnectionData *connections = QObjectPrivate::get(s)->connections.load(); if (connections->signalVectorCount() > signal_index) { - const QObjectPrivate::Connection *c2 = connections->signalVector->at(signal_index).first; + const QObjectPrivate::Connection *c2 = connections->signalVector.load()->at(signal_index).first.load(); while (c2) { - if (c2->receiver == receiver && c2->isSlotObject && c2->slotObj->compare(slot)) { + if (c2->receiver.load() == receiver && c2->isSlotObject && c2->slotObj->compare(slot)) { slotObj->destroyIfLastRef(); return QMetaObject::Connection(); } - c2 = c2->nextConnectionList; + c2 = c2->nextConnectionList.load(); } } type = static_cast(type ^ Qt::UniqueConnection); @@ -4795,7 +4886,10 @@ QMetaObject::Connection QObjectPrivate::connectImpl(const QObject *sender, int s QScopedPointer c(new QObjectPrivate::Connection); c->sender = s; c->signal_index = signal_index; - c->receiver = r; + QThreadData *td = r->d_func()->threadData; + td->ref(); + c->receiverThreadData.store(td); + c->receiver.store(r); c->slotObj = slotObj; c->connectionType = type; c->isSlotObject = true; @@ -4829,15 +4923,20 @@ bool QObject::disconnect(const QMetaObject::Connection &connection) if (!c) return false; + QObject *receiver = c->receiver.load(); + if (!receiver) + return false; QBasicMutex *senderMutex = signalSlotLock(c->sender); - QBasicMutex *receiverMutex = signalSlotLock(c->receiver); + QBasicMutex *receiverMutex = signalSlotLock(receiver); QObjectPrivate::ConnectionData *connections; { QOrderedMutexLocker locker(senderMutex, receiverMutex); - if (!c->receiver) + // load receiver once again and recheck to ensure nobody else has removed the connection in the meantime + receiver = c->receiver.load(); + if (!receiver) return false; connections = QObjectPrivate::get(c->sender)->connections.load(); @@ -5032,7 +5131,7 @@ bool QMetaObject::Connection::isConnected_helper() const Q_ASSERT(d_ptr); // we're only called from operator RestrictedBool() const QObjectPrivate::Connection *c = static_cast(d_ptr); - return c->receiver; + return c->receiver.load(); } diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h index f01b709faa..2fb11ecc64 100644 --- a/src/corelib/kernel/qobject_p.h +++ b/src/corelib/kernel/qobject_p.h @@ -150,11 +150,12 @@ public: // linked list of connections connected to slots in this object, next is in base class Connection **prev; // linked list of connections connected to signals in this object - Connection *nextConnectionList; + QAtomicPointer nextConnectionList; Connection *prevConnectionList; QObject *sender; - QObject *receiver; + QAtomicPointer receiver; + QAtomicPointer receiverThreadData; union { StaticMetaCallFunction callFunction; QtPrivate::QSlotObjectBase *slotObj; @@ -168,7 +169,7 @@ public: ushort connectionType : 3; // 0 == auto, 1 == direct, 2 == queued, 4 == blocking ushort isSlotObject : 1; ushort ownArgumentTypes : 1; - Connection() : nextConnectionList(nullptr), ref_(2), ownArgumentTypes(true) { + Connection() : ref_(2), ownArgumentTypes(true) { //ref_ is 2 for the use in the internal lists, and for the use in QMetaObject::Connection } ~Connection(); @@ -183,7 +184,7 @@ public: } void deref() { if (!ref_.deref()) { - Q_ASSERT(!receiver); + Q_ASSERT(!receiver.load()); Q_ASSERT(!isSlotObject); delete this; } @@ -191,9 +192,8 @@ public: }; // ConnectionList is a singly-linked list struct ConnectionList { - ConnectionList() : first(nullptr), last(nullptr) {} - Connection *first; - Connection *last; + QAtomicPointer first; + QAtomicPointer last; }; struct Sender @@ -260,15 +260,8 @@ public: // the id below is used to avoid activating new connections. When the object gets // deleted it's set to 0, so that signal emission stops QAtomicInteger currentConnectionId; - struct Ref { - int _ref = 0; - void ref() { ++_ref; } - int deref() { return --_ref; } - operator int() const { return _ref; } - }; - - Ref ref; - SignalVector *signalVector = nullptr; + QAtomicInt ref; + QAtomicPointer signalVector; Connection *senders = nullptr; Sender *currentSender = nullptr; // object currently activating the object QAtomicPointer orphaned; @@ -276,66 +269,14 @@ public: ~ConnectionData() { deleteOrphaned(orphaned.load()); - if (signalVector) - free(signalVector); + SignalVector *v = signalVector.load(); + if (v) + free(v); } // must be called on the senders connection data // assumes the senders and receivers lock are held - void removeConnection(Connection *c) - { - Q_ASSERT(c->receiver); - ConnectionList &connections = signalVector->at(c->signal_index); - c->receiver = nullptr; - -#ifndef QT_NO_DEBUG - bool found = false; - for (Connection *cc = connections.first; cc; cc = cc->nextConnectionList) { - if (cc == c) { - found = true; - break; - } - } - Q_ASSERT(found); -#endif - - // remove from the senders linked list - *c->prev = c->next; - if (c->next) - c->next->prev = c->prev; - c->prev = nullptr; - - if (connections.first == c) - connections.first = c->nextConnectionList; - if (connections.last == c) - connections.last = c->prevConnectionList; - Q_ASSERT(signalVector->at(c->signal_index).first != c); - Q_ASSERT(signalVector->at(c->signal_index).last != c); - - // keep c->nextConnectionList intact, as it might still get accessed by activate - if (c->nextConnectionList) - c->nextConnectionList->prevConnectionList = c->prevConnectionList; - if (c->prevConnectionList) - c->prevConnectionList->nextConnectionList = c->nextConnectionList; - c->prevConnectionList = nullptr; - - Q_ASSERT(c != orphaned.load()); - // add c to orphanedConnections - c->nextInOrphanList = orphaned.load(); - orphaned.store(c); - -#ifndef QT_NO_DEBUG - found = false; - for (Connection *cc = connections.first; cc; cc = cc->nextConnectionList) { - if (cc == c) { - found = true; - break; - } - } - Q_ASSERT(!found); -#endif - - } + void removeConnection(Connection *c); void cleanOrphanedConnections(QObject *sender) { if (orphaned.load() && ref == 1) @@ -345,32 +286,33 @@ public: ConnectionList &connectionsForSignal(int signal) { - return signalVector->at(signal); + return signalVector.load()->at(signal); } void resizeSignalVector(uint size) { - if (signalVector && signalVector->allocated > size) + SignalVector *vector = this->signalVector.load(); + if (vector && vector->allocated > size) return; size = (size + 7) & ~7; - SignalVector *v = reinterpret_cast(malloc(sizeof(SignalVector) + (size + 1) * sizeof(ConnectionList))); + SignalVector *newVector = reinterpret_cast(malloc(sizeof(SignalVector) + (size + 1) * sizeof(ConnectionList))); int start = -1; - if (signalVector) { - memcpy(v, signalVector, sizeof(SignalVector) + (signalVector->allocated + 1) * sizeof(ConnectionList)); - start = signalVector->count(); + if (vector) { + memcpy(newVector, vector, sizeof(SignalVector) + (vector->allocated + 1) * sizeof(ConnectionList)); + start = vector->count(); } for (int i = start; i < int(size); ++i) - v->at(i) = ConnectionList(); - v->next = nullptr; - v->allocated = size; - - qSwap(v, signalVector); - if (v) { - v->next = orphaned.load(); - orphaned.store(ConnectionOrSignalVector::fromSignalVector(v)); + newVector->at(i) = ConnectionList(); + newVector->next = nullptr; + newVector->allocated = size; + + signalVector.store(newVector); + if (vector) { + vector->nextInOrphanList = orphaned.load(); + orphaned.store(ConnectionOrSignalVector::fromSignalVector(vector)); } } int signalVectorCount() const { - return signalVector ? signalVector->count() : -1; + return signalVector ? signalVector.load()->count() : -1; } static void deleteOrphaned(ConnectionOrSignalVector *c); -- cgit v1.2.3 From c19d556863d931f5fd04d9e27ee7a47aafeaca2a Mon Sep 17 00:00:00 2001 From: Christian Ehrlicher Date: Thu, 21 Mar 2019 19:51:44 +0100 Subject: QVariant: deprecate qVariantFromValue/qVariantSetValue() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit qVariantFromValue/qVariantSetValue() was marked as obsolete since Qt4. Therefore mark them as deprecated with Qt5.14. Since QVariant::setValue/fromValue() were using the now deprecated functions move the implementation to them and let qVariantFromValue/qVariantSetValue() call QVariant::setValue/fromValue(). Fixes: QTBUG-74043 Change-Id: I46617cc4d5c1e8c162d0f1f7ae32e4cfe9ce915c Reviewed-by: Jędrzej Nowacki Reviewed-by: Edward Welbourne --- src/corelib/kernel/qvariant.cpp | 2 ++ src/corelib/kernel/qvariant.h | 58 +++++++++++++++++++++++------------------ 2 files changed, 35 insertions(+), 25 deletions(-) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp index 77d2c8cbe1..cd4e233af0 100644 --- a/src/corelib/kernel/qvariant.cpp +++ b/src/corelib/kernel/qvariant.cpp @@ -4282,6 +4282,7 @@ QDebug operator<<(QDebug dbg, const QVariant::Type p) \sa fromValue() */ +#if QT_DEPRECATED_SINCE(5, 14) /*! \fn template QVariant qVariantFromValue(const T &value) \relates QVariant @@ -4319,6 +4320,7 @@ QDebug operator<<(QDebug dbg, const QVariant::Type p) \sa QVariant::setValue() */ +#endif /*! \fn template T qvariant_cast(const QVariant &value) diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h index f95502e75f..90f5f5fc34 100644 --- a/src/corelib/kernel/qvariant.h +++ b/src/corelib/kernel/qvariant.h @@ -92,9 +92,6 @@ class QUrl; class QVariant; class QVariantComparisonHelper; -template -inline QVariant qVariantFromValue(const T &); - template inline T qvariant_cast(const QVariant &); @@ -365,7 +362,7 @@ class Q_CORE_EXPORT QVariant template static inline QVariant fromValue(const T &value) - { return qVariantFromValue(value); } + { return QVariant(qMetaTypeId(), &value, QTypeInfo::isPointer); } #if QT_HAS_INCLUDE() && __cplusplus >= 201703L template @@ -516,50 +513,61 @@ public: inline const DataPtr &data_ptr() const { return d; } }; +#if QT_DEPRECATED_SINCE(5, 14) template +QT_DEPRECATED_X("Use QVariant::fromValue() instead.") inline QVariant qVariantFromValue(const T &t) { - return QVariant(qMetaTypeId(), &t, QTypeInfo::isPointer); + return QVariant::fromValue(t); +} + +template +QT_DEPRECATED_X("Use QVariant::setValue() instead.") +inline void qVariantSetValue(QVariant &v, const T &t) +{ + v.setValue(t); } +#endif -template <> -inline QVariant qVariantFromValue(const QVariant &t) { return t; } +template<> +inline QVariant QVariant::fromValue(const QVariant &value) +{ + return value; +} #if QT_HAS_INCLUDE() && __cplusplus >= 201703L -template <> -inline QVariant qVariantFromValue(const std::monostate &) { return QVariant(); } +template<> +inline QVariant QVariant::fromValue(const std::monostate &) +{ + return QVariant(); +} #endif -template -inline void qVariantSetValue(QVariant &v, const T &t) +inline bool QVariant::isValid() const { return d.type != Invalid; } + +template +inline void QVariant::setValue(const T &avalue) { - //if possible we reuse the current QVariant private + // If possible we reuse the current QVariant private. const uint type = qMetaTypeId(); - QVariant::Private &d = v.data_ptr(); - if (v.isDetached() && (type == d.type || (type <= uint(QVariant::Char) && d.type <= uint(QVariant::Char)))) { + if (isDetached() && (type == d.type || (type <= uint(QVariant::Char) && d.type <= uint(QVariant::Char)))) { d.type = type; d.is_null = false; T *old = reinterpret_cast(d.is_shared ? d.data.shared->ptr : &d.data.ptr); if (QTypeInfo::isComplex) old->~T(); - new (old) T(t); //call the copy constructor + new (old) T(avalue); // call the copy constructor } else { - v = QVariant(type, &t, QTypeInfo::isPointer); + *this = QVariant(type, &avalue, QTypeInfo::isPointer); } } -template <> -inline void qVariantSetValue(QVariant &v, const QVariant &t) +template<> +inline void QVariant::setValue(const QVariant &avalue) { - v = t; + *this = avalue; } -inline bool QVariant::isValid() const { return d.type != Invalid; } - -template -inline void QVariant::setValue(const T &avalue) -{ qVariantSetValue(*this, avalue); } - #ifndef QT_NO_DATASTREAM Q_CORE_EXPORT QDataStream& operator>> (QDataStream& s, QVariant& p); Q_CORE_EXPORT QDataStream& operator<< (QDataStream& s, const QVariant& p); -- cgit v1.2.3 From 05d9195669216038569aff7cf2901bd8e7a71ceb Mon Sep 17 00:00:00 2001 From: Venugopal Shivashankar Date: Thu, 28 Mar 2019 16:06:16 +0100 Subject: Doc: Use the \nullptr macro instead of 0 This enables overriding the macro so that it translates to 'None' in the Qt for Python context. Change-Id: Ib3cecf57eeb0405a1929309b71e9f012a07f11cf Reviewed-by: Christian Ehrlicher --- src/corelib/kernel/qabstracteventdispatcher.cpp | 2 +- src/corelib/kernel/qcoreapplication.cpp | 2 +- src/corelib/kernel/qmetaobject.cpp | 4 ++-- src/corelib/kernel/qobject.cpp | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qabstracteventdispatcher.cpp b/src/corelib/kernel/qabstracteventdispatcher.cpp index 8e1b560874..ea08ff571f 100644 --- a/src/corelib/kernel/qabstracteventdispatcher.cpp +++ b/src/corelib/kernel/qabstracteventdispatcher.cpp @@ -162,7 +162,7 @@ QAbstractEventDispatcher::~QAbstractEventDispatcher() Returns a pointer to the event dispatcher object for the specified \a thread. If \a thread is zero, the current thread is used. If no event dispatcher exists for the specified thread, this function - returns 0. + returns \nullptr. \b{Note:} If Qt is built without thread support, the \a thread argument is ignored. diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index c637f0c1c9..6d7985c91b 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -2923,7 +2923,7 @@ bool QCoreApplication::hasPendingEvents() /*! Returns a pointer to the event dispatcher object for the main thread. If no - event dispatcher exists for the thread, this function returns 0. + event dispatcher exists for the thread, this function returns \nullptr. */ QAbstractEventDispatcher *QCoreApplication::eventDispatcher() { diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp index 5de2717078..b8b5c0de46 100644 --- a/src/corelib/kernel/qmetaobject.cpp +++ b/src/corelib/kernel/qmetaobject.cpp @@ -349,7 +349,7 @@ bool QMetaObject::inherits(const QMetaObject *metaObject) const Q_DECL_NOEXCEPT \internal Returns \a obj if object \a obj inherits from this - meta-object; otherwise returns 0. + meta-object; otherwise returns \nullptr. */ QObject *QMetaObject::cast(QObject *obj) const { @@ -361,7 +361,7 @@ QObject *QMetaObject::cast(QObject *obj) const \internal Returns \a obj if object \a obj inherits from this - meta-object; otherwise returns 0. + meta-object; otherwise returns \nullptr. */ const QObject *QMetaObject::cast(const QObject *obj) const { diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index cf838b6947..a791d2e8b3 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -2342,7 +2342,7 @@ static void err_info_about_objects(const char * func, /*! Returns a pointer to the object that sent the signal, if called in - a slot activated by a signal; otherwise it returns 0. The pointer + a slot activated by a signal; otherwise it returns \nullptr. The pointer is valid only during the execution of the slot that calls this function from this object's thread context. -- cgit v1.2.3 From 6c761a0db11b7a2b0104dbf46607ca396ae7ee2d Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Tue, 2 Apr 2019 10:58:32 +0200 Subject: Replace Q_NULLPTR with nullptr in corelib Change-Id: I9cdb5b7015c62c50b35f8a6519ea4e777db97683 Reviewed-by: Thiago Macieira --- src/corelib/kernel/qtestsupport_core.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qtestsupport_core.cpp b/src/corelib/kernel/qtestsupport_core.cpp index c54b933f94..7bd81ed498 100644 --- a/src/corelib/kernel/qtestsupport_core.cpp +++ b/src/corelib/kernel/qtestsupport_core.cpp @@ -102,7 +102,7 @@ Q_CORE_EXPORT void QTest::qWait(int ms) int remaining = ms; do { QCoreApplication::processEvents(QEventLoop::AllEvents, remaining); - QCoreApplication::sendPostedEvents(Q_NULLPTR, QEvent::DeferredDelete); + QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete); remaining = timer.remainingTime(); if (remaining <= 0) break; -- cgit v1.2.3 From a1e62e7ba14b00ac7c361936a18e7bc42bf1286d Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Tue, 2 Apr 2019 10:54:54 +0200 Subject: Replace Q_DECL_NOEXCEPT with noexcept in corelib In preparation of Qt6 move away from pre-C++11 macros. Change-Id: I44126693c20c18eca5620caab4f7e746218e0ce3 Reviewed-by: Thiago Macieira --- src/corelib/kernel/qcore_unix_p.h | 2 +- src/corelib/kernel/qcoreapplication.cpp | 2 +- src/corelib/kernel/qcoreevent.cpp | 8 ++--- src/corelib/kernel/qcoreevent.h | 2 +- src/corelib/kernel/qdeadlinetimer.cpp | 24 ++++++------- src/corelib/kernel/qdeadlinetimer.h | 50 ++++++++++++++-------------- src/corelib/kernel/qelapsedtimer.cpp | 6 ++-- src/corelib/kernel/qelapsedtimer.h | 30 ++++++++--------- src/corelib/kernel/qelapsedtimer_generic.cpp | 22 ++++++------ src/corelib/kernel/qelapsedtimer_mac.cpp | 24 ++++++------- src/corelib/kernel/qelapsedtimer_unix.cpp | 24 ++++++------- src/corelib/kernel/qelapsedtimer_win.cpp | 22 ++++++------ src/corelib/kernel/qeventdispatcher_unix_p.h | 12 +++---- src/corelib/kernel/qfunctions_fake_env_p.h | 4 +-- src/corelib/kernel/qmetaobject.cpp | 2 +- src/corelib/kernel/qmetatype.cpp | 2 +- src/corelib/kernel/qobject.cpp | 2 +- src/corelib/kernel/qobject.h | 32 +++++++++--------- src/corelib/kernel/qobjectdefs.h | 14 ++++---- src/corelib/kernel/qobjectdefs_impl.h | 4 +-- src/corelib/kernel/qtimer.h | 2 +- src/corelib/kernel/qvariant.h | 14 ++++---- 22 files changed, 152 insertions(+), 152 deletions(-) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qcore_unix_p.h b/src/corelib/kernel/qcore_unix_p.h index 32ef6408c2..7f58813535 100644 --- a/src/corelib/kernel/qcore_unix_p.h +++ b/src/corelib/kernel/qcore_unix_p.h @@ -347,7 +347,7 @@ static inline pid_t qt_safe_waitpid(pid_t pid, int *status, int options) #endif // in qelapsedtimer_mac.cpp or qtimestamp_unix.cpp -timespec qt_gettime() Q_DECL_NOTHROW; +timespec qt_gettime() noexcept; void qt_nanosleep(timespec amount); QByteArray qt_readlink(const char *path); diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index 5da33a5aae..038de264cb 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -369,7 +369,7 @@ uint QCoreApplicationPrivate::attribs = (1 << Qt::AA_SynthesizeMouseForUnhandledTabletEvents); struct QCoreApplicationData { - QCoreApplicationData() Q_DECL_NOTHROW { + QCoreApplicationData() noexcept { applicationNameSet = false; applicationVersionSet = false; } diff --git a/src/corelib/kernel/qcoreevent.cpp b/src/corelib/kernel/qcoreevent.cpp index cacbb1e495..aabd32b4a8 100644 --- a/src/corelib/kernel/qcoreevent.cpp +++ b/src/corelib/kernel/qcoreevent.cpp @@ -421,7 +421,7 @@ struct QBasicAtomicBitField { QBasicAtomicInteger next; QBasicAtomicInteger data[NumInts]; - bool allocateSpecific(int which) Q_DECL_NOTHROW + bool allocateSpecific(int which) noexcept { QBasicAtomicInteger &entry = data[which / BitsPerInt]; const uint old = entry.load(); @@ -437,7 +437,7 @@ struct QBasicAtomicBitField { // loop. } - int allocateNext() Q_DECL_NOTHROW + int allocateNext() noexcept { // Unroll loop to iterate over ints, then bits? Would save // potentially a lot of cmpxchgs, because we can scan the @@ -463,7 +463,7 @@ typedef QBasicAtomicBitField UserEventTypeRe static UserEventTypeRegistry userEventTypeRegistry; -static inline int registerEventTypeZeroBased(int id) Q_DECL_NOTHROW +static inline int registerEventTypeZeroBased(int id) noexcept { // if the type hint hasn't been registered yet, take it: if (id < UserEventTypeRegistry::NumBits && id >= 0 && userEventTypeRegistry.allocateSpecific(id)) @@ -486,7 +486,7 @@ static inline int registerEventTypeZeroBased(int id) Q_DECL_NOTHROW Returns -1 if all available values are already taken or the program is shutting down. */ -int QEvent::registerEventType(int hint) Q_DECL_NOTHROW +int QEvent::registerEventType(int hint) noexcept { const int result = registerEventTypeZeroBased(QEvent::MaxUser - hint); return result < 0 ? -1 : QEvent::MaxUser - result ; diff --git a/src/corelib/kernel/qcoreevent.h b/src/corelib/kernel/qcoreevent.h index ac974ba411..05af1a6132 100644 --- a/src/corelib/kernel/qcoreevent.h +++ b/src/corelib/kernel/qcoreevent.h @@ -307,7 +307,7 @@ public: inline void accept() { m_accept = true; } inline void ignore() { m_accept = false; } - static int registerEventType(int hint = -1) Q_DECL_NOTHROW; + static int registerEventType(int hint = -1) noexcept; protected: QEventPrivate *d; diff --git a/src/corelib/kernel/qdeadlinetimer.cpp b/src/corelib/kernel/qdeadlinetimer.cpp index 6aa886cfe1..e0d9d9de73 100644 --- a/src/corelib/kernel/qdeadlinetimer.cpp +++ b/src/corelib/kernel/qdeadlinetimer.cpp @@ -188,7 +188,7 @@ Q_DECL_CONST_FUNCTION static inline QPair toSecsAndNSecs(qint64 \sa hasExpired(), isForever(), remainingTime(), setRemainingTime() */ -QDeadlineTimer::QDeadlineTimer(qint64 msecs, Qt::TimerType type) Q_DECL_NOTHROW +QDeadlineTimer::QDeadlineTimer(qint64 msecs, Qt::TimerType type) noexcept : t2(0) { setRemainingTime(msecs, type); @@ -260,7 +260,7 @@ QDeadlineTimer::QDeadlineTimer(qint64 msecs, Qt::TimerType type) Q_DECL_NOTHROW \sa setPreciseRemainingTime(), hasExpired(), isForever(), remainingTime() */ -void QDeadlineTimer::setRemainingTime(qint64 msecs, Qt::TimerType timerType) Q_DECL_NOTHROW +void QDeadlineTimer::setRemainingTime(qint64 msecs, Qt::TimerType timerType) noexcept { if (msecs == -1) *this = QDeadlineTimer(Forever, timerType); @@ -279,7 +279,7 @@ void QDeadlineTimer::setRemainingTime(qint64 msecs, Qt::TimerType timerType) Q_D \sa setRemainingTime(), hasExpired(), isForever(), remainingTime() */ -void QDeadlineTimer::setPreciseRemainingTime(qint64 secs, qint64 nsecs, Qt::TimerType timerType) Q_DECL_NOTHROW +void QDeadlineTimer::setPreciseRemainingTime(qint64 secs, qint64 nsecs, Qt::TimerType timerType) noexcept { if (secs == -1) { *this = QDeadlineTimer(Forever, timerType); @@ -342,7 +342,7 @@ void QDeadlineTimer::setPreciseRemainingTime(qint64 secs, qint64 nsecs, Qt::Time \sa isForever(), remainingTime() */ -bool QDeadlineTimer::hasExpired() const Q_DECL_NOTHROW +bool QDeadlineTimer::hasExpired() const noexcept { if (isForever()) return false; @@ -389,7 +389,7 @@ void QDeadlineTimer::setTimerType(Qt::TimerType timerType) \sa remainingTimeNSecs(), isForever(), hasExpired() */ -qint64 QDeadlineTimer::remainingTime() const Q_DECL_NOTHROW +qint64 QDeadlineTimer::remainingTime() const noexcept { qint64 ns = remainingTimeNSecs(); return ns <= 0 ? ns : (ns + 999999) / (1000 * 1000); @@ -403,7 +403,7 @@ qint64 QDeadlineTimer::remainingTime() const Q_DECL_NOTHROW \sa remainingTime(), isForever(), hasExpired() */ -qint64 QDeadlineTimer::remainingTimeNSecs() const Q_DECL_NOTHROW +qint64 QDeadlineTimer::remainingTimeNSecs() const noexcept { if (isForever()) return -1; @@ -416,7 +416,7 @@ qint64 QDeadlineTimer::remainingTimeNSecs() const Q_DECL_NOTHROW Same as remainingTimeNSecs, but may return negative remaining times. Does not deal with Forever. */ -qint64 QDeadlineTimer::rawRemainingTimeNSecs() const Q_DECL_NOTHROW +qint64 QDeadlineTimer::rawRemainingTimeNSecs() const noexcept { QDeadlineTimer now = current(timerType()); if (QDeadlineTimerNanosecondsInT2) @@ -444,7 +444,7 @@ qint64 QDeadlineTimer::rawRemainingTimeNSecs() const Q_DECL_NOTHROW \sa remainingTime(), deadlineNSecs(), setDeadline() */ -qint64 QDeadlineTimer::deadline() const Q_DECL_NOTHROW +qint64 QDeadlineTimer::deadline() const noexcept { if (isForever()) return t1; @@ -471,7 +471,7 @@ qint64 QDeadlineTimer::deadline() const Q_DECL_NOTHROW \sa remainingTime(), deadlineNSecs() */ -qint64 QDeadlineTimer::deadlineNSecs() const Q_DECL_NOTHROW +qint64 QDeadlineTimer::deadlineNSecs() const noexcept { if (isForever()) return t1; @@ -492,7 +492,7 @@ qint64 QDeadlineTimer::deadlineNSecs() const Q_DECL_NOTHROW \sa setPreciseDeadline(), deadline(), deadlineNSecs(), setRemainingTime() */ -void QDeadlineTimer::setDeadline(qint64 msecs, Qt::TimerType timerType) Q_DECL_NOTHROW +void QDeadlineTimer::setDeadline(qint64 msecs, Qt::TimerType timerType) noexcept { if (msecs == (std::numeric_limits::max)()) { setPreciseDeadline(msecs, 0, timerType); // msecs == MAX implies Forever @@ -513,7 +513,7 @@ void QDeadlineTimer::setDeadline(qint64 msecs, Qt::TimerType timerType) Q_DECL_N \sa setDeadline(), deadline(), deadlineNSecs(), setRemainingTime() */ -void QDeadlineTimer::setPreciseDeadline(qint64 secs, qint64 nsecs, Qt::TimerType timerType) Q_DECL_NOTHROW +void QDeadlineTimer::setPreciseDeadline(qint64 secs, qint64 nsecs, Qt::TimerType timerType) noexcept { type = timerType; if (secs == (std::numeric_limits::max)() || nsecs == (std::numeric_limits::max)()) { @@ -534,7 +534,7 @@ void QDeadlineTimer::setPreciseDeadline(qint64 secs, qint64 nsecs, Qt::TimerType \note if \a dt was created as expired, its deadline is indeterminate and adding an amount of time may or may not cause it to become unexpired. */ -QDeadlineTimer QDeadlineTimer::addNSecs(QDeadlineTimer dt, qint64 nsecs) Q_DECL_NOTHROW +QDeadlineTimer QDeadlineTimer::addNSecs(QDeadlineTimer dt, qint64 nsecs) noexcept { if (dt.isForever() || nsecs == (std::numeric_limits::max)()) { dt = QDeadlineTimer(Forever, dt.timerType()); diff --git a/src/corelib/kernel/qdeadlinetimer.h b/src/corelib/kernel/qdeadlinetimer.h index 1a4ee04a96..8032ee9018 100644 --- a/src/corelib/kernel/qdeadlinetimer.h +++ b/src/corelib/kernel/qdeadlinetimer.h @@ -63,49 +63,49 @@ class Q_CORE_EXPORT QDeadlineTimer public: enum ForeverConstant { Forever }; - Q_DECL_CONSTEXPR QDeadlineTimer(Qt::TimerType type_ = Qt::CoarseTimer) Q_DECL_NOTHROW + Q_DECL_CONSTEXPR QDeadlineTimer(Qt::TimerType type_ = Qt::CoarseTimer) noexcept : t1(0), t2(0), type(type_) {} - Q_DECL_CONSTEXPR QDeadlineTimer(ForeverConstant, Qt::TimerType type_ = Qt::CoarseTimer) Q_DECL_NOTHROW + Q_DECL_CONSTEXPR QDeadlineTimer(ForeverConstant, Qt::TimerType type_ = Qt::CoarseTimer) noexcept : t1(std::numeric_limits::max()), t2(0), type(type_) {} - explicit QDeadlineTimer(qint64 msecs, Qt::TimerType type = Qt::CoarseTimer) Q_DECL_NOTHROW; + explicit QDeadlineTimer(qint64 msecs, Qt::TimerType type = Qt::CoarseTimer) noexcept; - void swap(QDeadlineTimer &other) Q_DECL_NOTHROW + void swap(QDeadlineTimer &other) noexcept { qSwap(t1, other.t1); qSwap(t2, other.t2); qSwap(type, other.type); } - Q_DECL_CONSTEXPR bool isForever() const Q_DECL_NOTHROW + Q_DECL_CONSTEXPR bool isForever() const noexcept { return t1 == (std::numeric_limits::max)(); } - bool hasExpired() const Q_DECL_NOTHROW; + bool hasExpired() const noexcept; - Qt::TimerType timerType() const Q_DECL_NOTHROW + Qt::TimerType timerType() const noexcept { return Qt::TimerType(type & 0xff); } void setTimerType(Qt::TimerType type); - qint64 remainingTime() const Q_DECL_NOTHROW; - qint64 remainingTimeNSecs() const Q_DECL_NOTHROW; - void setRemainingTime(qint64 msecs, Qt::TimerType type = Qt::CoarseTimer) Q_DECL_NOTHROW; + qint64 remainingTime() const noexcept; + qint64 remainingTimeNSecs() const noexcept; + void setRemainingTime(qint64 msecs, Qt::TimerType type = Qt::CoarseTimer) noexcept; void setPreciseRemainingTime(qint64 secs, qint64 nsecs = 0, - Qt::TimerType type = Qt::CoarseTimer) Q_DECL_NOTHROW; + Qt::TimerType type = Qt::CoarseTimer) noexcept; - qint64 deadline() const Q_DECL_NOTHROW Q_DECL_PURE_FUNCTION; - qint64 deadlineNSecs() const Q_DECL_NOTHROW Q_DECL_PURE_FUNCTION; - void setDeadline(qint64 msecs, Qt::TimerType timerType = Qt::CoarseTimer) Q_DECL_NOTHROW; + qint64 deadline() const noexcept Q_DECL_PURE_FUNCTION; + qint64 deadlineNSecs() const noexcept Q_DECL_PURE_FUNCTION; + void setDeadline(qint64 msecs, Qt::TimerType timerType = Qt::CoarseTimer) noexcept; void setPreciseDeadline(qint64 secs, qint64 nsecs = 0, - Qt::TimerType type = Qt::CoarseTimer) Q_DECL_NOTHROW; + Qt::TimerType type = Qt::CoarseTimer) noexcept; - static QDeadlineTimer addNSecs(QDeadlineTimer dt, qint64 nsecs) Q_DECL_NOTHROW Q_DECL_PURE_FUNCTION; - static QDeadlineTimer current(Qt::TimerType timerType = Qt::CoarseTimer) Q_DECL_NOTHROW; + static QDeadlineTimer addNSecs(QDeadlineTimer dt, qint64 nsecs) noexcept Q_DECL_PURE_FUNCTION; + static QDeadlineTimer current(Qt::TimerType timerType = Qt::CoarseTimer) noexcept; - friend bool operator==(QDeadlineTimer d1, QDeadlineTimer d2) Q_DECL_NOTHROW + friend bool operator==(QDeadlineTimer d1, QDeadlineTimer d2) noexcept { return d1.t1 == d2.t1 && d1.t2 == d2.t2; } - friend bool operator!=(QDeadlineTimer d1, QDeadlineTimer d2) Q_DECL_NOTHROW + friend bool operator!=(QDeadlineTimer d1, QDeadlineTimer d2) noexcept { return !(d1 == d2); } - friend bool operator<(QDeadlineTimer d1, QDeadlineTimer d2) Q_DECL_NOTHROW + friend bool operator<(QDeadlineTimer d1, QDeadlineTimer d2) noexcept { return d1.t1 < d2.t1 || (d1.t1 == d2.t1 && d1.t2 < d2.t2); } - friend bool operator<=(QDeadlineTimer d1, QDeadlineTimer d2) Q_DECL_NOTHROW + friend bool operator<=(QDeadlineTimer d1, QDeadlineTimer d2) noexcept { return d1 == d2 || d1 < d2; } - friend bool operator>(QDeadlineTimer d1, QDeadlineTimer d2) Q_DECL_NOTHROW + friend bool operator>(QDeadlineTimer d1, QDeadlineTimer d2) noexcept { return d2 < d1; } - friend bool operator>=(QDeadlineTimer d1, QDeadlineTimer d2) Q_DECL_NOTHROW + friend bool operator>=(QDeadlineTimer d1, QDeadlineTimer d2) noexcept { return !(d1 < d2); } friend QDeadlineTimer operator+(QDeadlineTimer dt, qint64 msecs) @@ -160,7 +160,7 @@ public: setPreciseRemainingTime(0, std::chrono::nanoseconds(remaining).count(), type_); } - std::chrono::nanoseconds remainingTimeAsDuration() const Q_DECL_NOTHROW + std::chrono::nanoseconds remainingTimeAsDuration() const noexcept { if (isForever()) return std::chrono::nanoseconds::max(); @@ -186,7 +186,7 @@ private: unsigned t2; unsigned type; - qint64 rawRemainingTimeNSecs() const Q_DECL_NOTHROW; + qint64 rawRemainingTimeNSecs() const noexcept; public: // This is not a public function, it's here only for Qt's internal convenience... diff --git a/src/corelib/kernel/qelapsedtimer.cpp b/src/corelib/kernel/qelapsedtimer.cpp index e578b5b8b3..adb554b624 100644 --- a/src/corelib/kernel/qelapsedtimer.cpp +++ b/src/corelib/kernel/qelapsedtimer.cpp @@ -236,7 +236,7 @@ static const qint64 invalidData = Q_INT64_C(0x8000000000000000); \sa isValid(), start(), restart() */ -void QElapsedTimer::invalidate() Q_DECL_NOTHROW +void QElapsedTimer::invalidate() noexcept { t1 = t2 = invalidData; } @@ -247,7 +247,7 @@ void QElapsedTimer::invalidate() Q_DECL_NOTHROW \sa invalidate(), start(), restart() */ -bool QElapsedTimer::isValid() const Q_DECL_NOTHROW +bool QElapsedTimer::isValid() const noexcept { return t1 != invalidData && t2 != invalidData; } @@ -260,7 +260,7 @@ bool QElapsedTimer::isValid() const Q_DECL_NOTHROW \sa elapsed(), QDeadlineTimer */ -bool QElapsedTimer::hasExpired(qint64 timeout) const Q_DECL_NOTHROW +bool QElapsedTimer::hasExpired(qint64 timeout) const noexcept { // if timeout is -1, quint64(timeout) is LLINT_MAX, so this will be // considered as never expired diff --git a/src/corelib/kernel/qelapsedtimer.h b/src/corelib/kernel/qelapsedtimer.h index 7954b41bf4..873847f6b6 100644 --- a/src/corelib/kernel/qelapsedtimer.h +++ b/src/corelib/kernel/qelapsedtimer.h @@ -62,28 +62,28 @@ public: { } - static ClockType clockType() Q_DECL_NOTHROW; - static bool isMonotonic() Q_DECL_NOTHROW; + static ClockType clockType() noexcept; + static bool isMonotonic() noexcept; - void start() Q_DECL_NOTHROW; - qint64 restart() Q_DECL_NOTHROW; - void invalidate() Q_DECL_NOTHROW; - bool isValid() const Q_DECL_NOTHROW; + void start() noexcept; + qint64 restart() noexcept; + void invalidate() noexcept; + bool isValid() const noexcept; - qint64 nsecsElapsed() const Q_DECL_NOTHROW; - qint64 elapsed() const Q_DECL_NOTHROW; - bool hasExpired(qint64 timeout) const Q_DECL_NOTHROW; + qint64 nsecsElapsed() const noexcept; + qint64 elapsed() const noexcept; + bool hasExpired(qint64 timeout) const noexcept; - qint64 msecsSinceReference() const Q_DECL_NOTHROW; - qint64 msecsTo(const QElapsedTimer &other) const Q_DECL_NOTHROW; - qint64 secsTo(const QElapsedTimer &other) const Q_DECL_NOTHROW; + qint64 msecsSinceReference() const noexcept; + qint64 msecsTo(const QElapsedTimer &other) const noexcept; + qint64 secsTo(const QElapsedTimer &other) const noexcept; - bool operator==(const QElapsedTimer &other) const Q_DECL_NOTHROW + bool operator==(const QElapsedTimer &other) const noexcept { return t1 == other.t1 && t2 == other.t2; } - bool operator!=(const QElapsedTimer &other) const Q_DECL_NOTHROW + bool operator!=(const QElapsedTimer &other) const noexcept { return !(*this == other); } - friend bool Q_CORE_EXPORT operator<(const QElapsedTimer &v1, const QElapsedTimer &v2) Q_DECL_NOTHROW; + friend bool Q_CORE_EXPORT operator<(const QElapsedTimer &v1, const QElapsedTimer &v2) noexcept; private: qint64 t1; diff --git a/src/corelib/kernel/qelapsedtimer_generic.cpp b/src/corelib/kernel/qelapsedtimer_generic.cpp index fdeb385188..fe959e3c94 100644 --- a/src/corelib/kernel/qelapsedtimer_generic.cpp +++ b/src/corelib/kernel/qelapsedtimer_generic.cpp @@ -48,7 +48,7 @@ QT_BEGIN_NAMESPACE \sa isMonotonic() */ -QElapsedTimer::ClockType QElapsedTimer::clockType() Q_DECL_NOTHROW +QElapsedTimer::ClockType QElapsedTimer::clockType() noexcept { return SystemTime; } @@ -60,7 +60,7 @@ QElapsedTimer::ClockType QElapsedTimer::clockType() Q_DECL_NOTHROW \sa clockType(), QElapsedTimer::ClockType */ -bool QElapsedTimer::isMonotonic() Q_DECL_NOTHROW +bool QElapsedTimer::isMonotonic() noexcept { return false; } @@ -75,7 +75,7 @@ bool QElapsedTimer::isMonotonic() Q_DECL_NOTHROW \sa restart(), invalidate(), elapsed() */ -void QElapsedTimer::start() Q_DECL_NOTHROW +void QElapsedTimer::start() noexcept { restart(); } @@ -97,7 +97,7 @@ void QElapsedTimer::start() Q_DECL_NOTHROW \sa start(), invalidate(), elapsed(), isValid() */ -qint64 QElapsedTimer::restart() Q_DECL_NOTHROW +qint64 QElapsedTimer::restart() noexcept { qint64 old = t1; t1 = QDateTime::currentMSecsSinceEpoch(); @@ -118,7 +118,7 @@ qint64 QElapsedTimer::restart() Q_DECL_NOTHROW \sa start(), restart(), hasExpired(), invalidate() */ -qint64 QElapsedTimer::nsecsElapsed() const Q_DECL_NOTHROW +qint64 QElapsedTimer::nsecsElapsed() const noexcept { return elapsed() * 1000000; } @@ -132,7 +132,7 @@ qint64 QElapsedTimer::nsecsElapsed() const Q_DECL_NOTHROW \sa start(), restart(), hasExpired(), isValid(), invalidate() */ -qint64 QElapsedTimer::elapsed() const Q_DECL_NOTHROW +qint64 QElapsedTimer::elapsed() const noexcept { return QDateTime::currentMSecsSinceEpoch() - t1; } @@ -152,7 +152,7 @@ qint64 QElapsedTimer::elapsed() const Q_DECL_NOTHROW \sa clockType(), elapsed() */ -qint64 QElapsedTimer::msecsSinceReference() const Q_DECL_NOTHROW +qint64 QElapsedTimer::msecsSinceReference() const noexcept { return t1; } @@ -167,7 +167,7 @@ qint64 QElapsedTimer::msecsSinceReference() const Q_DECL_NOTHROW \sa secsTo(), elapsed() */ -qint64 QElapsedTimer::msecsTo(const QElapsedTimer &other) const Q_DECL_NOTHROW +qint64 QElapsedTimer::msecsTo(const QElapsedTimer &other) const noexcept { qint64 diff = other.t1 - t1; return diff; @@ -183,7 +183,7 @@ qint64 QElapsedTimer::msecsTo(const QElapsedTimer &other) const Q_DECL_NOTHROW \sa msecsTo(), elapsed() */ -qint64 QElapsedTimer::secsTo(const QElapsedTimer &other) const Q_DECL_NOTHROW +qint64 QElapsedTimer::secsTo(const QElapsedTimer &other) const noexcept { return msecsTo(other) / 1000; } @@ -197,12 +197,12 @@ qint64 QElapsedTimer::secsTo(const QElapsedTimer &other) const Q_DECL_NOTHROW and the other isn't. However, two invalid timers are equal and thus this function will return false. */ -bool operator<(const QElapsedTimer &v1, const QElapsedTimer &v2) Q_DECL_NOTHROW +bool operator<(const QElapsedTimer &v1, const QElapsedTimer &v2) noexcept { return v1.t1 < v2.t1; } -QDeadlineTimer QDeadlineTimer::current(Qt::TimerType timerType) Q_DECL_NOTHROW +QDeadlineTimer QDeadlineTimer::current(Qt::TimerType timerType) noexcept { QDeadlineTimer result; result.t1 = QDateTime::currentMSecsSinceEpoch() * 1000 * 1000; diff --git a/src/corelib/kernel/qelapsedtimer_mac.cpp b/src/corelib/kernel/qelapsedtimer_mac.cpp index 7490693991..5370cf7b3d 100644 --- a/src/corelib/kernel/qelapsedtimer_mac.cpp +++ b/src/corelib/kernel/qelapsedtimer_mac.cpp @@ -58,12 +58,12 @@ typedef __int128_t LargeInt; typedef qint64 LargeInt; #endif -QElapsedTimer::ClockType QElapsedTimer::clockType() Q_DECL_NOTHROW +QElapsedTimer::ClockType QElapsedTimer::clockType() noexcept { return MachAbsoluteTime; } -bool QElapsedTimer::isMonotonic() Q_DECL_NOTHROW +bool QElapsedTimer::isMonotonic() noexcept { return true; } @@ -87,7 +87,7 @@ static qint64 absoluteToMSecs(qint64 cpuTime) return absoluteToNSecs(cpuTime) / 1000000; } -timespec qt_gettime() Q_DECL_NOTHROW +timespec qt_gettime() noexcept { timespec tv; @@ -107,13 +107,13 @@ void qt_nanosleep(timespec amount) EINTR_LOOP(r, nanosleep(&amount, &amount)); } -void QElapsedTimer::start() Q_DECL_NOTHROW +void QElapsedTimer::start() noexcept { t1 = mach_absolute_time(); t2 = 0; } -qint64 QElapsedTimer::restart() Q_DECL_NOTHROW +qint64 QElapsedTimer::restart() noexcept { qint64 old = t1; t1 = mach_absolute_time(); @@ -122,39 +122,39 @@ qint64 QElapsedTimer::restart() Q_DECL_NOTHROW return absoluteToMSecs(t1 - old); } -qint64 QElapsedTimer::nsecsElapsed() const Q_DECL_NOTHROW +qint64 QElapsedTimer::nsecsElapsed() const noexcept { uint64_t cpu_time = mach_absolute_time(); return absoluteToNSecs(cpu_time - t1); } -qint64 QElapsedTimer::elapsed() const Q_DECL_NOTHROW +qint64 QElapsedTimer::elapsed() const noexcept { uint64_t cpu_time = mach_absolute_time(); return absoluteToMSecs(cpu_time - t1); } -qint64 QElapsedTimer::msecsSinceReference() const Q_DECL_NOTHROW +qint64 QElapsedTimer::msecsSinceReference() const noexcept { return absoluteToMSecs(t1); } -qint64 QElapsedTimer::msecsTo(const QElapsedTimer &other) const Q_DECL_NOTHROW +qint64 QElapsedTimer::msecsTo(const QElapsedTimer &other) const noexcept { return absoluteToMSecs(other.t1 - t1); } -qint64 QElapsedTimer::secsTo(const QElapsedTimer &other) const Q_DECL_NOTHROW +qint64 QElapsedTimer::secsTo(const QElapsedTimer &other) const noexcept { return msecsTo(other) / 1000; } -bool operator<(const QElapsedTimer &v1, const QElapsedTimer &v2) Q_DECL_NOTHROW +bool operator<(const QElapsedTimer &v1, const QElapsedTimer &v2) noexcept { return v1.t1 < v2.t1; } -QDeadlineTimer QDeadlineTimer::current(Qt::TimerType timerType) Q_DECL_NOTHROW +QDeadlineTimer QDeadlineTimer::current(Qt::TimerType timerType) noexcept { Q_STATIC_ASSERT(!QDeadlineTimerNanosecondsInT2); QDeadlineTimer result; diff --git a/src/corelib/kernel/qelapsedtimer_unix.cpp b/src/corelib/kernel/qelapsedtimer_unix.cpp index e166d4e3d2..ccc2eeafa3 100644 --- a/src/corelib/kernel/qelapsedtimer_unix.cpp +++ b/src/corelib/kernel/qelapsedtimer_unix.cpp @@ -150,12 +150,12 @@ static int unixCheckClockType() #endif } -bool QElapsedTimer::isMonotonic() Q_DECL_NOTHROW +bool QElapsedTimer::isMonotonic() noexcept { return clockType() == MonotonicClock; } -QElapsedTimer::ClockType QElapsedTimer::clockType() Q_DECL_NOTHROW +QElapsedTimer::ClockType QElapsedTimer::clockType() noexcept { return unixCheckClockType() == CLOCK_REALTIME ? SystemTime : MonotonicClock; } @@ -169,7 +169,7 @@ static inline void do_gettime(qint64 *sec, qint64 *frac) } // used in qcore_unix.cpp and qeventdispatcher_unix.cpp -struct timespec qt_gettime() Q_DECL_NOTHROW +struct timespec qt_gettime() noexcept { qint64 sec, frac; do_gettime(&sec, &frac); @@ -204,17 +204,17 @@ static qint64 elapsedAndRestart(qint64 sec, qint64 frac, return (sec * Q_INT64_C(1000000000) + frac) / Q_INT64_C(1000000); } -void QElapsedTimer::start() Q_DECL_NOTHROW +void QElapsedTimer::start() noexcept { do_gettime(&t1, &t2); } -qint64 QElapsedTimer::restart() Q_DECL_NOTHROW +qint64 QElapsedTimer::restart() noexcept { return elapsedAndRestart(t1, t2, &t1, &t2); } -qint64 QElapsedTimer::nsecsElapsed() const Q_DECL_NOTHROW +qint64 QElapsedTimer::nsecsElapsed() const noexcept { qint64 sec, frac; do_gettime(&sec, &frac); @@ -223,34 +223,34 @@ qint64 QElapsedTimer::nsecsElapsed() const Q_DECL_NOTHROW return sec * Q_INT64_C(1000000000) + frac; } -qint64 QElapsedTimer::elapsed() const Q_DECL_NOTHROW +qint64 QElapsedTimer::elapsed() const noexcept { return nsecsElapsed() / Q_INT64_C(1000000); } -qint64 QElapsedTimer::msecsSinceReference() const Q_DECL_NOTHROW +qint64 QElapsedTimer::msecsSinceReference() const noexcept { return t1 * Q_INT64_C(1000) + t2 / Q_INT64_C(1000000); } -qint64 QElapsedTimer::msecsTo(const QElapsedTimer &other) const Q_DECL_NOTHROW +qint64 QElapsedTimer::msecsTo(const QElapsedTimer &other) const noexcept { qint64 secs = other.t1 - t1; qint64 fraction = other.t2 - t2; return (secs * Q_INT64_C(1000000000) + fraction) / Q_INT64_C(1000000); } -qint64 QElapsedTimer::secsTo(const QElapsedTimer &other) const Q_DECL_NOTHROW +qint64 QElapsedTimer::secsTo(const QElapsedTimer &other) const noexcept { return other.t1 - t1; } -bool operator<(const QElapsedTimer &v1, const QElapsedTimer &v2) Q_DECL_NOTHROW +bool operator<(const QElapsedTimer &v1, const QElapsedTimer &v2) noexcept { return v1.t1 < v2.t1 || (v1.t1 == v2.t1 && v1.t2 < v2.t2); } -QDeadlineTimer QDeadlineTimer::current(Qt::TimerType timerType) Q_DECL_NOTHROW +QDeadlineTimer QDeadlineTimer::current(Qt::TimerType timerType) noexcept { Q_STATIC_ASSERT(QDeadlineTimerNanosecondsInT2); QDeadlineTimer result; diff --git a/src/corelib/kernel/qelapsedtimer_win.cpp b/src/corelib/kernel/qelapsedtimer_win.cpp index a63290d2f8..d8a50a8277 100644 --- a/src/corelib/kernel/qelapsedtimer_win.cpp +++ b/src/corelib/kernel/qelapsedtimer_win.cpp @@ -110,25 +110,25 @@ quint64 qt_msectime() return ticksToNanoseconds(getTickCount()) / 1000000; } -QElapsedTimer::ClockType QElapsedTimer::clockType() Q_DECL_NOTHROW +QElapsedTimer::ClockType QElapsedTimer::clockType() noexcept { resolveCounterFrequency(); return counterFrequency > 0 ? PerformanceCounter : TickCounter; } -bool QElapsedTimer::isMonotonic() Q_DECL_NOTHROW +bool QElapsedTimer::isMonotonic() noexcept { return true; } -void QElapsedTimer::start() Q_DECL_NOTHROW +void QElapsedTimer::start() noexcept { t1 = getTickCount(); t2 = 0; } -qint64 QElapsedTimer::restart() Q_DECL_NOTHROW +qint64 QElapsedTimer::restart() noexcept { qint64 oldt1 = t1; t1 = getTickCount(); @@ -136,40 +136,40 @@ qint64 QElapsedTimer::restart() Q_DECL_NOTHROW return ticksToNanoseconds(t1 - oldt1) / 1000000; } -qint64 QElapsedTimer::nsecsElapsed() const Q_DECL_NOTHROW +qint64 QElapsedTimer::nsecsElapsed() const noexcept { qint64 elapsed = getTickCount() - t1; return ticksToNanoseconds(elapsed); } -qint64 QElapsedTimer::elapsed() const Q_DECL_NOTHROW +qint64 QElapsedTimer::elapsed() const noexcept { qint64 elapsed = getTickCount() - t1; return ticksToNanoseconds(elapsed) / 1000000; } -qint64 QElapsedTimer::msecsSinceReference() const Q_DECL_NOTHROW +qint64 QElapsedTimer::msecsSinceReference() const noexcept { return ticksToNanoseconds(t1) / 1000000; } -qint64 QElapsedTimer::msecsTo(const QElapsedTimer &other) const Q_DECL_NOTHROW +qint64 QElapsedTimer::msecsTo(const QElapsedTimer &other) const noexcept { qint64 difference = other.t1 - t1; return ticksToNanoseconds(difference) / 1000000; } -qint64 QElapsedTimer::secsTo(const QElapsedTimer &other) const Q_DECL_NOTHROW +qint64 QElapsedTimer::secsTo(const QElapsedTimer &other) const noexcept { return msecsTo(other) / 1000; } -bool operator<(const QElapsedTimer &v1, const QElapsedTimer &v2) Q_DECL_NOTHROW +bool operator<(const QElapsedTimer &v1, const QElapsedTimer &v2) noexcept { return (v1.t1 - v2.t1) < 0; } -QDeadlineTimer QDeadlineTimer::current(Qt::TimerType timerType) Q_DECL_NOTHROW +QDeadlineTimer QDeadlineTimer::current(Qt::TimerType timerType) noexcept { Q_STATIC_ASSERT(!QDeadlineTimerNanosecondsInT2); QDeadlineTimer result; diff --git a/src/corelib/kernel/qeventdispatcher_unix_p.h b/src/corelib/kernel/qeventdispatcher_unix_p.h index 8cfa4bbdf7..f37edfc967 100644 --- a/src/corelib/kernel/qeventdispatcher_unix_p.h +++ b/src/corelib/kernel/qeventdispatcher_unix_p.h @@ -64,10 +64,10 @@ class QEventDispatcherUNIXPrivate; struct Q_CORE_EXPORT QSocketNotifierSetUNIX final { - inline QSocketNotifierSetUNIX() Q_DECL_NOTHROW; + inline QSocketNotifierSetUNIX() noexcept; - inline bool isEmpty() const Q_DECL_NOTHROW; - inline short events() const Q_DECL_NOTHROW; + inline bool isEmpty() const noexcept; + inline short events() const noexcept; QSocketNotifier *notifiers[3]; }; @@ -150,19 +150,19 @@ public: QAtomicInt interrupt; // bool }; -inline QSocketNotifierSetUNIX::QSocketNotifierSetUNIX() Q_DECL_NOTHROW +inline QSocketNotifierSetUNIX::QSocketNotifierSetUNIX() noexcept { notifiers[0] = nullptr; notifiers[1] = nullptr; notifiers[2] = nullptr; } -inline bool QSocketNotifierSetUNIX::isEmpty() const Q_DECL_NOTHROW +inline bool QSocketNotifierSetUNIX::isEmpty() const noexcept { return !notifiers[0] && !notifiers[1] && !notifiers[2]; } -inline short QSocketNotifierSetUNIX::events() const Q_DECL_NOTHROW +inline short QSocketNotifierSetUNIX::events() const noexcept { short result = 0; diff --git a/src/corelib/kernel/qfunctions_fake_env_p.h b/src/corelib/kernel/qfunctions_fake_env_p.h index 7010d2cf5d..68d17ed4a1 100644 --- a/src/corelib/kernel/qfunctions_fake_env_p.h +++ b/src/corelib/kernel/qfunctions_fake_env_p.h @@ -72,8 +72,8 @@ Q_DECLARE_TYPEINFO(Variable, Q_MOVABLE_TYPE); struct NameEquals { typedef bool result_type; const char *name; - explicit NameEquals(const char *name) Q_DECL_NOTHROW : name(name) {} - result_type operator()(const Variable &other) const Q_DECL_NOTHROW + explicit NameEquals(const char *name) noexcept : name(name) {} + result_type operator()(const Variable &other) const noexcept { return qstrcmp(other.name, name) == 0; } }; diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp index c15a9f7b0f..ace3eac2ac 100644 --- a/src/corelib/kernel/qmetaobject.cpp +++ b/src/corelib/kernel/qmetaobject.cpp @@ -335,7 +335,7 @@ const char *QMetaObject::className() const \since 5.7 */ -bool QMetaObject::inherits(const QMetaObject *metaObject) const Q_DECL_NOEXCEPT +bool QMetaObject::inherits(const QMetaObject *metaObject) const noexcept { const QMetaObject *m = this; do { diff --git a/src/corelib/kernel/qmetatype.cpp b/src/corelib/kernel/qmetatype.cpp index 45d0b5df6c..19bda7e8d6 100644 --- a/src/corelib/kernel/qmetatype.cpp +++ b/src/corelib/kernel/qmetatype.cpp @@ -915,7 +915,7 @@ template struct MetaTypeOffsetsblockSig; diff --git a/src/corelib/kernel/qobject.h b/src/corelib/kernel/qobject.h index 63c5a9ad73..6d7b9521c2 100644 --- a/src/corelib/kernel/qobject.h +++ b/src/corelib/kernel/qobject.h @@ -142,8 +142,8 @@ public: inline bool isWidgetType() const { return d_ptr->isWidget; } inline bool isWindowType() const { return d_ptr->isWindow; } - inline bool signalsBlocked() const Q_DECL_NOTHROW { return d_ptr->blockSig; } - bool blockSignals(bool b) Q_DECL_NOTHROW; + inline bool signalsBlocked() const noexcept { return d_ptr->blockSig; } + bool blockSignals(bool b) noexcept; QThread *thread() const; void moveToThread(QThread *thread); @@ -436,7 +436,7 @@ protected: QScopedPointer d_ptr; static const QMetaObject staticQtMetaObject; - friend inline const QMetaObject *qt_getQtMetaObject() Q_DECL_NOEXCEPT; + friend inline const QMetaObject *qt_getQtMetaObject() noexcept; friend struct QMetaObject; friend struct QMetaObjectPrivate; @@ -467,7 +467,7 @@ inline QMetaObject::Connection QObject::connect(const QObject *asender, const ch const char *amember, Qt::ConnectionType atype) const { return connect(asender, asignal, this, amember, atype); } -inline const QMetaObject *qt_getQtMetaObject() Q_DECL_NOEXCEPT +inline const QMetaObject *qt_getQtMetaObject() noexcept { return &QObject::staticQtMetaObject; } #ifndef QT_NO_USERDATA @@ -540,17 +540,17 @@ Q_CORE_EXPORT QDebug operator<<(QDebug, const QObject *); class QSignalBlocker { public: - inline explicit QSignalBlocker(QObject *o) Q_DECL_NOTHROW; - inline explicit QSignalBlocker(QObject &o) Q_DECL_NOTHROW; + inline explicit QSignalBlocker(QObject *o) noexcept; + inline explicit QSignalBlocker(QObject &o) noexcept; inline ~QSignalBlocker(); #ifdef Q_COMPILER_RVALUE_REFS - inline QSignalBlocker(QSignalBlocker &&other) Q_DECL_NOTHROW; - inline QSignalBlocker &operator=(QSignalBlocker &&other) Q_DECL_NOTHROW; + inline QSignalBlocker(QSignalBlocker &&other) noexcept; + inline QSignalBlocker &operator=(QSignalBlocker &&other) noexcept; #endif - inline void reblock() Q_DECL_NOTHROW; - inline void unblock() Q_DECL_NOTHROW; + inline void reblock() noexcept; + inline void unblock() noexcept; private: Q_DISABLE_COPY(QSignalBlocker) QObject * m_o; @@ -558,20 +558,20 @@ private: bool m_inhibited; }; -QSignalBlocker::QSignalBlocker(QObject *o) Q_DECL_NOTHROW +QSignalBlocker::QSignalBlocker(QObject *o) noexcept : m_o(o), m_blocked(o && o->blockSignals(true)), m_inhibited(false) {} -QSignalBlocker::QSignalBlocker(QObject &o) Q_DECL_NOTHROW +QSignalBlocker::QSignalBlocker(QObject &o) noexcept : m_o(&o), m_blocked(o.blockSignals(true)), m_inhibited(false) {} #ifdef Q_COMPILER_RVALUE_REFS -QSignalBlocker::QSignalBlocker(QSignalBlocker &&other) Q_DECL_NOTHROW +QSignalBlocker::QSignalBlocker(QSignalBlocker &&other) noexcept : m_o(other.m_o), m_blocked(other.m_blocked), m_inhibited(other.m_inhibited) @@ -579,7 +579,7 @@ QSignalBlocker::QSignalBlocker(QSignalBlocker &&other) Q_DECL_NOTHROW other.m_o = nullptr; } -QSignalBlocker &QSignalBlocker::operator=(QSignalBlocker &&other) Q_DECL_NOTHROW +QSignalBlocker &QSignalBlocker::operator=(QSignalBlocker &&other) noexcept { if (this != &other) { // if both *this and other block the same object's signals: @@ -602,13 +602,13 @@ QSignalBlocker::~QSignalBlocker() m_o->blockSignals(m_blocked); } -void QSignalBlocker::reblock() Q_DECL_NOTHROW +void QSignalBlocker::reblock() noexcept { if (m_o) m_o->blockSignals(true); m_inhibited = false; } -void QSignalBlocker::unblock() Q_DECL_NOTHROW +void QSignalBlocker::unblock() noexcept { if (m_o) m_o->blockSignals(m_blocked); m_inhibited = true; diff --git a/src/corelib/kernel/qobjectdefs.h b/src/corelib/kernel/qobjectdefs.h index d7ed2b0282..a437a994fd 100644 --- a/src/corelib/kernel/qobjectdefs.h +++ b/src/corelib/kernel/qobjectdefs.h @@ -119,13 +119,13 @@ class QString; #define Q_ENUMS(x) QT_ANNOTATE_CLASS(qt_enums, x) #define Q_FLAGS(x) QT_ANNOTATE_CLASS(qt_enums, x) #define Q_ENUM_IMPL(ENUM) \ - friend Q_DECL_CONSTEXPR const QMetaObject *qt_getEnumMetaObject(ENUM) Q_DECL_NOEXCEPT { return &staticMetaObject; } \ - friend Q_DECL_CONSTEXPR const char *qt_getEnumName(ENUM) Q_DECL_NOEXCEPT { return #ENUM; } + friend Q_DECL_CONSTEXPR const QMetaObject *qt_getEnumMetaObject(ENUM) noexcept { return &staticMetaObject; } \ + friend Q_DECL_CONSTEXPR const char *qt_getEnumName(ENUM) noexcept { return #ENUM; } #define Q_ENUM(x) Q_ENUMS(x) Q_ENUM_IMPL(x) #define Q_FLAG(x) Q_FLAGS(x) Q_ENUM_IMPL(x) #define Q_ENUM_NS_IMPL(ENUM) \ - inline Q_DECL_CONSTEXPR const QMetaObject *qt_getEnumMetaObject(ENUM) Q_DECL_NOEXCEPT { return &staticMetaObject; } \ - inline Q_DECL_CONSTEXPR const char *qt_getEnumName(ENUM) Q_DECL_NOEXCEPT { return #ENUM; } + inline Q_DECL_CONSTEXPR const QMetaObject *qt_getEnumMetaObject(ENUM) noexcept { return &staticMetaObject; } \ + inline Q_DECL_CONSTEXPR const char *qt_getEnumName(ENUM) noexcept { return #ENUM; } #define Q_ENUM_NS(x) Q_ENUMS(x) Q_ENUM_NS_IMPL(x) #define Q_FLAG_NS(x) Q_FLAGS(x) Q_ENUM_NS_IMPL(x) #define Q_SCRIPTABLE QT_ANNOTATE_FUNCTION(qt_scriptable) @@ -340,7 +340,7 @@ struct Q_CORE_EXPORT QMetaObject const char *className() const; const QMetaObject *superClass() const; - bool inherits(const QMetaObject *metaObject) const Q_DECL_NOEXCEPT; + bool inherits(const QMetaObject *metaObject) const noexcept; QObject *cast(QObject *obj) const; const QObject *cast(const QObject *obj) const; @@ -605,8 +605,8 @@ public: operator RestrictedBool() const { return d_ptr && isConnected_helper() ? &Connection::d_ptr : nullptr; } #endif - Connection(Connection &&o) Q_DECL_NOTHROW : d_ptr(o.d_ptr) { o.d_ptr = nullptr; } - Connection &operator=(Connection &&other) Q_DECL_NOTHROW + Connection(Connection &&o) noexcept : d_ptr(o.d_ptr) { o.d_ptr = nullptr; } + Connection &operator=(Connection &&other) noexcept { qSwap(d_ptr, other.d_ptr); return *this; } }; diff --git a/src/corelib/kernel/qobjectdefs_impl.h b/src/corelib/kernel/qobjectdefs_impl.h index aa6bd84e95..31ecc8b20d 100644 --- a/src/corelib/kernel/qobjectdefs_impl.h +++ b/src/corelib/kernel/qobjectdefs_impl.h @@ -386,8 +386,8 @@ namespace QtPrivate { public: explicit QSlotObjectBase(ImplFn fn) : m_ref(1), m_impl(fn) {} - inline int ref() Q_DECL_NOTHROW { return m_ref.ref(); } - inline void destroyIfLastRef() Q_DECL_NOTHROW + inline int ref() noexcept { return m_ref.ref(); } + inline void destroyIfLastRef() noexcept { if (!m_ref.deref()) m_impl(Destroy, this, nullptr, nullptr, nullptr); } inline bool compare(void **a) { bool ret = false; m_impl(Compare, this, nullptr, a, &ret); return ret; } diff --git a/src/corelib/kernel/qtimer.h b/src/corelib/kernel/qtimer.h index 66f317c567..ae5552f1c9 100644 --- a/src/corelib/kernel/qtimer.h +++ b/src/corelib/kernel/qtimer.h @@ -218,7 +218,7 @@ private: inline int startTimer(int){ return -1;} inline void killTimer(int){} - static Q_DECL_CONSTEXPR Qt::TimerType defaultTypeFor(int msecs) Q_DECL_NOTHROW + static Q_DECL_CONSTEXPR Qt::TimerType defaultTypeFor(int msecs) noexcept { return msecs >= 2000 ? Qt::CoarseTimer : Qt::PreciseTimer; } static void singleShotImpl(int msec, Qt::TimerType timerType, const QObject *receiver, QtPrivate::QSlotObjectBase *slotObj); diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h index 90f5f5fc34..6b35bfa9e9 100644 --- a/src/corelib/kernel/qvariant.h +++ b/src/corelib/kernel/qvariant.h @@ -201,7 +201,7 @@ class Q_CORE_EXPORT QVariant LastType = 0xffffffff // need this so that gcc >= 3.4 allocates 32 bits for Type }; - QVariant() Q_DECL_NOTHROW : d() {} + QVariant() noexcept : d() {} ~QVariant(); QVariant(Type type); QVariant(int typeId, const void *copy); @@ -268,13 +268,13 @@ class Q_CORE_EXPORT QVariant QVariant& operator=(const QVariant &other); #ifdef Q_COMPILER_RVALUE_REFS - inline QVariant(QVariant &&other) Q_DECL_NOTHROW : d(other.d) + inline QVariant(QVariant &&other) noexcept : d(other.d) { other.d = Private(); } - inline QVariant &operator=(QVariant &&other) Q_DECL_NOTHROW + inline QVariant &operator=(QVariant &&other) noexcept { qSwap(d, other.d); return *this; } #endif - inline void swap(QVariant &other) Q_DECL_NOTHROW { qSwap(d, other.d); } + inline void swap(QVariant &other) noexcept { qSwap(d, other.d); } Type type() const; int userType() const; @@ -387,15 +387,15 @@ class Q_CORE_EXPORT QVariant }; struct Private { - inline Private() Q_DECL_NOTHROW : type(Invalid), is_shared(false), is_null(true) + inline Private() noexcept : type(Invalid), is_shared(false), is_null(true) { data.ptr = nullptr; } // Internal constructor for initialized variants. - explicit inline Private(uint variantType) Q_DECL_NOTHROW + explicit inline Private(uint variantType) noexcept : type(variantType), is_shared(false), is_null(false) {} - inline Private(const Private &other) Q_DECL_NOTHROW + inline Private(const Private &other) noexcept : data(other.data), type(other.type), is_shared(other.is_shared), is_null(other.is_null) {} -- cgit v1.2.3 From a334156e81ab2491b3f65ee3c7a8269912c26a0c Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Tue, 2 Apr 2019 15:44:01 +0200 Subject: Add QMetaProperty::relativePropertyIndex() Add a "sibling" function for QMetaProperty::propertyIndex() for the relative index. That way in QtQml we can avoid using propertyIndex() - metaObject.propertyOffset() where the latter traverses the parent chain. Change-Id: I113a956801b0e8d56a30a847b5b919da703824e2 Reviewed-by: Lars Knoll Reviewed-by: Thiago Macieira --- src/corelib/kernel/qmetaobject.cpp | 12 ++++++++++++ src/corelib/kernel/qmetaobject.h | 1 + 2 files changed, 13 insertions(+) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp index c15a9f7b0f..8309bd22c2 100644 --- a/src/corelib/kernel/qmetaobject.cpp +++ b/src/corelib/kernel/qmetaobject.cpp @@ -3016,6 +3016,18 @@ int QMetaProperty::propertyIndex() const return idx + mobj->propertyOffset(); } +/*! + \since 5.14 + + Returns this property's index relative within the enclosing meta object. +*/ +int QMetaProperty::relativePropertyIndex() const +{ + if (!mobj) + return -1; + return idx; +} + /*! Returns \c true if the property's type is an enumeration value that is used as a flag; otherwise returns \c false. diff --git a/src/corelib/kernel/qmetaobject.h b/src/corelib/kernel/qmetaobject.h index 51ace3d5f7..6c5f78d208 100644 --- a/src/corelib/kernel/qmetaobject.h +++ b/src/corelib/kernel/qmetaobject.h @@ -253,6 +253,7 @@ public: QVariant::Type type() const; int userType() const; int propertyIndex() const; + int relativePropertyIndex() const; bool isReadable() const; bool isWritable() const; -- cgit v1.2.3 From 8d7c97d428cdf89c3419a4e13b62a9849feefce9 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Thu, 4 Apr 2019 16:46:41 +0200 Subject: Remove remaining Q_DECL_NOEXCEPT/Q_DECL_NOTHROW usage Change-Id: I91ac9e714a465cab226b211812aa46e8fe5ff2ab Reviewed-by: Thiago Macieira --- src/corelib/kernel/qcore_mac_p.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qcore_mac_p.h b/src/corelib/kernel/qcore_mac_p.h index f96e7358a2..920105ee9e 100644 --- a/src/corelib/kernel/qcore_mac_p.h +++ b/src/corelib/kernel/qcore_mac_p.h @@ -90,7 +90,7 @@ public: QAppleRefCounted(const QAppleRefCounted &other) : value(other.value) { if (value) RetainFunction(value); } ~QAppleRefCounted() { if (value) ReleaseFunction(value); } operator T() const { return value; } - void swap(QAppleRefCounted &other) Q_DECL_NOEXCEPT_EXPR(noexcept(qSwap(value, other.value))) + void swap(QAppleRefCounted &other) noexcept(noexcept(qSwap(value, other.value))) { qSwap(value, other.value); } QAppleRefCounted &operator=(const QAppleRefCounted &other) { QAppleRefCounted copy(other); swap(copy); return *this; } -- cgit v1.2.3 From 127518deda5a05fda2ce24be98aaaeb7b975f163 Mon Sep 17 00:00:00 2001 From: Milian Wolff Date: Wed, 27 Mar 2019 13:56:57 +0100 Subject: Introduce Q_TRACE_SCOPE to simplify tracing of a function entry/exit Additionally, we also add a Q_TRACE_EXIT which runs a trace point when the scope is exited, leveraging qScopeGuard behind the scenes. Q_TRACE_SCOPE uses Q_TRACE_EXIT internally - the difference is that the _SCOPE version enforces the naming scheme of _entry / _exit for the tracepoints, whereas Q_TRACE_EXIT can be used generically. Change-Id: I4a2f5ea09f451fcf664d07fd493b679f7527ac06 Reviewed-by: Thiago Macieira --- src/corelib/kernel/qcoreapplication.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index 6d7985c91b..d173ec029b 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -778,7 +778,7 @@ QCoreApplication::QCoreApplication(int &argc, char **argv void QCoreApplicationPrivate::init() { - Q_TRACE(QCoreApplicationPrivate_init_entry); + Q_TRACE_SCOPE(QCoreApplicationPrivate_init); #if defined(Q_OS_MACOS) QMacAutoReleasePool pool; @@ -883,8 +883,6 @@ void QCoreApplicationPrivate::init() #ifndef QT_NO_QOBJECT is_app_running = true; // No longer starting up. #endif - - Q_TRACE(QCoreApplicationPrivate_init_exit); } /*! -- cgit v1.2.3 From f4c41b9797f08f173049502fa7bd465cf5bde938 Mon Sep 17 00:00:00 2001 From: Milian Wolff Date: Wed, 27 Mar 2019 14:00:21 +0100 Subject: Add missing _exit tracepoints for event handling This allows tools that look for matching `foo_entry/exit` pairs in the trace data to work properly. An unmatched `_entry` would otherwise confuse them, making them think that the call stack is continuously increasing. Change-Id: Idff7f587ea25c46ec86ad623cc82d503db34a194 Reviewed-by: Christoph Sterz Reviewed-by: Thiago Macieira --- src/corelib/kernel/qcoreapplication.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index d173ec029b..596941b5a9 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -1197,7 +1197,7 @@ bool QCoreApplicationPrivate::notify_helper(QObject *receiver, QEvent * event) { // Note: when adjusting the tracepoints in here // consider adjusting QApplicationPrivate::notify_helper too. - Q_TRACE(QCoreApplication_notify_entry, receiver, event, event->type()); + Q_TRACE_SCOPE(QCoreApplication_notify, receiver, event, event->type()); // send to all application event filters (only does anything in the main thread) if (QCoreApplication::self @@ -1489,7 +1489,7 @@ bool QCoreApplication::sendSpontaneousEvent(QObject *receiver, QEvent *event) */ void QCoreApplication::postEvent(QObject *receiver, QEvent *event, int priority) { - Q_TRACE(QCoreApplication_postEvent_entry, receiver, event, event->type()); + Q_TRACE_SCOPE(QCoreApplication_postEvent, receiver, event, event->type()); if (receiver == 0) { qWarning("QCoreApplication::postEvent: Unexpected null receiver"); -- cgit v1.2.3 From 4628e5cded8b1b4f064b75f23436bc6fc66ce043 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Tue, 2 Apr 2019 11:56:33 +0200 Subject: Remove handling of missing very old compiler feature check Removes handling of missing Q_COMPILER_NULLPTR, Q_COMPILER_AUTODECL, Q_COMPILER_LAMBDA, Q_COMPILER_VARIADIC_MACROS and Q_COMPILER_AUTO_FUNCTION. We haven't supported any compilers without these for a long time. Change-Id: I3df88206516a25763e2c28b083733780f35a8764 Reviewed-by: Thiago Macieira --- src/corelib/kernel/qobjectdefs.h | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qobjectdefs.h b/src/corelib/kernel/qobjectdefs.h index a437a994fd..28674193c3 100644 --- a/src/corelib/kernel/qobjectdefs.h +++ b/src/corelib/kernel/qobjectdefs.h @@ -64,11 +64,7 @@ class QString; // The following macros can be defined by tools that understand Qt // to have the information from the macro. #ifndef QT_ANNOTATE_CLASS -# ifndef Q_COMPILER_VARIADIC_MACROS -# define QT_ANNOTATE_CLASS(type, x) -# else -# define QT_ANNOTATE_CLASS(type, ...) -# endif +# define QT_ANNOTATE_CLASS(type, ...) #endif #ifndef QT_ANNOTATE_CLASS2 # define QT_ANNOTATE_CLASS2(type, a1, a2) @@ -105,11 +101,7 @@ class QString; #endif #define Q_PLUGIN_METADATA(x) QT_ANNOTATE_CLASS(qt_plugin_metadata, x) #define Q_INTERFACES(x) QT_ANNOTATE_CLASS(qt_interfaces, x) -#ifdef Q_COMPILER_VARIADIC_MACROS -# define Q_PROPERTY(...) QT_ANNOTATE_CLASS(qt_property, __VA_ARGS__) -#else -# define Q_PROPERTY(text) QT_ANNOTATE_CLASS(qt_property, text) -#endif +#define Q_PROPERTY(...) QT_ANNOTATE_CLASS(qt_property, __VA_ARGS__) #define Q_PRIVATE_PROPERTY(d, text) QT_ANNOTATE_CLASS2(qt_private_property, d, text) #ifndef Q_REVISION # define Q_REVISION(v) -- cgit v1.2.3 From 58b4e0736919e0504f5ca5307ad7aefa894a6f38 Mon Sep 17 00:00:00 2001 From: Milian Wolff Date: Thu, 11 Jan 2018 17:46:24 +0100 Subject: Optimize QTimer::singleShot(0, ...) when taking PMF or Functor callable QTimer::singleShot is optimized for zero timeouts when using the API taking a string method name. This optimization was not used for the API taking a PMF or functor. This patch adds it, making the various API calls behave similarly from a performance point of view. The approach taken here requires a QObject context object. If none is available, e.g. a nullptr was passed explicitly, or the QTimer::singleShot(O, Functor) API was used, the optimization could not easily be applied. This is not only bad from a performance POV, but also poses as a potential source for heisenbugs: Using the different API versions of QTimer::singleShot would use different code paths internally, which then would not ensure the expected slot call order. This problem actually existed already when mixing the string-based slot syntax with PMF/functors in the QTimer::singleShot API. This patch overcomes this hurdle and fixes all of the above: When we encounter a 0ms single shot timer, and no QObject context object is available, we fall back to the main thread, or create a temporary QObject for any other thread. The updated and extended benchmark shows that this is still a significant performance improvement over using a timer: ********* Start testing of qtimer_vs_qmetaobject ********* Config: Using QtTest library 5.14.0, Qt 5.14.0 (x86_64-little_endian-lp64 shared (dynamic) release build; by GCC 8.2.1 20181127) PASS : qtimer_vs_qmetaobject::initTestCase() PASS : qtimer_vs_qmetaobject::bench(singleShot_slot) RESULT : qtimer_vs_qmetaobject::bench():"singleShot_slot": 7.48 msecs per iteration (total: 748, iterations: 100) PASS : qtimer_vs_qmetaobject::bench(singleShot_pmf) RESULT : qtimer_vs_qmetaobject::bench():"singleShot_pmf": 7.20 msecs per iteration (total: 720, iterations: 100) PASS : qtimer_vs_qmetaobject::bench(singleShot_functor) RESULT : qtimer_vs_qmetaobject::bench():"singleShot_functor": 6.79 msecs per iteration (total: 679, iterations: 100) PASS : qtimer_vs_qmetaobject::bench(singleShot_functor_noctx) RESULT : qtimer_vs_qmetaobject::bench():"singleShot_functor_noctx": 6.92 msecs per iteration (total: 693, iterations: 100) PASS : qtimer_vs_qmetaobject::bench(invokeMethod_string) RESULT : qtimer_vs_qmetaobject::bench():"invokeMethod_string": 7.34 msecs per iteration (total: 735, iterations: 100) PASS : qtimer_vs_qmetaobject::bench(invokeMethod_pmf) RESULT : qtimer_vs_qmetaobject::bench():"invokeMethod_pmf": 6.90 msecs per iteration (total: 690, iterations: 100) PASS : qtimer_vs_qmetaobject::bench(invokeMethod_functor) RESULT : qtimer_vs_qmetaobject::bench():"invokeMethod_functor": 6.62 msecs per iteration (total: 662, iterations: 100) PASS : qtimer_vs_qmetaobject::benchBackgroundThread(singleShot_slot) RESULT : qtimer_vs_qmetaobject::benchBackgroundThread():"singleShot_slot": 7.45 msecs per iteration (total: 745, iterations: 100) PASS : qtimer_vs_qmetaobject::benchBackgroundThread(singleShot_pmf) RESULT : qtimer_vs_qmetaobject::benchBackgroundThread():"singleShot_pmf": 7.46 msecs per iteration (total: 747, iterations: 100) PASS : qtimer_vs_qmetaobject::benchBackgroundThread(singleShot_functor) RESULT : qtimer_vs_qmetaobject::benchBackgroundThread():"singleShot_functor": 6.70 msecs per iteration (total: 671, iterations: 100) PASS : qtimer_vs_qmetaobject::benchBackgroundThread(singleShot_functor_noctx) RESULT : qtimer_vs_qmetaobject::benchBackgroundThread():"singleShot_functor_noctx": 13.75 msecs per iteration (total: 1,376, iterations: 100) PASS : qtimer_vs_qmetaobject::benchBackgroundThread(invokeMethod_string) RESULT : qtimer_vs_qmetaobject::benchBackgroundThread():"invokeMethod_string": 7.05 msecs per iteration (total: 706, iterations: 100) PASS : qtimer_vs_qmetaobject::benchBackgroundThread(invokeMethod_pmf) RESULT : qtimer_vs_qmetaobject::benchBackgroundThread():"invokeMethod_pmf": 6.70 msecs per iteration (total: 670, iterations: 100) PASS : qtimer_vs_qmetaobject::benchBackgroundThread(invokeMethod_functor) RESULT : qtimer_vs_qmetaobject::benchBackgroundThread():"invokeMethod_functor": 6.58 msecs per iteration (total: 658, iterations: 100) PASS : qtimer_vs_qmetaobject::cleanupTestCase() Totals: 16 passed, 0 failed, 0 skipped, 0 blacklisted, 20977ms ********* Finished testing of qtimer_vs_qmetaobject ********* Without the change to qtimer.cpp, the results are: ********* Start testing of qtimer_vs_qmetaobject ********* Config: Using QtTest library 5.14.0, Qt 5.14.0 (x86_64-little_endian-lp64 shared (dynamic) release build; by GCC 8.2.1 20181127) PASS : qtimer_vs_qmetaobject::initTestCase() PASS : qtimer_vs_qmetaobject::bench(singleShot_slot) RESULT : qtimer_vs_qmetaobject::bench():"singleShot_slot": 7.45 msecs per iteration (total: 745, iterations: 100) PASS : qtimer_vs_qmetaobject::bench(singleShot_pmf) RESULT : qtimer_vs_qmetaobject::bench():"singleShot_pmf": 112.84 msecs per iteration (total: 11,285, iterations: 100) PASS : qtimer_vs_qmetaobject::bench(singleShot_functor) RESULT : qtimer_vs_qmetaobject::bench():"singleShot_functor": 115.62 msecs per iteration (total: 11,563, iterations: 100) PASS : qtimer_vs_qmetaobject::bench(singleShot_functor_noctx) RESULT : qtimer_vs_qmetaobject::bench():"singleShot_functor_noctx": 110.81 msecs per iteration (total: 11,082, iterations: 100) PASS : qtimer_vs_qmetaobject::bench(invokeMethod_string) RESULT : qtimer_vs_qmetaobject::bench():"invokeMethod_string": 7.04 msecs per iteration (total: 704, iterations: 100) PASS : qtimer_vs_qmetaobject::bench(invokeMethod_pmf) RESULT : qtimer_vs_qmetaobject::bench():"invokeMethod_pmf": 6.62 msecs per iteration (total: 662, iterations: 100) PASS : qtimer_vs_qmetaobject::bench(invokeMethod_functor) RESULT : qtimer_vs_qmetaobject::bench():"invokeMethod_functor": 6.62 msecs per iteration (total: 662, iterations: 100) PASS : qtimer_vs_qmetaobject::benchBackgroundThread(singleShot_slot) RESULT : qtimer_vs_qmetaobject::benchBackgroundThread():"singleShot_slot": 7.45 msecs per iteration (total: 746, iterations: 100) PASS : qtimer_vs_qmetaobject::benchBackgroundThread(singleShot_pmf) RESULT : qtimer_vs_qmetaobject::benchBackgroundThread():"singleShot_pmf": 118.42 msecs per iteration (total: 11,842, iterations: 100) PASS : qtimer_vs_qmetaobject::benchBackgroundThread(singleShot_functor) RESULT : qtimer_vs_qmetaobject::benchBackgroundThread():"singleShot_functor": 119.35 msecs per iteration (total: 11,936, iterations: 100) PASS : qtimer_vs_qmetaobject::benchBackgroundThread(singleShot_functor_noctx) RESULT : qtimer_vs_qmetaobject::benchBackgroundThread():"singleShot_functor_noctx": 130.96 msecs per iteration (total: 13,096, iterations: 100) PASS : qtimer_vs_qmetaobject::benchBackgroundThread(invokeMethod_string) RESULT : qtimer_vs_qmetaobject::benchBackgroundThread():"invokeMethod_string": 8.08 msecs per iteration (total: 808, iterations: 100) PASS : qtimer_vs_qmetaobject::benchBackgroundThread(invokeMethod_pmf) RESULT : qtimer_vs_qmetaobject::benchBackgroundThread():"invokeMethod_pmf": 6.79 msecs per iteration (total: 680, iterations: 100) PASS : qtimer_vs_qmetaobject::benchBackgroundThread(invokeMethod_functor) RESULT : qtimer_vs_qmetaobject::benchBackgroundThread():"invokeMethod_functor": 7.49 msecs per iteration (total: 749, iterations: 100) PASS : qtimer_vs_qmetaobject::cleanupTestCase() Totals: 16 passed, 0 failed, 0 skipped, 0 blacklisted, 153995ms ********* Finished testing of qtimer_vs_qmetaobject ********* Additionally, this patch adds a unit test to verify that the slot call order for 0ms single shot timers is followed while mixing the various API versions. It fails without this patch but passes now. Finally, another test is added to verify that using QTimer::singleShot before a QCoreApplication was constructed is still working properly. Change-Id: I0d6211554b6198cb3e527be9ec3adc572b1b54ee Reviewed-by: Thiago Macieira --- src/corelib/kernel/qobjectdefs.h | 1 + src/corelib/kernel/qtimer.cpp | 29 +++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qobjectdefs.h b/src/corelib/kernel/qobjectdefs.h index 28674193c3..418b8cf1d2 100644 --- a/src/corelib/kernel/qobjectdefs.h +++ b/src/corelib/kernel/qobjectdefs.h @@ -576,6 +576,7 @@ struct Q_CORE_EXPORT QMetaObject private: static bool invokeMethodImpl(QObject *object, QtPrivate::QSlotObjectBase *slot, Qt::ConnectionType type, void *ret); + friend class QTimer; }; class Q_CORE_EXPORT QMetaObject::Connection { diff --git a/src/corelib/kernel/qtimer.cpp b/src/corelib/kernel/qtimer.cpp index 13f027074a..188d529f04 100644 --- a/src/corelib/kernel/qtimer.cpp +++ b/src/corelib/kernel/qtimer.cpp @@ -42,6 +42,8 @@ #include "qabstracteventdispatcher.h" #include "qcoreapplication.h" #include "qobject_p.h" +#include "qthread.h" +#include "qcoreapplication_p.h" QT_BEGIN_NAMESPACE @@ -343,6 +345,33 @@ void QTimer::singleShotImpl(int msec, Qt::TimerType timerType, const QObject *receiver, QtPrivate::QSlotObjectBase *slotObj) { + if (msec == 0) { + bool deleteReceiver = false; + // Optimize: set a receiver context when none is given, such that we can use + // QMetaObject::invokeMethod which is more efficient than going through a timer. + // We need a QObject living in the current thread. But the QThread itself lives + // in a different thread - with the exception of the main QThread which lives in + // itself. And QThread::currentThread() is among the few QObjects we know that will + // most certainly be there. Note that one can actually call singleShot before the + // QApplication is created! + if (!receiver && QThread::currentThread() == QCoreApplicationPrivate::mainThread()) { + // reuse main thread as context object + receiver = QThread::currentThread(); + } else if (!receiver) { + // Create a receiver context object on-demand. According to the benchmarks, + // this is still more efficient than going through a timer. + receiver = new QObject; + deleteReceiver = true; + } + + QMetaObject::invokeMethodImpl(const_cast(receiver), slotObj, + Qt::QueuedConnection, nullptr); + + if (deleteReceiver) + const_cast(receiver)->deleteLater(); + return; + } + new QSingleShotTimer(msec, timerType, receiver, slotObj); } -- cgit v1.2.3 From 28c9e0e606d104e526bb1c8e6e8bcda3ee0aa496 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Tue, 2 Apr 2019 16:23:48 +0200 Subject: Remove handling of missing Q_COMPILER_RVALUE_REFS Change-Id: I7bc6c455fbae4cdad584c76773299a6d8cd40c82 Reviewed-by: Thiago Macieira --- src/corelib/kernel/qobject.h | 4 ---- src/corelib/kernel/qppsattribute.cpp | 2 -- src/corelib/kernel/qppsattribute_p.h | 2 -- src/corelib/kernel/qvariant.h | 2 -- 4 files changed, 10 deletions(-) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qobject.h b/src/corelib/kernel/qobject.h index 6d7b9521c2..1d83731441 100644 --- a/src/corelib/kernel/qobject.h +++ b/src/corelib/kernel/qobject.h @@ -544,10 +544,8 @@ public: inline explicit QSignalBlocker(QObject &o) noexcept; inline ~QSignalBlocker(); -#ifdef Q_COMPILER_RVALUE_REFS inline QSignalBlocker(QSignalBlocker &&other) noexcept; inline QSignalBlocker &operator=(QSignalBlocker &&other) noexcept; -#endif inline void reblock() noexcept; inline void unblock() noexcept; @@ -570,7 +568,6 @@ QSignalBlocker::QSignalBlocker(QObject &o) noexcept m_inhibited(false) {} -#ifdef Q_COMPILER_RVALUE_REFS QSignalBlocker::QSignalBlocker(QSignalBlocker &&other) noexcept : m_o(other.m_o), m_blocked(other.m_blocked), @@ -594,7 +591,6 @@ QSignalBlocker &QSignalBlocker::operator=(QSignalBlocker &&other) noexcept } return *this; } -#endif QSignalBlocker::~QSignalBlocker() { diff --git a/src/corelib/kernel/qppsattribute.cpp b/src/corelib/kernel/qppsattribute.cpp index 6be462edb5..166d590872 100644 --- a/src/corelib/kernel/qppsattribute.cpp +++ b/src/corelib/kernel/qppsattribute.cpp @@ -145,7 +145,6 @@ QPpsAttribute &QPpsAttribute::operator=(const QPpsAttribute &other) return *this; } -#ifdef Q_COMPILER_RVALUE_REFS QPpsAttribute::QPpsAttribute(QPpsAttribute &&other) : d(other.d) { other.d->type = QPpsAttribute::None; @@ -156,7 +155,6 @@ QPpsAttribute &QPpsAttribute::operator=(QPpsAttribute &&other) qSwap(d, other.d); return *this; } -#endif bool QPpsAttribute::operator==(const QPpsAttribute &other) const { diff --git a/src/corelib/kernel/qppsattribute_p.h b/src/corelib/kernel/qppsattribute_p.h index b59dcd5851..d6611cb675 100644 --- a/src/corelib/kernel/qppsattribute_p.h +++ b/src/corelib/kernel/qppsattribute_p.h @@ -96,10 +96,8 @@ public: bool operator==(const QPpsAttribute &other) const; bool operator!=(const QPpsAttribute &other) const; -#ifdef Q_COMPILER_RVALUE_REFS QPpsAttribute(QPpsAttribute &&other); QPpsAttribute &operator=(QPpsAttribute &&other); -#endif bool isValid() const; Type type() const; diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h index 6b35bfa9e9..2247c7adc8 100644 --- a/src/corelib/kernel/qvariant.h +++ b/src/corelib/kernel/qvariant.h @@ -267,12 +267,10 @@ class Q_CORE_EXPORT QVariant #endif QVariant& operator=(const QVariant &other); -#ifdef Q_COMPILER_RVALUE_REFS inline QVariant(QVariant &&other) noexcept : d(other.d) { other.d = Private(); } inline QVariant &operator=(QVariant &&other) noexcept { qSwap(d, other.d); return *this; } -#endif inline void swap(QVariant &other) noexcept { qSwap(d, other.d); } -- cgit v1.2.3 From 0adb78a8479417c902cde9ba050edc2f828ecd83 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Fri, 5 Apr 2019 11:13:30 +0200 Subject: QElapsedTimer: Remove unused static nanosecondsToTicks method Fixes clang-cl warning qelapsedtimer_win.cpp(80,22): warning: unused function 'nanosecondsToTicks' [-Wunused-function] Change-Id: I1ff334049fcf4b265fe97235b7daf06969331313 Reviewed-by: Thiago Macieira --- src/corelib/kernel/qelapsedtimer_win.cpp | 9 --------- 1 file changed, 9 deletions(-) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qelapsedtimer_win.cpp b/src/corelib/kernel/qelapsedtimer_win.cpp index a63290d2f8..3beb158b8a 100644 --- a/src/corelib/kernel/qelapsedtimer_win.cpp +++ b/src/corelib/kernel/qelapsedtimer_win.cpp @@ -77,15 +77,6 @@ static inline qint64 ticksToNanoseconds(qint64 ticks) return ticks * 1000000; } -static inline qint64 nanosecondsToTicks(qint64 nsec) -{ - if (counterFrequency > 0) { - // QueryPerformanceCounter uses an arbitrary frequency - return double(nsec) * counterFrequency / 1000000000.; - } - // GetTickCount(64) uses milliseconds - return nsec / 1000000; -} static quint64 getTickCount() { -- cgit v1.2.3 From 6d4a456a28282973d2501e0b16f09cafb316bb0a Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Fri, 5 Apr 2019 11:25:13 +0200 Subject: Fix off-by-one error in QTranslatorPrivate::do_load() The central loop starts by reading five bytes; but the loop condition only checked that four were available. Change-Id: I244cecacabeffbac10ad94081f32847f912d95d9 Reviewed-by: Kai Koehne Reviewed-by: Thiago Macieira Reviewed-by: hjk --- src/corelib/kernel/qtranslator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qtranslator.cpp b/src/corelib/kernel/qtranslator.cpp index 929554f6bc..63aeed07c3 100644 --- a/src/corelib/kernel/qtranslator.cpp +++ b/src/corelib/kernel/qtranslator.cpp @@ -824,7 +824,7 @@ bool QTranslatorPrivate::do_load(const uchar *data, int len, const QString &dire data += MagicLength; QStringList dependencies; - while (data < end - 4) { + while (data < end - 5) { quint8 tag = read8(data++); quint32 blockLen = read32(data); data += 4; -- cgit v1.2.3 From 95f787bfdc890c259e8b347bdad9123d534efe0f Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Tue, 9 Apr 2019 13:33:15 +0200 Subject: Replace Q_DECL_NOTHROW with noexcept the remaining places The first replacement had missed objective-C++ code some places ourside the src dir. In C-files Q_DECL_NOTHROW is replaced with Q_DECL_NOEXCEPT as we still need to turn it off when compiled in C mode, but can get rid of the old NOTHROW moniker. Change-Id: I6370f57066679c5120d0265a69e7e378e09d4759 Reviewed-by: Thiago Macieira --- src/corelib/kernel/qcore_foundation.mm | 18 +++++++++--------- src/corelib/kernel/qcore_mac_objc.mm | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qcore_foundation.mm b/src/corelib/kernel/qcore_foundation.mm index 56eabc4b8c..623d462749 100644 --- a/src/corelib/kernel/qcore_foundation.mm +++ b/src/corelib/kernel/qcore_foundation.mm @@ -501,7 +501,7 @@ NSTimeZone *QTimeZone::toNSTimeZone() const \sa QRectF::fromCGRect() */ -CGRect QRect::toCGRect() const Q_DECL_NOTHROW +CGRect QRect::toCGRect() const noexcept { return CGRectMake(x(), y(), width(), height()); } @@ -513,7 +513,7 @@ CGRect QRect::toCGRect() const Q_DECL_NOTHROW \sa fromCGRect() */ -CGRect QRectF::toCGRect() const Q_DECL_NOTHROW +CGRect QRectF::toCGRect() const noexcept { return CGRectMake(x(), y(), width(), height()); } @@ -525,7 +525,7 @@ CGRect QRectF::toCGRect() const Q_DECL_NOTHROW \sa toCGRect() */ -QRectF QRectF::fromCGRect(CGRect rect) Q_DECL_NOTHROW +QRectF QRectF::fromCGRect(CGRect rect) noexcept { return QRectF(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height); } @@ -539,7 +539,7 @@ QRectF QRectF::fromCGRect(CGRect rect) Q_DECL_NOTHROW \sa QPointF::fromCGPoint() */ -CGPoint QPoint::toCGPoint() const Q_DECL_NOTHROW +CGPoint QPoint::toCGPoint() const noexcept { return CGPointMake(x(), y()); } @@ -551,7 +551,7 @@ CGPoint QPoint::toCGPoint() const Q_DECL_NOTHROW \sa fromCGPoint() */ -CGPoint QPointF::toCGPoint() const Q_DECL_NOTHROW +CGPoint QPointF::toCGPoint() const noexcept { return CGPointMake(x(), y()); } @@ -563,7 +563,7 @@ CGPoint QPointF::toCGPoint() const Q_DECL_NOTHROW \sa toCGPoint() */ -QPointF QPointF::fromCGPoint(CGPoint point) Q_DECL_NOTHROW +QPointF QPointF::fromCGPoint(CGPoint point) noexcept { return QPointF(point.x, point.y); } @@ -577,7 +577,7 @@ QPointF QPointF::fromCGPoint(CGPoint point) Q_DECL_NOTHROW \sa QSizeF::fromCGSize() */ -CGSize QSize::toCGSize() const Q_DECL_NOTHROW +CGSize QSize::toCGSize() const noexcept { return CGSizeMake(width(), height()); } @@ -589,7 +589,7 @@ CGSize QSize::toCGSize() const Q_DECL_NOTHROW \sa fromCGSize() */ -CGSize QSizeF::toCGSize() const Q_DECL_NOTHROW +CGSize QSizeF::toCGSize() const noexcept { return CGSizeMake(width(), height()); } @@ -601,7 +601,7 @@ CGSize QSizeF::toCGSize() const Q_DECL_NOTHROW \sa toCGSize() */ -QSizeF QSizeF::fromCGSize(CGSize size) Q_DECL_NOTHROW +QSizeF QSizeF::fromCGSize(CGSize size) noexcept { return QSizeF(size.width, size.height); } diff --git a/src/corelib/kernel/qcore_mac_objc.mm b/src/corelib/kernel/qcore_mac_objc.mm index 6687eb88a5..6b51eb65d9 100644 --- a/src/corelib/kernel/qcore_mac_objc.mm +++ b/src/corelib/kernel/qcore_mac_objc.mm @@ -371,7 +371,7 @@ bool operator<(const KeyPair &entry, const Qt::Key &key) struct qtKey2CocoaKeySortLessThan { typedef bool result_type; - Q_DECL_CONSTEXPR result_type operator()(const KeyPair &entry1, const KeyPair &entry2) const Q_DECL_NOTHROW + Q_DECL_CONSTEXPR result_type operator()(const KeyPair &entry1, const KeyPair &entry2) const noexcept { return entry1.qtKey < entry2.qtKey; } -- cgit v1.2.3 From 5f2afe18ccb0bbe258d4016ef65218cd3656cac2 Mon Sep 17 00:00:00 2001 From: Milian Wolff Date: Tue, 9 Apr 2019 13:38:06 +0200 Subject: Fix QMetaObject::newInstance on non-QObject meta object QMetaObject::newInstance returns a QObject, thus it's not possible to create a new instance of a Q_GADGET using this function. Previously, we returned a non-null QObject pointer for such scenarios, which then leads to crashes when one tries to use it. Now, we check whether the meta object inherits QObject's meta object, and error out early otherwise. Change-Id: I7b1fb6c8d48b3e98161894be2f281a491963345e Reviewed-by: Thiago Macieira --- src/corelib/kernel/qmetaobject.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp index b8b5c0de46..666bb6eace 100644 --- a/src/corelib/kernel/qmetaobject.cpp +++ b/src/corelib/kernel/qmetaobject.cpp @@ -235,6 +235,12 @@ QObject *QMetaObject::newInstance(QGenericArgument val0, QGenericArgument val8, QGenericArgument val9) const { + if (!inherits(&QObject::staticMetaObject)) + { + qWarning("QMetaObject::newInstance: type %s does not inherit QObject", className()); + return nullptr; + } + QByteArray constructorName = className(); { int idx = constructorName.lastIndexOf(':'); -- cgit v1.2.3