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 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