diff options
Diffstat (limited to 'src/corelib/kernel')
46 files changed, 994 insertions, 1390 deletions
diff --git a/src/corelib/kernel/kernel.pri b/src/corelib/kernel/kernel.pri index 3f7bf3cd47..789bcb7927 100644 --- a/src/corelib/kernel/kernel.pri +++ b/src/corelib/kernel/kernel.pri @@ -7,7 +7,7 @@ HEADERS += \ kernel/qdeadlinetimer.h \ kernel/qdeadlinetimer_p.h \ kernel/qelapsedtimer.h \ - kernel/qeventloop.h\ + kernel/qeventloop.h \ kernel/qpointer.h \ kernel/qcorecmdlineargs_p.h \ kernel/qcoreapplication.h \ diff --git a/src/corelib/kernel/qabstracteventdispatcher.cpp b/src/corelib/kernel/qabstracteventdispatcher.cpp index ea08ff571f..186c2e743b 100644 --- a/src/corelib/kernel/qabstracteventdispatcher.cpp +++ b/src/corelib/kernel/qabstracteventdispatcher.cpp @@ -470,7 +470,11 @@ void QAbstractEventDispatcher::removeNativeEventFilter(QAbstractNativeEventFilte \sa installNativeEventFilter(), QAbstractNativeEventFilter::nativeEventFilter() \since 5.0 */ +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) +bool QAbstractEventDispatcher::filterNativeEvent(const QByteArray &eventType, void *message, qintptr *result) +#else bool QAbstractEventDispatcher::filterNativeEvent(const QByteArray &eventType, void *message, long *result) +#endif { Q_D(QAbstractEventDispatcher); if (!d->eventFilters.isEmpty()) { diff --git a/src/corelib/kernel/qabstracteventdispatcher.h b/src/corelib/kernel/qabstracteventdispatcher.h index bd8da5c35d..4ef9c068df 100644 --- a/src/corelib/kernel/qabstracteventdispatcher.h +++ b/src/corelib/kernel/qabstracteventdispatcher.h @@ -110,7 +110,11 @@ public: void installNativeEventFilter(QAbstractNativeEventFilter *filterObj); void removeNativeEventFilter(QAbstractNativeEventFilter *filterObj); +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + bool filterNativeEvent(const QByteArray &eventType, void *message, qintptr *result); +#else bool filterNativeEvent(const QByteArray &eventType, void *message, long *result); +#endif #if QT_DEPRECATED_SINCE(5, 0) QT_DEPRECATED bool filterEvent(void *message) { return filterNativeEvent("", message, nullptr); } diff --git a/src/corelib/kernel/qabstractnativeeventfilter.cpp b/src/corelib/kernel/qabstractnativeeventfilter.cpp index dcbb92f044..eaadea4c12 100644 --- a/src/corelib/kernel/qabstractnativeeventfilter.cpp +++ b/src/corelib/kernel/qabstractnativeeventfilter.cpp @@ -74,6 +74,7 @@ QAbstractNativeEventFilter::~QAbstractNativeEventFilter() eventDispatcher->removeNativeEventFilter(this); } +// ### fixme Qt 6: result will be qintptr * /*! \fn bool QAbstractNativeEventFilter::nativeEventFilter(const QByteArray &eventType, void *message, long *result) diff --git a/src/corelib/kernel/qabstractnativeeventfilter.h b/src/corelib/kernel/qabstractnativeeventfilter.h index d7baa42513..a468bffd61 100644 --- a/src/corelib/kernel/qabstractnativeeventfilter.h +++ b/src/corelib/kernel/qabstractnativeeventfilter.h @@ -52,7 +52,11 @@ public: QAbstractNativeEventFilter(); virtual ~QAbstractNativeEventFilter(); +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + virtual bool nativeEventFilter(const QByteArray &eventType, void *message, qintptr *result) = 0; +#else virtual bool nativeEventFilter(const QByteArray &eventType, void *message, long *result) = 0; +#endif private: Q_DISABLE_COPY(QAbstractNativeEventFilter) diff --git a/src/corelib/kernel/qcore_foundation.mm b/src/corelib/kernel/qcore_foundation.mm index 56eabc4b8c..623d462749 100644 --- a/src/corelib/kernel/qcore_foundation.mm +++ b/src/corelib/kernel/qcore_foundation.mm @@ -501,7 +501,7 @@ NSTimeZone *QTimeZone::toNSTimeZone() const \sa QRectF::fromCGRect() */ -CGRect QRect::toCGRect() const Q_DECL_NOTHROW +CGRect QRect::toCGRect() const noexcept { return CGRectMake(x(), y(), width(), height()); } @@ -513,7 +513,7 @@ CGRect QRect::toCGRect() const Q_DECL_NOTHROW \sa fromCGRect() */ -CGRect QRectF::toCGRect() const Q_DECL_NOTHROW +CGRect QRectF::toCGRect() const noexcept { return CGRectMake(x(), y(), width(), height()); } @@ -525,7 +525,7 @@ CGRect QRectF::toCGRect() const Q_DECL_NOTHROW \sa toCGRect() */ -QRectF QRectF::fromCGRect(CGRect rect) Q_DECL_NOTHROW +QRectF QRectF::fromCGRect(CGRect rect) noexcept { return QRectF(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height); } @@ -539,7 +539,7 @@ QRectF QRectF::fromCGRect(CGRect rect) Q_DECL_NOTHROW \sa QPointF::fromCGPoint() */ -CGPoint QPoint::toCGPoint() const Q_DECL_NOTHROW +CGPoint QPoint::toCGPoint() const noexcept { return CGPointMake(x(), y()); } @@ -551,7 +551,7 @@ CGPoint QPoint::toCGPoint() const Q_DECL_NOTHROW \sa fromCGPoint() */ -CGPoint QPointF::toCGPoint() const Q_DECL_NOTHROW +CGPoint QPointF::toCGPoint() const noexcept { return CGPointMake(x(), y()); } @@ -563,7 +563,7 @@ CGPoint QPointF::toCGPoint() const Q_DECL_NOTHROW \sa toCGPoint() */ -QPointF QPointF::fromCGPoint(CGPoint point) Q_DECL_NOTHROW +QPointF QPointF::fromCGPoint(CGPoint point) noexcept { return QPointF(point.x, point.y); } @@ -577,7 +577,7 @@ QPointF QPointF::fromCGPoint(CGPoint point) Q_DECL_NOTHROW \sa QSizeF::fromCGSize() */ -CGSize QSize::toCGSize() const Q_DECL_NOTHROW +CGSize QSize::toCGSize() const noexcept { return CGSizeMake(width(), height()); } @@ -589,7 +589,7 @@ CGSize QSize::toCGSize() const Q_DECL_NOTHROW \sa fromCGSize() */ -CGSize QSizeF::toCGSize() const Q_DECL_NOTHROW +CGSize QSizeF::toCGSize() const noexcept { return CGSizeMake(width(), height()); } @@ -601,7 +601,7 @@ CGSize QSizeF::toCGSize() const Q_DECL_NOTHROW \sa toCGSize() */ -QSizeF QSizeF::fromCGSize(CGSize size) Q_DECL_NOTHROW +QSizeF QSizeF::fromCGSize(CGSize size) noexcept { return QSizeF(size.width, size.height); } diff --git a/src/corelib/kernel/qcore_mac_objc.mm b/src/corelib/kernel/qcore_mac_objc.mm index 6687eb88a5..6b51eb65d9 100644 --- a/src/corelib/kernel/qcore_mac_objc.mm +++ b/src/corelib/kernel/qcore_mac_objc.mm @@ -371,7 +371,7 @@ bool operator<(const KeyPair &entry, const Qt::Key &key) struct qtKey2CocoaKeySortLessThan { typedef bool result_type; - Q_DECL_CONSTEXPR result_type operator()(const KeyPair &entry1, const KeyPair &entry2) const Q_DECL_NOTHROW + Q_DECL_CONSTEXPR result_type operator()(const KeyPair &entry1, const KeyPair &entry2) const noexcept { return entry1.qtKey < entry2.qtKey; } diff --git a/src/corelib/kernel/qcore_mac_p.h b/src/corelib/kernel/qcore_mac_p.h index f96e7358a2..920105ee9e 100644 --- a/src/corelib/kernel/qcore_mac_p.h +++ b/src/corelib/kernel/qcore_mac_p.h @@ -90,7 +90,7 @@ public: QAppleRefCounted(const QAppleRefCounted &other) : value(other.value) { if (value) RetainFunction(value); } ~QAppleRefCounted() { if (value) ReleaseFunction(value); } operator T() const { return value; } - void swap(QAppleRefCounted &other) Q_DECL_NOEXCEPT_EXPR(noexcept(qSwap(value, other.value))) + void swap(QAppleRefCounted &other) noexcept(noexcept(qSwap(value, other.value))) { qSwap(value, other.value); } QAppleRefCounted &operator=(const QAppleRefCounted &other) { QAppleRefCounted copy(other); swap(copy); return *this; } diff --git a/src/corelib/kernel/qcore_unix_p.h b/src/corelib/kernel/qcore_unix_p.h index 5a2a29a327..7f58813535 100644 --- a/src/corelib/kernel/qcore_unix_p.h +++ b/src/corelib/kernel/qcore_unix_p.h @@ -171,7 +171,7 @@ inline void qt_ignore_sigpipe() struct sigaction noaction; memset(&noaction, 0, sizeof(noaction)); noaction.sa_handler = SIG_IGN; - ::sigaction(SIGPIPE, &noaction, 0); + ::sigaction(SIGPIPE, &noaction, nullptr); atom.store(1); } } @@ -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 30994d3056..d9fdb7f785 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -256,15 +256,6 @@ void QCoreApplicationPrivate::processCommandLineArguments() // Support for introspection -#ifndef QT_NO_QOBJECT -QSignalSpyCallbackSet Q_CORE_EXPORT qt_signal_spy_callback_set = { 0, 0, 0, 0 }; - -void qt_register_signal_spy_callbacks(const QSignalSpyCallbackSet &callback_set) -{ - qt_signal_spy_callback_set = callback_set; -} -#endif - extern "C" void Q_CORE_EXPORT qt_startup_hook() { } @@ -378,7 +369,7 @@ uint QCoreApplicationPrivate::attribs = (1 << Qt::AA_SynthesizeMouseForUnhandledTabletEvents); struct QCoreApplicationData { - QCoreApplicationData() Q_DECL_NOTHROW { + QCoreApplicationData() noexcept { applicationNameSet = false; applicationVersionSet = false; } @@ -866,11 +857,6 @@ void QCoreApplicationPrivate::init() eventDispatcherReady(); #endif -#ifdef QT_EVAL - extern void qt_core_eval_init(QCoreApplicationPrivate::Type); - qt_core_eval_init(application_type); -#endif - processCommandLineArguments(); qt_call_pre_routines(); diff --git a/src/corelib/kernel/qcoreapplication_p.h b/src/corelib/kernel/qcoreapplication_p.h index b3479414ab..14ca3efd7f 100644 --- a/src/corelib/kernel/qcoreapplication_p.h +++ b/src/corelib/kernel/qcoreapplication_p.h @@ -149,7 +149,7 @@ public: QString cachedApplicationDirPath; static QString *cachedApplicationFilePath; static void setApplicationFilePath(const QString &path); - static inline void clearApplicationFilePath() { delete cachedApplicationFilePath; cachedApplicationFilePath = 0; } + static inline void clearApplicationFilePath() { delete cachedApplicationFilePath; cachedApplicationFilePath = nullptr; } #ifndef QT_NO_QOBJECT void execCleanup(); diff --git a/src/corelib/kernel/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<uint> next; QBasicAtomicInteger<uint> data[NumInts]; - bool allocateSpecific(int which) Q_DECL_NOTHROW + bool allocateSpecific(int which) noexcept { QBasicAtomicInteger<uint> &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<QEvent::MaxUser - QEvent::User + 1> 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<qint64, qint64> 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<qint64>::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<qint64>::max)() || nsecs == (std::numeric_limits<qint64>::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<qint64>::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<qint64>::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<qint64>::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_glib_p.h b/src/corelib/kernel/qeventdispatcher_glib_p.h index 88ff316ee5..313825d0a7 100644 --- a/src/corelib/kernel/qeventdispatcher_glib_p.h +++ b/src/corelib/kernel/qeventdispatcher_glib_p.h @@ -66,8 +66,8 @@ class Q_CORE_EXPORT QEventDispatcherGlib : public QAbstractEventDispatcher Q_DECLARE_PRIVATE(QEventDispatcherGlib) public: - explicit QEventDispatcherGlib(QObject *parent = 0); - explicit QEventDispatcherGlib(GMainContext *context, QObject *parent = 0); + explicit QEventDispatcherGlib(QObject *parent = nullptr); + explicit QEventDispatcherGlib(GMainContext *context, QObject *parent = nullptr); ~QEventDispatcherGlib(); bool processEvents(QEventLoop::ProcessEventsFlags flags) override; @@ -102,7 +102,7 @@ class Q_CORE_EXPORT QEventDispatcherGlibPrivate : public QAbstractEventDispatche { public: - QEventDispatcherGlibPrivate(GMainContext *context = 0); + QEventDispatcherGlibPrivate(GMainContext *context = nullptr); GMainContext *mainContext; GPostEventSource *postEventSource; GSocketNotifierSource *socketNotifierSource; diff --git a/src/corelib/kernel/qeventdispatcher_unix_p.h b/src/corelib/kernel/qeventdispatcher_unix_p.h index 0fd068b074..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]; }; @@ -102,7 +102,7 @@ class Q_CORE_EXPORT QEventDispatcherUNIX : public QAbstractEventDispatcher Q_DECLARE_PRIVATE(QEventDispatcherUNIX) public: - explicit QEventDispatcherUNIX(QObject *parent = 0); + explicit QEventDispatcherUNIX(QObject *parent = nullptr); ~QEventDispatcherUNIX(); bool processEvents(QEventLoop::ProcessEventsFlags flags) override; @@ -123,7 +123,7 @@ public: void flush() override; protected: - QEventDispatcherUNIX(QEventDispatcherUNIXPrivate &dd, QObject *parent = 0); + QEventDispatcherUNIX(QEventDispatcherUNIXPrivate &dd, QObject *parent = nullptr); }; class Q_CORE_EXPORT QEventDispatcherUNIXPrivate : public QAbstractEventDispatcherPrivate @@ -150,19 +150,19 @@ public: QAtomicInt interrupt; // bool }; -inline QSocketNotifierSetUNIX::QSocketNotifierSetUNIX() Q_DECL_NOTHROW +inline QSocketNotifierSetUNIX::QSocketNotifierSetUNIX() noexcept { - notifiers[0] = 0; - notifiers[1] = 0; - notifiers[2] = 0; + notifiers[0] = nullptr; + notifiers[1] = nullptr; + notifiers[2] = nullptr; } -inline bool QSocketNotifierSetUNIX::isEmpty() const Q_DECL_NOTHROW +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/qeventdispatcher_win.cpp b/src/corelib/kernel/qeventdispatcher_win.cpp index 685d765adb..84378454ca 100644 --- a/src/corelib/kernel/qeventdispatcher_win.cpp +++ b/src/corelib/kernel/qeventdispatcher_win.cpp @@ -136,7 +136,11 @@ LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPA msg.wParam = wp; msg.lParam = lp; QAbstractEventDispatcher* dispatcher = QAbstractEventDispatcher::instance(); +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + qintptr result; +#else long result; +#endif if (!dispatcher) { if (message == WM_TIMER) KillTimer(hwnd, wp); 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 2ff8b32e0a..3bcad8cf32 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 { @@ -3017,6 +3017,18 @@ int QMetaProperty::propertyIndex() const } /*! + \since 5.14 + + Returns this property's index relative within the enclosing meta object. +*/ +int QMetaProperty::relativePropertyIndex() const +{ + if (!mobj) + return -1; + return idx; +} + +/*! Returns \c true if the property's type is an enumeration value that is used as a flag; otherwise returns \c false. diff --git a/src/corelib/kernel/qmetaobject.h b/src/corelib/kernel/qmetaobject.h index 51ace3d5f7..6c5f78d208 100644 --- a/src/corelib/kernel/qmetaobject.h +++ b/src/corelib/kernel/qmetaobject.h @@ -253,6 +253,7 @@ public: QVariant::Type type() const; int userType() const; int propertyIndex() const; + int relativePropertyIndex() const; bool isReadable() const; bool isWritable() const; diff --git a/src/corelib/kernel/qmetaobject_moc_p.h b/src/corelib/kernel/qmetaobject_moc_p.h index ad258acfcd..8c7900767b 100644 --- a/src/corelib/kernel/qmetaobject_moc_p.h +++ b/src/corelib/kernel/qmetaobject_moc_p.h @@ -138,7 +138,7 @@ static QByteArray normalizeTypeInternal(const char *t, const char *e, bool fixSc { "struct ", 7 }, { "class ", 6 }, { "enum ", 5 }, - { 0, 0 } + { nullptr, 0 } }; int i = 0; do { @@ -146,7 +146,7 @@ static QByteArray normalizeTypeInternal(const char *t, const char *e, bool fixSc t += optional[i].len; break; } - } while (optional[++i].keyword != 0); + } while (optional[++i].keyword != nullptr); } bool star = false; diff --git a/src/corelib/kernel/qmetaobject_p.h b/src/corelib/kernel/qmetaobject_p.h index 522bd78e42..0cd9da2eac 100644 --- a/src/corelib/kernel/qmetaobject_p.h +++ b/src/corelib/kernel/qmetaobject_p.h @@ -54,6 +54,7 @@ #include <QtCore/qglobal.h> #include <QtCore/qobjectdefs.h> +#include <QtCore/qmutex.h> #ifndef QT_NO_QOBJECT #include <private/qobject_p.h> // For QObjectPrivate::Connection #endif @@ -168,7 +169,6 @@ Q_DECLARE_TYPEINFO(QArgumentType, Q_MOVABLE_TYPE); typedef QVarLengthArray<QArgumentType, 10> QArgumentTypeArray; class QMetaMethodPrivate; -class QMutex; struct QMetaObjectPrivate { @@ -226,15 +226,15 @@ struct QMetaObjectPrivate static QObjectPrivate::Connection *connect(const QObject *sender, int signal_index, const QMetaObject *smeta, const QObject *receiver, int method_index_relative, - const QMetaObject *rmeta = 0, - int type = 0, int *types = 0); + const QMetaObject *rmeta = nullptr, + int type = 0, int *types = nullptr); static bool disconnect(const QObject *sender, int signal_index, const QMetaObject *smeta, const QObject *receiver, int method_index, void **slot, 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, - QMutex *senderMutex, DisconnectType = DisconnectAll); + QBasicMutex *senderMutex, DisconnectType = DisconnectAll); #endif }; diff --git a/src/corelib/kernel/qmetaobjectbuilder_p.h b/src/corelib/kernel/qmetaobjectbuilder_p.h index 6100835bad..6d43be7811 100644 --- a/src/corelib/kernel/qmetaobjectbuilder_p.h +++ b/src/corelib/kernel/qmetaobjectbuilder_p.h @@ -173,7 +173,7 @@ public: void setStaticMetacallFunction(QMetaObjectBuilder::StaticMetacallFunction value); QMetaObject *toMetaObject() const; - QByteArray toRelocatableData(bool * = 0) const; + QByteArray toRelocatableData(bool * = nullptr) const; static void fromRelocatableData(QMetaObject *, const QMetaObject *, const QByteArray &); #ifndef QT_NO_DATASTREAM @@ -196,7 +196,7 @@ private: class Q_CORE_EXPORT QMetaMethodBuilder { public: - QMetaMethodBuilder() : _mobj(0), _index(0) {} + QMetaMethodBuilder() : _mobj(nullptr), _index(0) {} int index() const; @@ -238,7 +238,7 @@ private: class Q_CORE_EXPORT QMetaPropertyBuilder { public: - QMetaPropertyBuilder() : _mobj(0), _index(0) {} + QMetaPropertyBuilder() : _mobj(nullptr), _index(0) {} int index() const { return _index; } @@ -294,7 +294,7 @@ private: class Q_CORE_EXPORT QMetaEnumBuilder { public: - QMetaEnumBuilder() : _mobj(0), _index(0) {} + QMetaEnumBuilder() : _mobj(nullptr), _index(0) {} int index() const { return _index; } diff --git a/src/corelib/kernel/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 <int... TypeIds> struct MetaTypeOffsets<QtPrivate::IndexesList<TypeIds. short offsets[sizeof...(TypeIds)]; constexpr MetaTypeOffsets() : offsets{calculateOffsetForTypeId(TypeIds)...} {} - const char *operator[](int typeId) const Q_DECL_NOTHROW + const char *operator[](int typeId) const noexcept { short o = offsets[typeId]; return o < 0 ? nullptr : metaTypeStrings + o; diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index d03b9fafb1..73b655cb36 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 <ogoffart@woboq.com> ** Contact: https://www.qt.io/licensing/ @@ -77,6 +77,12 @@ QT_BEGIN_NAMESPACE static int DIRECT_CONNECTION_ONLY = 0; +Q_CORE_EXPORT QBasicAtomicPointer<QSignalSpyCallbackSet> qt_signal_spy_callback_set = Q_BASIC_ATOMIC_INITIALIZER(nullptr); + +void qt_register_signal_spy_callbacks(QSignalSpyCallbackSet *callback_set) +{ + qt_signal_spy_callback_set.store(callback_set); +} QDynamicMetaObjectData::~QDynamicMetaObjectData() { @@ -146,10 +152,9 @@ static QBasicMutex _q_ObjectMutexPool[131]; * \internal * mutex to be locked when accessing the connectionlists or the senders list */ -static inline QMutex *signalSlotLock(const QObject *o) +static inline QBasicMutex *signalSlotLock(const QObject *o) { - return static_cast<QMutex *>(&_q_ObjectMutexPool[ - uint(quintptr(o)) % sizeof(_q_ObjectMutexPool)/sizeof(QBasicMutex)]); + return &_q_ObjectMutexPool[uint(quintptr(o)) % sizeof(_q_ObjectMutexPool)/sizeof(QBasicMutex)]; } #if QT_VERSION < 0x60000 @@ -160,39 +165,6 @@ extern "C" Q_CORE_EXPORT void qt_removeObject(QObject *) {} #endif -struct QConnectionSenderSwitcher { - QObject *receiver; - QObjectPrivate::Sender *previousSender; - QObjectPrivate::Sender currentSender; - bool switched; - - inline QConnectionSenderSwitcher() : switched(false) {} - - inline QConnectionSenderSwitcher(QObject *receiver, QObject *sender, int signal_absolute_id) - { - switchSender(receiver, sender, signal_absolute_id); - } - - inline void switchSender(QObject *receiver, QObject *sender, int signal_absolute_id) - { - this->receiver = receiver; - currentSender.sender = sender; - currentSender.signal = signal_absolute_id; - currentSender.ref = 1; - previousSender = QObjectPrivate::setCurrentSender(receiver, ¤tSender); - switched = true; - } - - inline ~QConnectionSenderSwitcher() - { - if (switched) - QObjectPrivate::resetCurrentSender(receiver, ¤tSender, previousSender); - } -private: - Q_DISABLE_COPY(QConnectionSenderSwitcher) -}; - - void (*QAbstractDeclarativeData::destroyed)(QAbstractDeclarativeData *, QObject *) = 0; void (*QAbstractDeclarativeData::destroyed_qml1)(QAbstractDeclarativeData *, QObject *) = 0; void (*QAbstractDeclarativeData::parentChanged)(QAbstractDeclarativeData *, QObject *, QObject *) = 0; @@ -209,7 +181,7 @@ QMetaObject *QObjectData::dynamicMetaObject() const } QObjectPrivate::QObjectPrivate(int version) - : threadData(0), connectionLists(0), senders(0), currentSender(0), currentChildBeingDeleted(0) + : threadData(0), currentChildBeingDeleted(0) { #ifdef QT_BUILD_INTERNAL // Don't check the version parameter in internal builds. @@ -232,7 +204,6 @@ QObjectPrivate::QObjectPrivate(int version) receiveChildEvents = true; postedEvents = 0; extraData = 0; - connectedSignals[0] = connectedSignals[1] = 0; metaObject = 0; isWindow = false; deleteLaterCalled = false; @@ -285,59 +256,22 @@ static void computeOffsets(const QMetaObject *metaobject, int *signalOffset, int } } -/* - This vector contains the all connections from an object. - - Each object may have one vector containing the lists of - connections for a given signal. The index in the vector correspond - to the signal index. The signal index is the one returned by - QObjectPrivate::signalIndex (not QMetaObject::indexOfSignal). - Negative index means connections to all signals. - - This vector is protected by the object mutex (signalSlotMutexes()) - - Each Connection is also part of a 'senders' linked list. The mutex - of the receiver must be locked when touching the pointers of this - linked list. -*/ -class QObjectConnectionListVector : public QVector<QObjectPrivate::ConnectionList> -{ -public: - bool orphaned; //the QObject owner of this vector has been destroyed while the vector was inUse - bool dirty; //some Connection have been disconnected (their receiver is 0) but not removed from the list yet - int inUse; //number of functions that are currently accessing this object or its connections - QObjectPrivate::ConnectionList allsignals; - - QObjectConnectionListVector() - : QVector<QObjectPrivate::ConnectionList>(), orphaned(false), dirty(false), inUse(0) - { } - - QObjectPrivate::ConnectionList &operator[](int at) - { - if (at < 0) - return allsignals; - return QVector<QObjectPrivate::ConnectionList>::operator[](at); - } -}; - // Used by QAccessibleWidget bool QObjectPrivate::isSender(const QObject *receiver, const char *signal) const { Q_Q(const QObject); int signal_index = signalIndex(signal); - if (signal_index < 0) + ConnectionData *cd = connections.load(); + if (signal_index < 0 || !cd) return false; - QMutexLocker locker(signalSlotLock(q)); - if (connectionLists) { - if (signal_index < connectionLists->count()) { - const QObjectPrivate::Connection *c = - connectionLists->at(signal_index).first; - - while (c) { - if (c->receiver == receiver) - return true; - c = c->nextConnectionList; - } + QBasicMutexLocker locker(signalSlotLock(q)); + if (signal_index < cd->signalVectorCount()) { + const QObjectPrivate::Connection *c = cd->signalVector.load()->at(signal_index).first.load(); + + while (c) { + if (c->receiver.load() == receiver) + return true; + c = c->nextConnectionList.load(); } } return false; @@ -346,21 +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); - if (signal_index < 0) + ConnectionData *cd = connections.load(); + if (signal_index < 0 || !cd) return returnValue; - QMutexLocker locker(signalSlotLock(q)); - if (connectionLists) { - if (signal_index < connectionLists->count()) { - const QObjectPrivate::Connection *c = connectionLists->at(signal_index).first; - - while (c) { - if (c->receiver) - returnValue << c->receiver; - c = c->nextConnectionList; - } + if (signal_index < cd->signalVectorCount()) { + const QObjectPrivate::Connection *c = cd->signalVector.load()->at(signal_index).first.load(); + + while (c) { + QObject *r = c->receiver.load(); + if (r) + returnValue << r; + c = c->nextConnectionList.load(); } } return returnValue; @@ -370,9 +302,12 @@ QObjectList QObjectPrivate::receiverList(const char *signal) const QObjectList QObjectPrivate::senderList() const { QObjectList returnValue; - QMutexLocker locker(signalSlotLock(q_func())); - for (Connection *c = senders; c; c = c->next) - returnValue << c->sender; + ConnectionData *cd = connections.load(); + if (cd) { + QBasicMutexLocker locker(signalSlotLock(q_func())); + for (Connection *c = cd->senders; c; c = c->next) + returnValue << c->sender; + } return returnValue; } @@ -389,79 +324,187 @@ QObjectList QObjectPrivate::senderList() const void QObjectPrivate::addConnection(int signal, Connection *c) { Q_ASSERT(c->sender == q_ptr); - if (!connectionLists) - connectionLists = new QObjectConnectionListVector(); - if (signal >= connectionLists->count()) - connectionLists->resize(signal + 1); - - ConnectionList &connectionList = (*connectionLists)[signal]; - if (connectionList.last) { - connectionList.last->nextConnectionList = c; + ensureConnectionData(); + ConnectionData *cd = connections.load(); + cd->resizeSignalVector(signal + 1); + + ConnectionList &connectionList = cd->connectionsForSignal(signal); + 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); } - connectionList.last = c; + c->id = ++cd->currentConnectionId; + c->prevConnectionList = connectionList.last.load(); + connectionList.last.store(c); - cleanConnectionLists(); + QObjectPrivate *rd = QObjectPrivate::get(c->receiver.load()); + rd->ensureConnectionData(); - c->prev = &(QObjectPrivate::get(c->receiver)->senders); + c->prev = &(rd->connections.load()->senders); c->next = *c->prev; *c->prev = c; if (c->next) 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); - if (signal < 0) { - connectedSignals[0] = connectedSignals[1] = ~0; - } else if (signal < (int)sizeof(connectedSignals) * 8) { - connectedSignals[signal >> 5] |= (1 << (signal & 0x1f)); +#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::cleanConnectionLists() +void QObjectPrivate::ConnectionData::cleanOrphanedConnectionsImpl(QObject *sender) { - if (connectionLists->dirty && !connectionLists->inUse) { - // remove broken connections - bool allConnected = false; - for (int signal = -1; signal < connectionLists->count(); ++signal) { - QObjectPrivate::ConnectionList &connectionList = - (*connectionLists)[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; - bool connected = false; // whether the signal is still connected somewhere - while (c) { - if (c->receiver) { - last = c; - prev = &c->nextConnectionList; - c = *prev; - connected = true; - } else { - QObjectPrivate::Connection *next = c->nextConnectionList; - *prev = next; - c->deref(); - c = next; - } - } + ConnectionOrSignalVector *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; + // 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); + } + deleteOrphaned(c); +} - if (!allConnected && !connected && signal >= 0 - && size_t(signal) < sizeof(connectedSignals) * 8) { - // This signal is no longer connected - connectedSignals[signal >> 5] &= ~(1 << (signal & 0x1f)); - } else if (signal == -1) { - allConnected = connected; - } +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<Connection *>(o); + next = c->nextInOrphanList; + Q_ASSERT(!c->receiver.load()); + Q_ASSERT(!c->prev); + c->freeSlotObject(); + c->deref(); } - connectionLists->dirty = false; + o = next; + } +} + +/*! \internal + + Returns \c true if the signal with index \a signal_index from object \a sender is connected. + + \a signal_index must be the index returned by QObjectPrivate::signalIndex; +*/ +bool QObjectPrivate::isSignalConnected(uint signalIndex, bool checkDeclarative) const +{ + if (checkDeclarative && isDeclarativeSignalConnected(signalIndex)) + return true; + + ConnectionData *cd = connections.load(); + if (!cd) + return false; + SignalVector *signalVector = cd->signalVector.load(); + if (!signalVector) + return false; + + if (signalVector->at(-1).first.load()) + return true; + + if (signalIndex < uint(cd->signalVectorCount())) { + const QObjectPrivate::Connection *c = signalVector->at(signalIndex).first.load(); + while (c) { + if (c->receiver.load()) + return true; + c = c->nextConnectionList.load(); + } + } + return false; +} + +bool QObjectPrivate::maybeSignalConnected(uint signalIndex) const +{ + ConnectionData *cd = connections.load(); + if (!cd) + return false; + SignalVector *signalVector = cd->signalVector.load(); + if (!signalVector) + return false; + + if (signalVector->at(-1).first) + return true; + + if (signalIndex < uint(cd->signalVectorCount())) { + const QObjectPrivate::Connection *c = signalVector->at(signalIndex).first; + return c != nullptr; } + return false; +} + +/*! + \internal + */ +QAbstractMetaCallEvent::~QAbstractMetaCallEvent() +{ +#if QT_CONFIG(thread) + if (semaphore_) + semaphore_->release(); +#endif } /*! @@ -470,8 +513,8 @@ void QObjectPrivate::cleanConnectionLists() 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) { } @@ -480,9 +523,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(); @@ -501,10 +544,6 @@ QMetaCallEvent::~QMetaCallEvent() free(types_); free(args_); } -#if QT_CONFIG(thread) - if (semaphore_) - semaphore_->release(); -#endif if (slotObj_) slotObj_->destroyIfLastRef(); } @@ -921,92 +960,56 @@ QObject::~QObject() } } - // set ref to zero to indicate that this object has been deleted - if (d->currentSender != 0) - d->currentSender->ref = 0; - d->currentSender = 0; + QObjectPrivate::ConnectionData *cd = d->connections.load(); + if (cd) { + if (cd->currentSender) { + cd->currentSender->receiverDeleted(); + cd->currentSender = nullptr; + } - if (d->connectionLists || d->senders) { - QMutex *signalSlotMutex = signalSlotLock(this); - QMutexLocker locker(signalSlotMutex); + QBasicMutex *signalSlotMutex = signalSlotLock(this); + QBasicMutexLocker locker(signalSlotMutex); // disconnect all receivers - if (d->connectionLists) { - ++d->connectionLists->inUse; - int connectionListsCount = d->connectionLists->count(); - for (int signal = -1; signal < connectionListsCount; ++signal) { - QObjectPrivate::ConnectionList &connectionList = - (*d->connectionLists)[signal]; - - while (QObjectPrivate::Connection *c = connectionList.first) { - if (!c->receiver) { - connectionList.first = c->nextConnectionList; - c->deref(); - continue; - } + int receiverCount = cd->signalVectorCount(); + for (int signal = -1; signal < receiverCount; ++signal) { + QObjectPrivate::ConnectionList &connectionList = cd->connectionsForSignal(signal); - QMutex *m = signalSlotLock(c->receiver); - bool needToUnlock = QOrderedMutexLocker::relock(signalSlotMutex, m); + while (QObjectPrivate::Connection *c = connectionList.first.load()) { + Q_ASSERT(c->receiver); - if (c->receiver) { - *c->prev = c->next; - if (c->next) c->next->prev = c->prev; - } - c->receiver = 0; - if (needToUnlock) - m->unlock(); - - connectionList.first = c->nextConnectionList; - - // The destroy operation must happen outside the lock - if (c->isSlotObject) { - c->isSlotObject = false; - locker.unlock(); - c->slotObj->destroyIfLastRef(); - locker.relock(); - } - c->deref(); + QBasicMutex *m = signalSlotLock(c->receiver.load()); + bool needToUnlock = QOrderedMutexLocker::relock(signalSlotMutex, m); + if (c->receiver) { + cd->removeConnection(c); + Q_ASSERT(connectionList.first.load() != c); } + if (needToUnlock) + m->unlock(); } - - if (!--d->connectionLists->inUse) { - delete d->connectionLists; - } else { - d->connectionLists->orphaned = true; - } - d->connectionLists = 0; } /* 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 = d->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. // This ensures any eventual destructor of sender will block on getting receiver's lock // and not finish until we release it. sender->disconnectNotify(QMetaObjectPrivate::signal(sender->metaObject(), node->signal_index)); - QMutex *m = signalSlotLock(sender); - node->prev = &node; + QBasicMutex *m = signalSlotLock(sender); 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; - QObjectConnectionListVector *senderLists = sender->d_func()->connectionLists; - if (senderLists) - senderLists->dirty = true; + + QObjectPrivate::ConnectionData *senderData = sender->d_func()->connections.load(); + Q_ASSERT(senderData); QtPrivate::QSlotObjectBase *slotObj = nullptr; if (node->isSlotObject) { @@ -1014,19 +1017,24 @@ 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(); } } + + // invalidate all connections on the object and make sure + // activate() will skip them + cd->currentConnectionId.store(0); } + if (cd && !cd->ref.deref()) + delete cd; + d->connections.store(nullptr); if (!d->children.isEmpty()) d->deleteChildren(); @@ -1253,9 +1261,13 @@ bool QObject::event(QEvent *e) case QEvent::MetaCall: { - QMetaCallEvent *mce = static_cast<QMetaCallEvent*>(e); + QAbstractMetaCallEvent *mce = static_cast<QAbstractMetaCallEvent*>(e); - QConnectionSenderSwitcher sw(this, const_cast<QObject*>(mce->sender()), mce->signalId()); + if (!d_func()->connections.load()) { + QBasicMutexLocker locker(signalSlotLock(this)); + d_func()->ensureConnectionData(); + } + QObjectPrivate::Sender sender(this, const_cast<QObject*>(mce->sender()), mce->signalId()); mce->placeMetaCall(this); break; @@ -1415,7 +1427,7 @@ bool QObject::eventFilter(QObject * /* watched */, QEvent * /* event */) \sa signalsBlocked(), QSignalBlocker */ -bool QObject::blockSignals(bool block) Q_DECL_NOTHROW +bool QObject::blockSignals(bool block) noexcept { Q_D(QObject); bool previous = d->blockSig; @@ -1510,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); @@ -1559,9 +1574,31 @@ void QObjectPrivate::setThreadData_helper(QThreadData *currentData, QThreadData } // the current emitting thread shouldn't restore currentSender after calling moveToThread() - if (currentSender) - currentSender->ref = 0; - currentSender = 0; + ConnectionData *cd = connections.load(); + 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 targetData->ref(); @@ -2370,13 +2407,14 @@ QObject *QObject::sender() const { Q_D(const QObject); - QMutexLocker locker(signalSlotLock(this)); - if (!d->currentSender) - return 0; + QBasicMutexLocker locker(signalSlotLock(this)); + QObjectPrivate::ConnectionData *cd = d->connections.load(); + if (!cd || !cd->currentSender) + return nullptr; - for (QObjectPrivate::Connection *c = d->senders; c; c = c->next) { - if (c->sender == d->currentSender->sender) - return d->currentSender->sender; + for (QObjectPrivate::Connection *c = cd->senders; c; c = c->next) { + if (c->sender == cd->currentSender->sender) + return cd->currentSender->sender; } return 0; @@ -2411,14 +2449,15 @@ int QObject::senderSignalIndex() const { Q_D(const QObject); - QMutexLocker locker(signalSlotLock(this)); - if (!d->currentSender) + QBasicMutexLocker locker(signalSlotLock(this)); + QObjectPrivate::ConnectionData *cd = d->connections.load(); + if (!cd || !cd->currentSender) return -1; - for (QObjectPrivate::Connection *c = d->senders; c; c = c->next) { - if (c->sender == d->currentSender->sender) { + for (QObjectPrivate::Connection *c = cd->senders; c; c = c->next) { + if (c->sender == cd->currentSender->sender) { // Convert from signal range to method range - return QMetaObjectPrivate::signal(c->sender->metaObject(), d->currentSender->signal).methodIndex(); + return QMetaObjectPrivate::signal(c->sender->metaObject(), cd->currentSender->signal).methodIndex(); } } @@ -2474,15 +2513,13 @@ int QObject::receivers(const char *signal) const signal_index); } - QMutexLocker locker(signalSlotLock(this)); - if (d->connectionLists) { - if (signal_index < d->connectionLists->count()) { - const QObjectPrivate::Connection *c = - d->connectionLists->at(signal_index).first; - while (c) { - receivers += c->receiver ? 1 : 0; - c = c->nextConnectionList; - } + QObjectPrivate::ConnectionData *cd = d->connections.load(); + QBasicMutexLocker locker(signalSlotLock(this)); + if (cd && signal_index < cd->signalVectorCount()) { + const QObjectPrivate::Connection *c = cd->signalVector.load()->at(signal_index).first.load(); + while (c) { + receivers += c->receiver.load() ? 1 : 0; + c = c->nextConnectionList.load(); } } } @@ -2522,22 +2559,8 @@ bool QObject::isSignalConnected(const QMetaMethod &signal) const signalIndex += QMetaObjectPrivate::signalOffset(signal.mobj); - QMutexLocker locker(signalSlotLock(this)); - if (d->connectionLists) { - if (signalIndex < sizeof(d->connectedSignals) * 8 && !d->connectionLists->dirty) - return d->isSignalConnected(signalIndex); - - if (signalIndex < uint(d->connectionLists->count())) { - const QObjectPrivate::Connection *c = - d->connectionLists->at(signalIndex).first; - while (c) { - if (c->receiver) - return true; - c = c->nextConnectionList; - } - } - } - return d->isDeclarativeSignalConnected(signalIndex); + QBasicMutexLocker locker(signalSlotLock(this)); + return d->isSignalConnected(signalIndex, true); } /*! @@ -3300,24 +3323,22 @@ QObjectPrivate::Connection *QMetaObjectPrivate::connect(const QObject *sender, int method_offset = rmeta ? rmeta->methodOffset() : 0; Q_ASSERT(!rmeta || QMetaObjectPrivate::get(rmeta)->revision >= 6); - QObjectPrivate::StaticMetaCallFunction callFunction = - rmeta ? rmeta->d.static_metacall : 0; + QObjectPrivate::StaticMetaCallFunction callFunction = rmeta ? rmeta->d.static_metacall : nullptr; QOrderedMutexLocker locker(signalSlotLock(sender), signalSlotLock(receiver)); - if (type & Qt::UniqueConnection) { - QObjectConnectionListVector *connectionLists = QObjectPrivate::get(s)->connectionLists; - if (connectionLists && connectionLists->count() > signal_index) { - const QObjectPrivate::Connection *c2 = - (*connectionLists)[signal_index].first; + QObjectPrivate::ConnectionData *scd = QObjectPrivate::get(s)->connections.load(); + if (type & Qt::UniqueConnection && scd) { + if (scd->signalVectorCount() > signal_index) { + 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) - return 0; - c2 = c2->nextConnectionList; + if (!c2->isSlotObject && c2->receiver.load() == receiver && c2->method() == method_index_absolute) + return nullptr; + c2 = c2->nextConnectionList.load(); } } type &= Qt::UniqueConnection - 1; @@ -3326,13 +3347,15 @@ QObjectPrivate::Connection *QMetaObjectPrivate::connect(const QObject *sender, QScopedPointer<QObjectPrivate::Connection> 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()); @@ -3378,47 +3401,38 @@ 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, - QMutex *senderMutex, DisconnectType disconnectType) + QBasicMutex *senderMutex, DisconnectType disconnectType) { bool success = false; + + auto &connectionList = connections->connectionsForSignal(signalIndex); + auto *c = connectionList.first.load(); while (c) { - if (c->receiver - && (receiver == 0 || (c->receiver == receiver + QObject *r = c->receiver.load(); + if (r && (receiver == nullptr || (r == 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; - QMutex *receiverMutex = 0; - if (c->receiver) { - receiverMutex = signalSlotLock(c->receiver); + QBasicMutex *receiverMutex = nullptr; + if (r) { + receiverMutex = signalSlotLock(r); // 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.load()) + 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) return success; } - c = c->nextConnectionList; + c = c->nextConnectionList.load(); } return success; } @@ -3437,43 +3451,34 @@ bool QMetaObjectPrivate::disconnect(const QObject *sender, QObject *s = const_cast<QObject *>(sender); - QMutex *senderMutex = signalSlotLock(sender); - QMutexLocker locker(senderMutex); + QBasicMutex *senderMutex = signalSlotLock(sender); + QBasicMutexLocker locker(senderMutex); - QObjectConnectionListVector *connectionLists = QObjectPrivate::get(s)->connectionLists; - if (!connectionLists) + QObjectPrivate::ConnectionData *scd = QObjectPrivate::get(s)->connections.load(); + if (!scd) return false; - // prevent incoming connections changing the connectionLists while unlocked - ++connectionLists->inUse; - bool success = false; - if (signal_index < 0) { - // remove from all connection lists - for (int sig_index = -1; sig_index < connectionLists->count(); ++sig_index) { - QObjectPrivate::Connection *c = - (*connectionLists)[sig_index].first; - if (disconnectHelper(c, receiver, method_index, slot, senderMutex, disconnectType)) { - success = true; - connectionLists->dirty = true; + { + // prevent incoming connections changing the connections->receivers while unlocked + QObjectPrivate::ConnectionDataPointer connections(scd); + + if (signal_index < 0) { + // remove from all connection lists + for (int sig_index = -1; sig_index < scd->signalVectorCount(); ++sig_index) { + if (disconnectHelper(connections.data(), sig_index, receiver, method_index, slot, senderMutex, disconnectType)) + success = true; } - } - } else if (signal_index < connectionLists->count()) { - QObjectPrivate::Connection *c = - (*connectionLists)[signal_index].first; - if (disconnectHelper(c, receiver, method_index, slot, senderMutex, disconnectType)) { - success = true; - connectionLists->dirty = true; + } else if (signal_index < scd->signalVectorCount()) { + if (disconnectHelper(connections.data(), signal_index, receiver, method_index, slot, senderMutex, disconnectType)) + success = true; } } - --connectionLists->inUse; - Q_ASSERT(connectionLists->inUse >= 0); - if (connectionLists->orphaned && !connectionLists->inUse) - delete connectionLists; - locker.unlock(); if (success) { + scd->cleanOrphanedConnections(s); + QMetaMethod smethod = QMetaObjectPrivate::signal(smeta, signal_index); if (smethod.isValid()) s->disconnectNotify(smethod); @@ -3589,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, - QMutexLocker &locker) +static void queued_activate(QObject *sender, int signal, QObjectPrivate::Connection *c, void **argv) { const int *argumentTypes = c->argumentTypes.load(); if (!argumentTypes) { @@ -3620,134 +3624,111 @@ 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); } -/*! - \internal - */ -void QMetaObject::activate(QObject *sender, const QMetaObject *m, int local_signal_index, - void **argv) -{ - activate(sender, QMetaObjectPrivate::signalOffset(m), local_signal_index, argv); -} - -/*! - \internal - */ -void QMetaObject::activate(QObject *sender, int signalOffset, int local_signal_index, void **argv) +template <bool callbacks_enabled> +void doActivate(QObject *sender, int signal_index, void **argv) { - int signal_index = signalOffset + local_signal_index; + QObjectPrivate *sp = QObjectPrivate::get(sender); - if (sender->d_func()->blockSig) + if (sp->blockSig) return; - if (sender->d_func()->isDeclarativeSignalConnected(signal_index) + if (sp->isDeclarativeSignalConnected(signal_index) && QAbstractDeclarativeData::signalEmitted) { Q_TRACE(QMetaObject_activate_begin_declarative_signal, sender, signal_index); - QAbstractDeclarativeData::signalEmitted(sender->d_func()->declarativeData, sender, + QAbstractDeclarativeData::signalEmitted(sp->declarativeData, sender, signal_index, argv); Q_TRACE(QMetaObject_activate_end_declarative_signal, sender, signal_index); } - if (!sender->d_func()->isSignalConnected(signal_index, /*checkDeclarative =*/ false) - && !qt_signal_spy_callback_set.signal_begin_callback - && !qt_signal_spy_callback_set.signal_end_callback - && !Q_TRACE_ENABLED(QMetaObject_activate_begin_signal) - && !Q_TRACE_ENABLED(QMetaObject_activate_end_signal)) { - // The possible declarative connection is done, and nothing else is connected, so: - return; - } + const QSignalSpyCallbackSet *signal_spy_set = callbacks_enabled ? qt_signal_spy_callback_set.load() : nullptr; void *empty_argv[] = { nullptr }; if (!argv) argv = empty_argv; - if (qt_signal_spy_callback_set.signal_begin_callback != 0) { - qt_signal_spy_callback_set.signal_begin_callback(sender, signal_index, argv); + if (!sp->maybeSignalConnected(signal_index)) { + // The possible declarative connection is done, and nothing else is connected + if (callbacks_enabled && signal_spy_set->signal_begin_callback != nullptr) + signal_spy_set->signal_begin_callback(sender, signal_index, argv); + Q_TRACE(QMetaObject_activate_begin_signal, sender, signal_index); + Q_TRACE(QMetaObject_activate_end_signal, sender, signal_index); + if (callbacks_enabled && signal_spy_set->signal_end_callback != nullptr) + signal_spy_set->signal_end_callback(sender, signal_index); + return; } + + if (callbacks_enabled && signal_spy_set->signal_begin_callback != nullptr) + signal_spy_set->signal_begin_callback(sender, signal_index, argv); Q_TRACE(QMetaObject_activate_begin_signal, sender, signal_index); + bool senderDeleted = false; { - QMutexLocker locker(signalSlotLock(sender)); - struct ConnectionListsRef { - QObjectConnectionListVector *connectionLists; - ConnectionListsRef(QObjectConnectionListVector *connectionLists) : connectionLists(connectionLists) - { - if (connectionLists) - ++connectionLists->inUse; - } - ~ConnectionListsRef() - { - if (!connectionLists) - return; - - --connectionLists->inUse; - Q_ASSERT(connectionLists->inUse >= 0); - if (connectionLists->orphaned) { - if (!connectionLists->inUse) - delete connectionLists; - } - } - - QObjectConnectionListVector *operator->() const { return connectionLists; } - }; - ConnectionListsRef connectionLists = sender->d_func()->connectionLists; - if (!connectionLists.connectionLists) { - locker.unlock(); - if (qt_signal_spy_callback_set.signal_end_callback != 0) - qt_signal_spy_callback_set.signal_end_callback(sender, signal_index); - Q_TRACE(QMetaObject_activate_end_signal, sender, signal_index); - return; - } + Q_ASSERT(sp->connections); + QObjectPrivate::ConnectionDataPointer connections(sp->connections.load()); + QObjectPrivate::SignalVector *signalVector = connections->signalVector.load(); const QObjectPrivate::ConnectionList *list; - if (signal_index < connectionLists->count()) - list = &connectionLists->at(signal_index); + if (signal_index < signalVector->count()) + list = &signalVector->at(signal_index); else - list = &connectionLists->allsignals; + 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; - 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; + 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 == receiver->d_func()->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) { @@ -3758,89 +3739,103 @@ void QMetaObject::activate(QObject *sender, int signalOffset, int local_signal_i 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 } - QConnectionSenderSwitcher sw; + QObjectPrivate::Sender senderData(receiverInSameThread ? receiver : nullptr, sender, signal_index); - if (receiverInSameThread) { - sw.switchSender(receiver, sender, signal_index); - } if (c->isSlotObject) { c->slotObj->ref(); QScopedPointer<QtPrivate::QSlotObjectBase, QSlotObjectBaseDeleter> 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 methodIndex = c->method(); const int method_relative = c->method_relative; const auto callFunction = c->callFunction; - locker.unlock(); - if (qt_signal_spy_callback_set.slot_begin_callback != 0) - qt_signal_spy_callback_set.slot_begin_callback(receiver, methodIndex, argv); + const int methodIndex = (Q_HAS_TRACEPOINTS || callbacks_enabled) ? c->method() : 0; + if (callbacks_enabled && signal_spy_set->slot_begin_callback != nullptr) + signal_spy_set->slot_begin_callback(receiver, methodIndex, argv); Q_TRACE(QMetaObject_activate_begin_slot, receiver, methodIndex); callFunction(receiver, QMetaObject::InvokeMetaMethod, method_relative, argv); Q_TRACE(QMetaObject_activate_end_slot, receiver, methodIndex); - if (qt_signal_spy_callback_set.slot_end_callback != 0) - qt_signal_spy_callback_set.slot_end_callback(receiver, methodIndex); - locker.relock(); + if (callbacks_enabled && signal_spy_set->slot_end_callback != nullptr) + signal_spy_set->slot_end_callback(receiver, methodIndex); } else { const int method = c->method_relative + c->method_offset; - locker.unlock(); - if (qt_signal_spy_callback_set.slot_begin_callback != 0) { - qt_signal_spy_callback_set.slot_begin_callback(receiver, method, argv); + if (callbacks_enabled && signal_spy_set->slot_begin_callback != nullptr) { + signal_spy_set->slot_begin_callback(receiver, method, argv); } Q_TRACE(QMetaObject_activate_begin_slot, receiver, method); - metacall(receiver, QMetaObject::InvokeMetaMethod, method, argv); + QMetaObject::metacall(receiver, QMetaObject::InvokeMetaMethod, method, argv); Q_TRACE(QMetaObject_activate_end_slot, receiver, method); - if (qt_signal_spy_callback_set.slot_end_callback != 0) - qt_signal_spy_callback_set.slot_end_callback(receiver, method); - - locker.relock(); + if (callbacks_enabled && signal_spy_set->slot_end_callback != nullptr) + signal_spy_set->slot_end_callback(receiver, method); } + } while ((c = c->nextConnectionList.load()) != nullptr && c->id <= highestConnectionId); - if (connectionLists->orphaned) - break; - } while (c != last && (c = c->nextConnectionList) != 0); - - if (connectionLists->orphaned) - break; - } while (list != &connectionLists->allsignals && + } while (list != &signalVector->at(-1) && //start over for all signals; - ((list = &connectionLists->allsignals), true)); + ((list = &signalVector->at(-1)), true)); + if (connections->currentConnectionId.load() == 0) + senderDeleted = true; } + if (!senderDeleted) + sp->connections.load()->cleanOrphanedConnections(sender); - if (qt_signal_spy_callback_set.signal_end_callback != 0) - qt_signal_spy_callback_set.signal_end_callback(sender, signal_index); + if (callbacks_enabled && signal_spy_set->signal_end_callback != nullptr) + signal_spy_set->signal_end_callback(sender, signal_index); Q_TRACE(QMetaObject_activate_end_signal, sender, signal_index); + +} + +/*! + \internal + */ +void QMetaObject::activate(QObject *sender, const QMetaObject *m, int local_signal_index, + void **argv) +{ + int signal_index = local_signal_index + QMetaObjectPrivate::signalOffset(m); + + if (Q_UNLIKELY(qt_signal_spy_callback_set.load())) + doActivate<true>(sender, signal_index, argv); + else + doActivate<false>(sender, signal_index, argv); } /*! \internal + */ +void QMetaObject::activate(QObject *sender, int signalOffset, int local_signal_index, void **argv) +{ + int signal_index = signalOffset + local_signal_index; + + if (Q_UNLIKELY(qt_signal_spy_callback_set.load())) + doActivate<true>(sender, signal_index, argv); + else + doActivate<false>(sender, signal_index, argv); + } + +/*! + \internal signal_index comes from indexOfMethod() */ void QMetaObject::activate(QObject *sender, int signal_index, void **argv) @@ -3853,7 +3848,7 @@ void QMetaObject::activate(QObject *sender, int signal_index, void **argv) /*! \internal - Returns the signal index used in the internal connectionLists vector. + Returns the signal index used in the internal connections->receivers vector. It is different from QMetaObject::indexOfSignal(): indexOfSignal is the same as indexOfMethod while QObjectPrivate::signalIndex is smaller because it doesn't give index to slots. @@ -4093,37 +4088,40 @@ void QObject::dumpObjectInfo() const objectName().isEmpty() ? "unnamed" : objectName().toLocal8Bit().data()); Q_D(const QObject); - QMutexLocker locker(signalSlotLock(this)); + QBasicMutexLocker locker(signalSlotLock(this)); // first, look for connections where this object is the sender qDebug(" SIGNALS OUT"); - if (d->connectionLists) { - for (int signal_index = 0; signal_index < d->connectionLists->count(); ++signal_index) { + QObjectPrivate::ConnectionData *cd = d->connections.load(); + if (cd && cd->signalVectorCount()) { + 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); qDebug(" signal: %s", signal.methodSignature().constData()); // receivers - const QObjectPrivate::Connection *c = - d->connectionLists->at(signal_index).first; while (c) { - if (!c->receiver) { + if (!c->receiver.load()) { qDebug(" <Disconnected receiver>"); - c = c->nextConnectionList; + c = c->nextConnectionList.load(); continue; } if (c->isSlotObject) { qDebug(" <functor or function pointer>"); - 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 { @@ -4133,8 +4131,8 @@ void QObject::dumpObjectInfo() const // now look for connections where this object is the receiver qDebug(" SIGNALS IN"); - if (d->senders) { - for (QObjectPrivate::Connection *s = d->senders; s; s = s->next) { + if (cd && cd->senders) { + for (QObjectPrivate::Connection *s = cd->senders; s; s = s->next) { QByteArray slotName = QByteArrayLiteral("<unknown>"); if (!s->isSlotObject) { const QMetaMethod slot = metaObject()->method(s->method()); @@ -4869,18 +4867,17 @@ QMetaObject::Connection QObjectPrivate::connectImpl(const QObject *sender, int s QOrderedMutexLocker locker(signalSlotLock(sender), signalSlotLock(receiver)); - if (type & Qt::UniqueConnection && slot) { - QObjectConnectionListVector *connectionLists = QObjectPrivate::get(s)->connectionLists; - if (connectionLists && connectionLists->count() > signal_index) { - const QObjectPrivate::Connection *c2 = - (*connectionLists)[signal_index].first; + if (type & Qt::UniqueConnection && slot && QObjectPrivate::get(s)->connections.load()) { + QObjectPrivate::ConnectionData *connections = QObjectPrivate::get(s)->connections.load(); + if (connections->signalVectorCount() > signal_index) { + 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<Qt::ConnectionType>(type ^ Qt::UniqueConnection); @@ -4889,7 +4886,10 @@ QMetaObject::Connection QObjectPrivate::connectImpl(const QObject *sender, int s QScopedPointer<QObjectPrivate::Connection> 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; @@ -4921,35 +4921,35 @@ bool QObject::disconnect(const QMetaObject::Connection &connection) { QObjectPrivate::Connection *c = static_cast<QObjectPrivate::Connection *>(connection.d_ptr); - if (!c || !c->receiver) + if (!c) + return false; + QObject *receiver = c->receiver.load(); + if (!receiver) return false; - QMutex *senderMutex = signalSlotLock(c->sender); - QMutex *receiverMutex = signalSlotLock(c->receiver); + QBasicMutex *senderMutex = signalSlotLock(c->sender); + QBasicMutex *receiverMutex = signalSlotLock(receiver); + QObjectPrivate::ConnectionData *connections; { QOrderedMutexLocker locker(senderMutex, receiverMutex); - QObjectConnectionListVector *connectionLists = QObjectPrivate::get(c->sender)->connectionLists; - Q_ASSERT(connectionLists); - connectionLists->dirty = true; + // 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; - *c->prev = c->next; - if (c->next) - c->next->prev = c->prev; - c->receiver = 0; + 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)); - const_cast<QMetaObject::Connection &>(connection).d_ptr = 0; + const_cast<QMetaObject::Connection &>(connection).d_ptr = nullptr; c->deref(); // has been removed from the QMetaObject::Connection object return true; @@ -5131,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<QObjectPrivate::Connection *>(d_ptr); - return c->receiver; + return c->receiver.load(); } diff --git a/src/corelib/kernel/qobject.h b/src/corelib/kernel/qobject.h index 63c5a9ad73..1d83731441 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<QObjectData> 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,15 @@ 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; -#endif + inline QSignalBlocker(QSignalBlocker &&other) noexcept; + inline QSignalBlocker &operator=(QSignalBlocker &&other) noexcept; - 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 +556,19 @@ 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 +576,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: @@ -594,7 +591,6 @@ QSignalBlocker &QSignalBlocker::operator=(QSignalBlocker &&other) Q_DECL_NOTHROW } return *this; } -#endif QSignalBlocker::~QSignalBlocker() { @@ -602,13 +598,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/qobject_p.h b/src/corelib/kernel/qobject_p.h index a762e6f529..2fb11ecc64 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 <ogoffart@woboq.com> ** Contact: https://www.qt.io/licensing/ ** @@ -79,9 +79,9 @@ struct QSignalSpyCallbackSet EndCallback signal_end_callback, slot_end_callback; }; -void Q_CORE_EXPORT qt_register_signal_spy_callbacks(const QSignalSpyCallbackSet &callback_set); +void Q_CORE_EXPORT qt_register_signal_spy_callbacks(QSignalSpyCallbackSet *callback_set); -extern QSignalSpyCallbackSet Q_CORE_EXPORT qt_signal_spy_callback_set; +extern Q_CORE_EXPORT QBasicAtomicPointer<QSignalSpyCallbackSet> qt_signal_spy_callback_set; enum { QObjectPrivateVersion = QT_VERSION }; @@ -124,54 +124,199 @@ 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 + ConnectionOrSignalVector *nextInOrphanList; + // linked list of connections connected to slots in this object + Connection *next; + }; + + static SignalVector *asSignalVector(ConnectionOrSignalVector *c) { + if (reinterpret_cast<quintptr>(c) & 1) + return reinterpret_cast<SignalVector *>(reinterpret_cast<quintptr>(c) & ~quintptr(1u)); + return nullptr; + } + static Connection *fromSignalVector(SignalVector *v) { + return reinterpret_cast<Connection *>(reinterpret_cast<quintptr>(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 + QAtomicPointer<Connection> nextConnectionList; + Connection *prevConnectionList; + QObject *sender; - QObject *receiver; + QAtomicPointer<QObject> receiver; + QAtomicPointer<QThreadData> receiverThreadData; union { StaticMetaCallFunction callFunction; QtPrivate::QSlotObjectBase *slotObj; }; - // The next pointer for the singly-linked ConnectionList - Connection *nextConnectionList; - //senders linked list - Connection *next; - Connection **prev; QAtomicPointer<const int> 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; - 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(); 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(!receiver.load()); + Q_ASSERT(!isSlotObject); delete this; } } }; // ConnectionList is a singly-linked list struct ConnectionList { - ConnectionList() : first(nullptr), last(nullptr) {} - Connection *first; - Connection *last; + QAtomicPointer<Connection> first; + QAtomicPointer<Connection> last; }; struct Sender { + Sender(QObject *receiver, QObject *sender, int signal) + : receiver(receiver), sender(sender), signal(signal) + { + if (receiver) { + ConnectionData *cd = receiver->d_func()->connections.load(); + previous = cd->currentSender; + cd->currentSender = this; + } + } + ~Sender() + { + if (receiver) + receiver->d_func()->connections.load()->currentSender = previous; + } + void receiverDeleted() + { + Sender *s = this; + while (s) { + s->receiver = nullptr; + s = s->previous; + } + } + Sender *previous; + QObject *receiver; QObject *sender; int signal; - int ref; }; + struct SignalVector : public ConnectionOrSignalVector { + quintptr allocated; + // ConnectionList signals[] + ConnectionList &at(int i) + { + return reinterpret_cast<ConnectionList *>(this + 1)[i + 1]; + } + const ConnectionList &at(int i) const + { + return reinterpret_cast<const ConnectionList *>(this + 1)[i + 1]; + } + int count() { return static_cast<int>(allocated); } + }; + + + + /* + This contains the all connections from and to an object. + + The signalVector contains the lists of connections for a given signal. The index in the vector correspond + to the signal index. The signal index is the one returned by QObjectPrivate::signalIndex (not + QMetaObject::indexOfSignal). allsignals contains a list of special connections that will get invoked on + any signal emission. This is done by connecting to signal index -1. + + This vector is protected by the object mutex (signalSlotLock()) + + Each Connection is also part of a 'senders' linked list. This one contains all connections connected + to a slot in this object. The mutex of the receiver must be locked when touching the pointers of this + linked list. + */ + struct ConnectionData { + // 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<uint> currentConnectionId; + QAtomicInt ref; + QAtomicPointer<SignalVector> signalVector; + Connection *senders = nullptr; + Sender *currentSender = nullptr; // object currently activating the object + QAtomicPointer<Connection> orphaned; + + ~ConnectionData() + { + deleteOrphaned(orphaned.load()); + 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); + void cleanOrphanedConnections(QObject *sender) + { + if (orphaned.load() && ref == 1) + cleanOrphanedConnectionsImpl(sender); + } + void cleanOrphanedConnectionsImpl(QObject *sender); + + ConnectionList &connectionsForSignal(int signal) + { + return signalVector.load()->at(signal); + } + + void resizeSignalVector(uint size) { + SignalVector *vector = this->signalVector.load(); + if (vector && vector->allocated > size) + return; + size = (size + 7) & ~7; + SignalVector *newVector = reinterpret_cast<SignalVector *>(malloc(sizeof(SignalVector) + (size + 1) * sizeof(ConnectionList))); + int start = -1; + if (vector) { + memcpy(newVector, vector, sizeof(SignalVector) + (vector->allocated + 1) * sizeof(ConnectionList)); + start = vector->count(); + } + for (int i = start; i < int(size); ++i) + 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.load()->count() : -1; + } + + static void deleteOrphaned(ConnectionOrSignalVector *c); + }; QObjectPrivate(int version = QObjectPrivateVersion); virtual ~QObjectPrivate(); @@ -187,13 +332,6 @@ public: QObjectList senderList() const; void addConnection(int signal, Connection *c); - void cleanConnectionLists(); - - static inline Sender *setCurrentSender(QObject *receiver, - Sender *sender); - static inline void resetCurrentSender(QObject *receiver, - Sender *currentSender, - Sender *previousSender); static QObjectPrivate *get(QObject *o) { return o->d_func(); @@ -201,7 +339,8 @@ public: static const QObjectPrivate *get(const QObject *o) { return o->d_func(); } int signalIndex(const char *signalName, const QMetaObject **meta = nullptr) const; - inline bool isSignalConnected(uint signalIdx, bool checkDeclarative = true) const; + bool isSignalConnected(uint signalIdx, bool checkDeclarative = true) const; + bool maybeSignalConnected(uint signalIndex) const; inline bool isDeclarativeSignalConnected(uint signalIdx) const; // To allow abitrary objects to call connectNotify()/disconnectNotify() without making @@ -224,15 +363,21 @@ public: const int *types, const QMetaObject *senderMetaObject); static QMetaObject::Connection connect(const QObject *sender, int signal_index, QtPrivate::QSlotObjectBase *slotObj, Qt::ConnectionType type); static bool disconnect(const QObject *sender, int signal_index, void **slot); + + void ensureConnectionData() + { + if (connections.load()) + return; + ConnectionData *cd = new ConnectionData; + cd->ref.ref(); + connections.store(cd); + } public: ExtraData *extraData; // extra data set by the user QThreadData *threadData; // id of the thread that owns the object - QObjectConnectionListVector *connectionLists; - - Connection *senders; // linked list of connections connected to this object - Sender *currentSender; // object currently activating the object - mutable quint32 connectedSignals[2]; + using ConnectionDataPointer = QExplicitlySharedDataPointer<ConnectionData>; + QAtomicPointer<ConnectionData> connections; union { QObject *currentChildBeingDeleted; // should only be used when QObjectData::isDeletingChildren is set @@ -246,47 +391,12 @@ public: Q_DECLARE_TYPEINFO(QObjectPrivate::ConnectionList, Q_MOVABLE_TYPE); -/*! \internal - - Returns \c true if the signal with index \a signal_index from object \a sender is connected. - Signals with indices above a certain range are always considered connected (see connectedSignals - in QObjectPrivate). - - \a signal_index must be the index returned by QObjectPrivate::signalIndex; -*/ -inline bool QObjectPrivate::isSignalConnected(uint signal_index, bool checkDeclarative) const -{ - return signal_index >= sizeof(connectedSignals) * 8 - || (connectedSignals[signal_index >> 5] & (1 << (signal_index & 0x1f)) - || (checkDeclarative && isDeclarativeSignalConnected(signal_index))); -} - inline bool QObjectPrivate::isDeclarativeSignalConnected(uint signal_index) const { return declarativeData && QAbstractDeclarativeData::isSignalConnected && QAbstractDeclarativeData::isSignalConnected(declarativeData, q_func(), signal_index); } -inline QObjectPrivate::Sender *QObjectPrivate::setCurrentSender(QObject *receiver, - Sender *sender) -{ - Sender *previousSender = receiver->d_func()->currentSender; - receiver->d_func()->currentSender = sender; - return previousSender; -} - -inline void QObjectPrivate::resetCurrentSender(QObject *receiver, - Sender *currentSender, - Sender *previousSender) -{ - // ref is set to zero when this object is deleted during the metacall - if (currentSender->ref == 1) - receiver->d_func()->currentSender = previousSender; - // if we've recursed, we need to tell the caller about the objects deletion - if (previousSender) - previousSender->ref = currentSender->ref; -} - inline void QObjectPrivate::connectNotify(const QMetaMethod &signal) { q_ptr->connectNotify(signal); @@ -372,7 +482,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, @@ -383,23 +512,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_; diff --git a/src/corelib/kernel/qobjectdefs.h b/src/corelib/kernel/qobjectdefs.h index d7ed2b0282..418b8cf1d2 100644 --- a/src/corelib/kernel/qobjectdefs.h +++ b/src/corelib/kernel/qobjectdefs.h @@ -64,11 +64,7 @@ class QString; // The following macros can be defined by tools that understand Qt // to have the information from the macro. #ifndef QT_ANNOTATE_CLASS -# ifndef Q_COMPILER_VARIADIC_MACROS -# define QT_ANNOTATE_CLASS(type, x) -# else -# define QT_ANNOTATE_CLASS(type, ...) -# endif +# define QT_ANNOTATE_CLASS(type, ...) #endif #ifndef QT_ANNOTATE_CLASS2 # define QT_ANNOTATE_CLASS2(type, a1, a2) @@ -105,11 +101,7 @@ class QString; #endif #define Q_PLUGIN_METADATA(x) QT_ANNOTATE_CLASS(qt_plugin_metadata, x) #define Q_INTERFACES(x) QT_ANNOTATE_CLASS(qt_interfaces, x) -#ifdef Q_COMPILER_VARIADIC_MACROS -# define Q_PROPERTY(...) QT_ANNOTATE_CLASS(qt_property, __VA_ARGS__) -#else -# define Q_PROPERTY(text) QT_ANNOTATE_CLASS(qt_property, text) -#endif +#define Q_PROPERTY(...) QT_ANNOTATE_CLASS(qt_property, __VA_ARGS__) #define Q_PRIVATE_PROPERTY(d, text) QT_ANNOTATE_CLASS2(qt_private_property, d, text) #ifndef Q_REVISION # define Q_REVISION(v) @@ -119,13 +111,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 +332,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; @@ -584,6 +576,7 @@ struct Q_CORE_EXPORT QMetaObject private: static bool invokeMethodImpl(QObject *object, QtPrivate::QSlotObjectBase *slot, Qt::ConnectionType type, void *ret); + friend class QTimer; }; class Q_CORE_EXPORT QMetaObject::Connection { @@ -605,8 +598,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/qppsattribute.cpp b/src/corelib/kernel/qppsattribute.cpp index 6be462edb5..166d590872 100644 --- a/src/corelib/kernel/qppsattribute.cpp +++ b/src/corelib/kernel/qppsattribute.cpp @@ -145,7 +145,6 @@ QPpsAttribute &QPpsAttribute::operator=(const QPpsAttribute &other) return *this; } -#ifdef Q_COMPILER_RVALUE_REFS QPpsAttribute::QPpsAttribute(QPpsAttribute &&other) : d(other.d) { other.d->type = QPpsAttribute::None; @@ -156,7 +155,6 @@ QPpsAttribute &QPpsAttribute::operator=(QPpsAttribute &&other) qSwap(d, other.d); return *this; } -#endif bool QPpsAttribute::operator==(const QPpsAttribute &other) const { diff --git a/src/corelib/kernel/qppsattribute_p.h b/src/corelib/kernel/qppsattribute_p.h index b59dcd5851..d6611cb675 100644 --- a/src/corelib/kernel/qppsattribute_p.h +++ b/src/corelib/kernel/qppsattribute_p.h @@ -96,10 +96,8 @@ public: bool operator==(const QPpsAttribute &other) const; bool operator!=(const QPpsAttribute &other) const; -#ifdef Q_COMPILER_RVALUE_REFS QPpsAttribute(QPpsAttribute &&other); QPpsAttribute &operator=(QPpsAttribute &&other); -#endif bool isValid() const; Type type() const; diff --git a/src/corelib/kernel/qsharedmemory_p.h b/src/corelib/kernel/qsharedmemory_p.h index 95fe0d1083..59802eb6ce 100644 --- a/src/corelib/kernel/qsharedmemory_p.h +++ b/src/corelib/kernel/qsharedmemory_p.h @@ -98,7 +98,7 @@ public: { if (q_sm && q_sm->lock()) return true; - q_sm = 0; + q_sm = nullptr; return false; } diff --git a/src/corelib/kernel/qtcore_eval.cpp b/src/corelib/kernel/qtcore_eval.cpp deleted file mode 100644 index 5437210699..0000000000 --- a/src/corelib/kernel/qtcore_eval.cpp +++ /dev/null @@ -1,560 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <qcoreevent.h> -#include <qdatetime.h> -#include <qlibraryinfo.h> -#include <qobject.h> -#include <qcoreapplication.h> -#include <private/qcoreapplication_p.h> - -#include "stdio.h" -#include "stdlib.h" - -QT_BEGIN_NAMESPACE - -#include "qconfig_eval.cpp" - -static const char boilerplate_supported_but_time_limited[] = - "\nQt %1 Evaluation License\n" - "Copyright (C) 2016 The Qt Company Ltd.\n" - "This trial version may only be used for evaluation purposes\n" - "and will shut down after 120 minutes.\n" - "Registered to:\n" - " Licensee: %2\n\n" - "The evaluation expires in %4 days\n\n" - "Contact http://www.qt.io/contact-us for pricing and purchasing information.\n"; - -static const char boilerplate_supported[] = - "\nQt %1 Evaluation License\n" - "Copyright (C) 2016 The Qt Company Ltd.\n" - "This trial version may only be used for evaluation purposes\n" - "Registered to:\n" - " Licensee: %2\n\n" - "The evaluation expires in %4 days\n\n" - "Contact http://www.qt.io/contact-us for pricing and purchasing information.\n"; - -static const char boilerplate_expired[] = - "This software is using the trial version of the Qt GUI toolkit.\n" - "The trial period has expired. If you need more time to\n" - "evaluate Qt, or if you have any questions about Qt, contact us\n" - "at: http://www.qt.io/contact-us.\n\n"; - -static const char will_shutdown_1min[] = - "\nThe evaluation of Qt will SHUT DOWN in 1 minute.\n" - "Contact http://www.qt.io/contact-us for pricing and purchasing information.\n"; - -static const char will_shutdown_now[] = - "\nThe evaluation of Qt has now reached its automatic\n" - "timeout and will shut down.\n" - "Contact http://www.qt.io/contact-us for pricing and purchasing information.\n"; - -enum EvaluationStatus { - EvaluationNotSupported = 0, - EvaluationSupportedButTimeLimited, - EvaluationSupported -}; - -static EvaluationStatus qt_eval_is_supported() -{ - const volatile char *const license_key = qt_eval_key_data + 12; - - // fast fail - if (!qt_eval_key_data[0] || !*license_key) - return EvaluationNotSupported; - - // is this an unsupported evaluation? - const volatile char *typecode = license_key; - int field = 2; - for ( ; field && *typecode; ++typecode) - if (*typecode == '-') - --field; - - if (!field && typecode[1] == '4' && typecode[2] == 'M') { - if (typecode[0] == 'Q') - return EvaluationSupportedButTimeLimited; - else if (typecode[0] == 'R' || typecode[0] == 'Z') - return EvaluationSupported; - } - return EvaluationNotSupported; -} - -static int qt_eval_days_left() -{ - const volatile char *const expiry_date = qt_eval_expiry_date + 12; - - QDate today = QDate::currentDate(); - QDate lastday = QDate::fromString( - QString::fromLatin1(const_cast<const char*>(expiry_date)), Qt::ISODate); - return today.daysTo(lastday); -} - -static bool qt_eval_is_expired() -{ - return qt_eval_days_left() < 0; -} - -static QString qt_eval_string() -{ - const char *msg; - switch (qt_eval_is_supported()) { - case EvaluationSupportedButTimeLimited: - msg = boilerplate_supported_but_time_limited; - break; - case EvaluationSupported: - msg = boilerplate_supported; - break; - default: - return QString(); - } - - return QString::fromLatin1(msg) - .arg(QLatin1String(QT_VERSION_STR)) - .arg(QLibraryInfo::licensee()) - .arg(qt_eval_days_left()); -} - -#define WARN_TIMEOUT 60 * 1000 * 119 -#define KILL_DELAY 60 * 1000 * 1 - -class QCoreFuriCuri : public QObject -{ -public: - - int warn; - int kill; - - QCoreFuriCuri() : QObject(), warn(-1), kill(-1) - { - if (qt_eval_is_supported() == EvaluationSupportedButTimeLimited) { - warn = startTimer(WARN_TIMEOUT); - kill = 0; - } - } - - void timerEvent(QTimerEvent *e) override { - if (e->timerId() == warn) { - killTimer(warn); - fprintf(stderr, "%s\n", will_shutdown_1min); - kill = startTimer(KILL_DELAY); - } else if (e->timerId() == kill) { - fprintf(stderr, "%s\n", will_shutdown_now); - QCoreApplication::instance()->quit(); - } - } -}; - -#if defined(QT_BUILD_CORE_LIB) || defined (QT_BOOTSTRAPPED) - -void qt_core_eval_init(QCoreApplicationPrivate::Type type) -{ - if (type != QCoreApplicationPrivate::Tty) - return; - - if (!qt_eval_is_supported()) - return; - - if (qt_eval_is_expired()) { - fprintf(stderr, "%s\n", boilerplate_expired); - exit(0); - } else { - fprintf(stderr, "%s\n", qPrintable(qt_eval_string())); - Q_UNUSED(new QCoreFuriCuri()); - } -} -#endif - -#ifdef QT_BUILD_WIDGETS_LIB - -QT_BEGIN_INCLUDE_NAMESPACE -#include <qdialog.h> -#include <qlabel.h> -#include <qlayout.h> -#include <qmessagebox.h> -#if QT_CONFIG(pushbutton) -#include <qpushbutton.h> -#endif -#include <qtimer.h> -#include <qapplication.h> -QT_END_INCLUDE_NAMESPACE - - -static const char * const qtlogo_eval_xpm[] = { -/* columns rows colors chars-per-pixel */ -"46 55 174 2", -" c #002E02", -". c #00370D", -"X c #003A0E", -"o c #003710", -"O c #013C13", -"+ c #043E1A", -"@ c #084F0A", -"# c #0B520C", -"$ c #054413", -"% c #0C4C17", -"& c #07421D", -"* c #09451D", -"= c #0D491E", -"- c #125515", -"; c #13541A", -": c #17591B", -"> c #1B5C1D", -", c #1F611F", -"< c #20621E", -"1 c #337B1E", -"2 c #0B4521", -"3 c #0F4923", -"4 c #114B24", -"5 c #154D2A", -"6 c #175323", -"7 c #1C5924", -"8 c #1C532F", -"9 c #1E5432", -"0 c #245936", -"q c #265938", -"w c #295C3B", -"e c #246324", -"r c #266823", -"t c #2A6C24", -"y c #276628", -"u c #2D7026", -"i c #327427", -"p c #367927", -"a c #37782A", -"s c #397C2A", -"d c #2E613E", -"f c #336C37", -"g c #2F6040", -"h c #356545", -"j c #3C6B4E", -"k c #3F6C51", -"l c #406E4F", -"z c #406D52", -"x c #477457", -"c c #497557", -"v c #4B7857", -"b c #517B5E", -"n c #3C8423", -"m c #3E812C", -"M c #53A61D", -"N c #41862C", -"B c #458A2D", -"V c #498F2D", -"C c #479324", -"Z c #489226", -"A c #4D952C", -"S c #478B30", -"D c #488C30", -"F c #4D9232", -"G c #509632", -"H c #549A33", -"J c #589F35", -"K c #56A526", -"L c #57A821", -"P c #5BAA27", -"I c #57A32A", -"U c #5CA72E", -"Y c #5DAB2A", -"T c #5CA336", -"R c #60AD2E", -"E c #63B12D", -"W c #65AF35", -"Q c #62A53F", -"! c #65AE39", -"~ c #66B036", -"^ c #6AB437", -"/ c #67B138", -"( c #6AB339", -") c #6DB838", -"_ c #70BA3C", -"` c #4D8545", -"' c #4E8942", -"] c #548851", -"[ c #6FAF4A", -"{ c #6DB243", -"} c #71B546", -"| c #70B840", -" . c #73B648", -".. c #79BA4E", -"X. c #7CBB53", -"o. c #598266", -"O. c #62886D", -"+. c #6A8F75", -"@. c #6B9173", -"#. c #70937A", -"$. c #799F79", -"%. c #7BAF66", -"&. c #81BD5B", -"*. c #85BF60", -"=. c #85AC7F", -"-. c #8DBA7B", -";. c #87C061", -":. c #8AC364", -">. c #8DC46A", -",. c #90C56E", -"<. c #93C771", -"1. c #96CA73", -"2. c #9ACB7C", -"3. c #9FD07D", -"4. c #779981", -"5. c #7F9F89", -"6. c #809F88", -"7. c #82A18B", -"8. c #86A192", -"9. c #8DA994", -"0. c #8FA998", -"q. c #94AF9B", -"w. c #97B991", -"e. c #97B19E", -"r. c #9DB6A3", -"t. c #A3BCA7", -"y. c #A6BCAB", -"u. c #A9BEB1", -"i. c #9ECD81", -"p. c #A2CF85", -"a. c #A5D284", -"s. c #A6D189", -"d. c #A9D28E", -"f. c #ABD491", -"g. c #B1D797", -"h. c #B1D699", -"j. c #B5D89E", -"k. c #ADC5AC", -"l. c #B1CAAE", -"z. c #B9DAA3", -"x. c #BDDDA8", -"c. c #ADC1B4", -"v. c #B2C6B6", -"b. c #B5C6BC", -"n. c #B6C9BA", -"m. c #BCD1BA", -"M. c #C6E1B4", -"N. c #CDE5BD", -"B. c #C2D2C6", -"V. c #CADEC2", -"C. c #C6D3CC", -"Z. c #C8D7CB", -"A. c #CEDAD2", -"S. c #D2DDD4", -"D. c #D3E9C6", -"F. c #D7EBC9", -"G. c #D9EBCD", -"H. c #DEEED4", -"J. c #D6E0D9", -"K. c #DAE4DC", -"L. c #E0EFD7", -"P. c #E5F2DD", -"I. c #DFE8E0", -"U. c #E4EBE5", -"Y. c #E9EFEA", -"T. c #EDF4EB", -"R. c #F0FAE6", -"E. c #F1F8EC", -"W. c #EDF0F0", -"Q. c #F4F7F3", -"!. c #F6F9F4", -"~. c #F8FAF7", -"^. c #FEFEFE", -"/. c None", -/* pixels */ -"/././././.c h ' Q / W _ &.p././././././././././././././././././././././././././././././././.", -"/././.4 O % Z ~ ~ W ~ W R U R R ( X.>.p././././././././././././././././././././././././././.", -"/./.. * = J _ ~ ~ ~ ~ ~ / / / / W W U P P U W .;.2././././././././././././././././././././.", -"/.= = & a ) W ~ ~ ~ ~ ~ / W / ~ ~ ~ ^ ( ( ^ ~ R R U P Y ~ .;.2././././././././././././././.", -"O.O = = T ^ W ~ ~ ~ ~ ~ ~ W W / W ~ ~ ~ ~ ~ ~ ~ ( ( ( ( ~ W Y Y Y Y W { &.1././././././././.", -"0 = * 7 ~ ~ ~ ~ ~ ~ ~ ~ ~ / / W ~ ~ ~ ~ ~ ~ ~ ~ W W W ~ ~ ~ ~ ( ( ( W W R U P U W { X.1.f./.", -"= = & e ^ W ~ ~ ~ ~ ~ ~ ~ ~ / / ~ ~ ~ ~ ~ ~ ~ ~ W ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ^ ( ( / ~ W R U U Y ", -"= = & e ^ W ~ ~ ~ ~ ~ ~ ~ ~ W W ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ W ( W ~ ~ ~ ^ ^ ( ", -"= = * e ^ W ~ ~ ~ ~ ~ ~ / W / W ! ( / ~ W ^ ( ( ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ W ~ W W ~ ~ ~ ~ ~ ~ ", -"= = & e ^ ! ~ ~ ~ ~ ~ ~ W W ^ _ ~ K Y W W R P Y W ( ~ ~ ~ ~ ~ ~ ~ W / ~ ~ ~ ^ W ~ ~ ~ ~ ~ ~ ", -"= = & e ^ W ~ ~ ~ ~ ~ ~ W ) W 1 ` w.V.L.H.D.z.,.~ Y ^ ~ ~ ~ ~ ~ W ~ ~ ~ ( ~ W W ~ ~ ~ ~ ~ ~ ", -"= = & e ^ W ~ ~ ~ ~ ~ W ) V = 8.~.^.^.^.^.^.^.^.U.<.Y ~ ~ ~ ~ ~ W W ! ~ Y W ^ W ~ ~ ~ ~ ~ ~ ", -"= = & e ^ W ~ ~ ~ ~ W ^ B O u.^.~.^.^.^.^.~.~.^.^.^.h.Y ^ ~ ~ ^ F $ k.R.G.1.Y / ~ ~ ~ ~ ~ ~ ", -"= = & e ^ ~ ~ ~ / W ( J X 7.^.~.^.^.^.^.^.^.^.^.^.^.^.s.Y / W ) a 2 U.^.^.d.U ( ~ ~ ~ ~ ~ ~ ", -"= = & e ^ W / ~ ~ ~ ^ > w ~.^.^.^.^.^.F.%.v c.^.^.^.^.~.X.W ~ ^ > h ^.^.^.d.P ( ~ ~ ~ ~ ~ ~ ", -"= = & e ^ W ~ ~ W ^ H o e.^.^.^.^.^.G.Y E n . y.^.^.^.^.M.Y ( ! $ @.^.~.^.f.U ( / ~ ~ W ~ ~ ", -"= = & e ^ W ~ W ! ) t 4 U.^.^.^.^.^.>.U ( _ , 9 ~.^.^.^.~...^ A y.^.~.^.s.M W Y ~ ~ ~ ~ ~ ", -"= 3 & e ^ W ~ ( ^ ( $ c ^.^.^.^.^.E.) ~ ~ ^ S o n.^.^.^.^.=.- l.v.Y.^.^.^.M.:.:.X.~ ~ ~ ~ ~ ", -"= = & e ^ ! W W ( J X 7.^.^.^.^.^.F.Y ( W ^ T X 6.^.^.~.^.c.. J.^.^.^.^.^.^.^.^.P.~ ~ ~ ~ ~ ", -"= = & r ^ W / W ) B o v.^.~.^.^.^.M.U / ~ ~ ! $ o.^.^.^.^.K.* S.^.^.^.^.^.^.^.^.P.~ ~ ~ ~ ~ ", -"= = & e ^ ! ~ W ) a + S.^.^.^.^.^.z.P ( W ~ ( % z ^.^.^.^.~.f t.U.^.^.^.^.~.^.^.P.~ ~ ~ ~ ~ ", -"* = & e ^ W ~ W ) t 3 Y.^.^.^.^.^.f.P ( ~ ~ ^ ; h ^.^.^.^.^.:.@ j ^.^.^.^.h.{ X.&.~ ~ ~ ~ ~ ", -"3 = & e ^ W ~ ~ ^ e 8 Q.^.^.^.^.^.s.P ~ ~ W ^ > 0 ~.^.^.^.^.1.# z ^.^.^.^.d.L W R ~ ~ ~ ~ ~ ", -"= = & e ^ W ~ ~ ^ > q ~.^.^.^.^.^.p.U ^ ~ W ) e 9 ~.^.^.^.^.3.# k ^.^.^.^.f.Y ( / ~ ~ ~ ~ ~ ", -"= = & e ^ W / W ^ > w ~.^.^.^.^.^.i.Y / ~ W ^ e 8 Q.^.^.^.^.a.# z ^.^.^.^.f.Y / ~ ~ ~ ~ ~ ~ ", -"= = & e ^ W / W ^ > w ^.^.^.^.^.^.2.Y / ~ ~ ) e 8 Q.^.^.^.^.s.# z ^.^.^.^.d.P ( ~ ~ ~ ~ ~ ~ ", -"= = & e ^ W W W ^ > q ^.^.^.^.^.^.p.Y / ~ ~ ^ e 9 Q.^.^.^.^.a.@ z ^.^.^.^.f.U / ~ ~ ~ ~ ~ ~ ", -"= = & e ^ W / W ) 7 9 Q.^.^.^.^.^.a.P / ~ W ) , 9 Q.^.^.^.^.3.# z ^.^.~.^.f.P ^ ~ ~ ~ ~ ~ ~ ", -"= = & e ^ W / W ) r 5 T.^.^.^.^.^.d.Y / ~ W ) > q ~.^.^.^.^.1.# k ^.^.^.^.f.Y ( ~ ~ ~ ~ ~ ~ ", -"= = & e ^ / / W ) i 2 I.^.^.^.^.^.h.P ( ~ W ( > g ^.^.^.^.^.:.# z ^.^.^.^.f.P / ~ ~ ~ ~ ~ ~ ", -"= = & e ( W / W ) m O Z.^.^.^.^.^.x.P / ~ ~ ( ; j ^.^.^.^.~.&.- k ^.^.~.^.f.P / ~ ~ ~ ~ ~ ~ ", -"= = & e ( W / W ) F o y.^.~.^.^.^.N.U ( ~ ~ W $ b ^.^.^.^.R._ - k ^.^.^.^.f.Y ( ~ ~ ~ ~ ~ ~ ", -"= = & e ^ W ~ ~ ^ J X 4.^.^.^.^.^.L.~ ~ W ^ T X #.^.^.^.^.F.~ ; j ^.^.^.^.f.U ( ~ ~ ~ ~ ~ ~ ", -"= = & e ^ ~ ~ ~ / ^ % l ^.^.^.^.^.!. .R ^ ^ G . r.^.~.^.^.j.E : j ^.^.^.^.f.P ) ( ~ ~ ~ ~ ~ ", -"= = & e ^ W ~ ~ W ) u = U.^.^.^.^.^.1.Y ! ) a & K.^.^.^.^.;.~ : j ^.^.~.^.z.M I I / ~ ~ W ~ ", -"= = & e ( W ~ ~ W ( G . q.^.^.^.^.^.D.U ^ ! X o.^.^.^.^.P.~ ^ > g ^.^.^.^.E.-.$.m.X.W ~ ~ ~ ", -"= = & e ^ / ~ ~ ^ ! ( > w ~.^.^.^.^.^.h.T > j T.^.^.~.^.a.Y _ i 3 U.^.^.^.^.^.^.^.X.R ~ ~ ~ ", -"= = & e ^ / ~ ~ W W ^ H . 9.^.~.^.^.^.^.K.C.~.^.^.^.^.H.W W ^ T . q.^.~.^.^.^.^.^.X.R ~ ~ ~ ", -"= = + e ^ W / ~ W W W ) m + B.^.~.^.^.^.^.^.^.^.^.^.E.X.Y ( W ^ B 6 y.^.^.^.E.D.2.( ~ ~ ~ ~ ", -"= = * e ^ ! / ! W ^ W W ) a 4 b.^.^.^.^.^.^.^.^.^.P...Y ( ! W ! ^ W Z [ *.X.{ Y U ~ ~ ~ ~ ~ ", -"= = & e ( W ~ ~ W / W / W ) A < +.A.~.^.^.^.^.!.p.W R ~ ~ ~ ~ ~ W / ) E U W W / ^ ~ ~ ~ ~ ~ ", -"= = & e ^ W ~ ~ / W / / / W ( _ Z X 6.^.^.^.^.E.W ~ ^ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ / ~ ~ ~ ~ ~ ~ ~ ~ ", -"= = & e ^ ~ ~ ~ W W / W ~ ~ ~ ~ ) ; h ^.^.^.^.^.d.M U ~ / ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ W ", -"= = & e ^ W ~ ~ ^ W W / ~ ~ ~ W ) p + S.^.^.^.^.~.M.f. .W ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ .", -"= = & e ^ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ W ( T O +.^.~.^.^.^.^.^.&.Y ( ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ W ( Y 2.", -"= = & e ( W ~ ~ ~ ~ ~ ~ ~ ~ ~ / W ) N + b.^.^.^.^.^.^.&.R ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ W /.", -"= = & e ^ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ W ^ N 7 r.W.^.^.^.!.X.W ~ ~ W ~ W ~ ~ ~ ~ ~ ~ / ( ( K p./.", -"= = & e ( W ~ ~ W ~ ~ ~ ~ ~ ~ ~ ~ ~ W ( W C Q &.:.X.| ~ ~ ~ ~ W ~ / ~ ( / ( ~ W E U P 1././.", -"= = + e ^ / / / ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ W / ) ^ R Y W W ~ ~ ( / ( / W R Y Y U R ( X.,././././.", -"= = * e ( / ~ / ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ W W W ! ( ( ( W W E U P Y W ( X.,.d./././././././././.", -"= = * e ( W ~ ~ ~ ~ W ! ~ W ~ W ~ ( ( / ^ W W U Y P W ( X.,.d./././././././././././././././.", -"8 $ * e ( W ~ ~ ~ ! ( ( ( / ( W R Y Y Y R ( X.>.d./././././././././././././././././././././.", -"/.d . y ^ / / / ( W Y Y P P W ( X.>.d./././././././././././././././././././././././././././.", -"/./.h : ^ R R R W ( X.<.f./././././././././././././././././././././././././././././././././.", -"/././.] _ *.3./././././././././././././././././././././././././././././././././././././././." -}; - -class EvalMessageBox : public QDialog -{ -public: - EvalMessageBox(bool expired) - { - setWindowTitle(QLatin1String(" ")); - - QString str = expired ? QLatin1String(boilerplate_expired) : qt_eval_string(); - str = str.trimmed(); - - QFrame *border = new QFrame(this); - - QLabel *pixmap_label = new QLabel(border); - pixmap_label->setPixmap(QPixmap(qtlogo_eval_xpm)); - pixmap_label->setAlignment(Qt::AlignTop); - - QLabel *text_label = new QLabel(str, border); - - QHBoxLayout *pm_and_text_layout = new QHBoxLayout(); - pm_and_text_layout->addWidget(pixmap_label); - pm_and_text_layout->addWidget(text_label); - - QVBoxLayout *master_layout = new QVBoxLayout(border); - master_layout->addLayout(pm_and_text_layout); - - QVBoxLayout *border_layout = new QVBoxLayout(this); - border_layout->setMargin(0); - border_layout->addWidget(border); - - if (expired) { - QPushButton *cmd = new QPushButton(QLatin1String("OK"), border); - cmd->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); - cmd->setDefault(true); - - QHBoxLayout *button_layout = new QHBoxLayout(); - master_layout->addLayout(button_layout); - button_layout->addWidget(cmd); - - connect(cmd, SIGNAL(clicked()), this, SLOT(close())); - } else { - border->setFrameShape(QFrame::WinPanel); - border->setFrameShadow(QFrame::Raised); - setParent(parentWidget(), Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint); - QTimer::singleShot(7000, this, SLOT(close())); - setAttribute(Qt::WA_DeleteOnClose); - setAttribute(Qt::WA_QuitOnClose, false); - } - - setFixedSize(sizeHint()); - } -}; - -class QGuiFuriCuri : public QCoreFuriCuri -{ -public: - void timerEvent(QTimerEvent *e) { - if (e->timerId() == warn) { - killTimer(warn); - QMessageBox::information(0, QLatin1String("Automatic Timeout"), QLatin1String(will_shutdown_1min)); - kill = startTimer(KILL_DELAY); - } else if (e->timerId() == kill) { - killTimer(kill); - QMessageBox::information(0, QLatin1String("Automatic Timeout"), QLatin1String(will_shutdown_now)); - qApp->quit(); - } - } -}; - - -void qt_gui_eval_init(QCoreApplicationPrivate::Type type) -{ - Q_UNUSED(type); - - if (!qt_eval_is_supported()) - return; - - if (qt_eval_is_expired()) { - EvalMessageBox box(true); - box.exec(); - ::exit(0); - } else { - Q_UNUSED(new QGuiFuriCuri()); - } -} - -static QString qt_eval_title_prefix() -{ - return QLatin1String("[Qt Evaluation] "); -} - -QString qt_eval_adapt_window_title(const QString &title) -{ - if (!qt_eval_is_supported()) - return title; - return qt_eval_title_prefix() + title; -} - -void qt_eval_init_widget(QWidget *w) -{ - if (!qt_eval_is_supported()) - return; - if (w->isTopLevel() && w->windowTitle().isEmpty() && w->windowType() != Qt::Desktop ) { - w->setWindowTitle(QLatin1String(" ")); - } -} -#endif - -QT_END_NAMESPACE 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; diff --git a/src/corelib/kernel/qtimer.cpp b/src/corelib/kernel/qtimer.cpp index 13f027074a..188d529f04 100644 --- a/src/corelib/kernel/qtimer.cpp +++ b/src/corelib/kernel/qtimer.cpp @@ -42,6 +42,8 @@ #include "qabstracteventdispatcher.h" #include "qcoreapplication.h" #include "qobject_p.h" +#include "qthread.h" +#include "qcoreapplication_p.h" QT_BEGIN_NAMESPACE @@ -343,6 +345,33 @@ void QTimer::singleShotImpl(int msec, Qt::TimerType timerType, const QObject *receiver, QtPrivate::QSlotObjectBase *slotObj) { + if (msec == 0) { + bool deleteReceiver = false; + // Optimize: set a receiver context when none is given, such that we can use + // QMetaObject::invokeMethod which is more efficient than going through a timer. + // We need a QObject living in the current thread. But the QThread itself lives + // in a different thread - with the exception of the main QThread which lives in + // itself. And QThread::currentThread() is among the few QObjects we know that will + // most certainly be there. Note that one can actually call singleShot before the + // QApplication is created! + if (!receiver && QThread::currentThread() == QCoreApplicationPrivate::mainThread()) { + // reuse main thread as context object + receiver = QThread::currentThread(); + } else if (!receiver) { + // Create a receiver context object on-demand. According to the benchmarks, + // this is still more efficient than going through a timer. + receiver = new QObject; + deleteReceiver = true; + } + + QMetaObject::invokeMethodImpl(const_cast<QObject *>(receiver), slotObj, + Qt::QueuedConnection, nullptr); + + if (deleteReceiver) + const_cast<QObject *>(receiver)->deleteLater(); + return; + } + new QSingleShotTimer(msec, timerType, receiver, slotObj); } 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.cpp b/src/corelib/kernel/qvariant.cpp index 18c7f7648d..cd4e233af0 100644 --- a/src/corelib/kernel/qvariant.cpp +++ b/src/corelib/kernel/qvariant.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2019 The Qt Company Ltd. ** Copyright (C) 2018 Intel Corporation. ** Copyright (C) 2015 Olivier Goffart <ogoffart@woboq.com> ** Contact: https://www.qt.io/licensing/ @@ -1462,6 +1462,7 @@ static void customConstruct(QVariant::Private *d, const void *copy) if (size <= sizeof(QVariant::Private::Data) && (type.flags() & (QMetaType::MovableType | QMetaType::IsEnumeration))) { type.construct(&d->data.ptr, copy); + d->is_null = d->data.ptr == nullptr; d->is_shared = false; } else { // Private::Data contains long long, and long double is the biggest standard type. @@ -1472,6 +1473,7 @@ static void customConstruct(QVariant::Private *d, const void *copy) void *data = operator new(offset + size); void *ptr = static_cast<char *>(data) + offset; type.construct(ptr, copy); + d->is_null = ptr == nullptr; d->is_shared = true; d->data.shared = new (data) QVariant::PrivateShared(ptr); } @@ -4002,8 +4004,8 @@ static int numericCompare(const QVariant::Private *d1, const QVariant::Private * return 0; // only do fuzzy comparisons for finite, non-zero numbers - int c1 = std::fpclassify(r1); - int c2 = std::fpclassify(r2); + int c1 = qFpClassify(r1); + int c2 = qFpClassify(r2); if ((c1 == FP_NORMAL || c1 == FP_SUBNORMAL) && (c2 == FP_NORMAL || c2 == FP_SUBNORMAL)) { if (qFuzzyCompare(r1, r2)) return 0; @@ -4280,6 +4282,7 @@ QDebug operator<<(QDebug dbg, const QVariant::Type p) \sa fromValue() */ +#if QT_DEPRECATED_SINCE(5, 14) /*! \fn template<typename T> QVariant qVariantFromValue(const T &value) \relates QVariant @@ -4317,6 +4320,7 @@ QDebug operator<<(QDebug dbg, const QVariant::Type p) \sa QVariant::setValue() */ +#endif /*! \fn template<typename T> T qvariant_cast(const QVariant &value) diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h index f95502e75f..2247c7adc8 100644 --- a/src/corelib/kernel/qvariant.h +++ b/src/corelib/kernel/qvariant.h @@ -92,9 +92,6 @@ class QUrl; class QVariant; class QVariantComparisonHelper; -template <typename T> -inline QVariant qVariantFromValue(const T &); - template<typename T> inline T qvariant_cast(const QVariant &); @@ -204,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); @@ -270,14 +267,12 @@ class Q_CORE_EXPORT QVariant #endif 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; @@ -365,7 +360,7 @@ class Q_CORE_EXPORT QVariant template<typename T> static inline QVariant fromValue(const T &value) - { return qVariantFromValue(value); } + { return QVariant(qMetaTypeId<T>(), &value, QTypeInfo<T>::isPointer); } #if QT_HAS_INCLUDE(<variant>) && __cplusplus >= 201703L template<typename... Types> @@ -390,15 +385,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) {} @@ -516,50 +511,61 @@ public: inline const DataPtr &data_ptr() const { return d; } }; +#if QT_DEPRECATED_SINCE(5, 14) template <typename T> +QT_DEPRECATED_X("Use QVariant::fromValue() instead.") inline QVariant qVariantFromValue(const T &t) { - return QVariant(qMetaTypeId<T>(), &t, QTypeInfo<T>::isPointer); + return QVariant::fromValue(t); +} + +template <typename T> +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(<variant>) && __cplusplus >= 201703L -template <> -inline QVariant qVariantFromValue(const std::monostate &) { return QVariant(); } +template<> +inline QVariant QVariant::fromValue(const std::monostate &) +{ + return QVariant(); +} #endif -template <typename T> -inline void qVariantSetValue(QVariant &v, const T &t) +inline bool QVariant::isValid() const { return d.type != Invalid; } + +template<typename T> +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<T>(); - 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<T*>(d.is_shared ? d.data.shared->ptr : &d.data.ptr); if (QTypeInfo<T>::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<T>::isPointer); + *this = QVariant(type, &avalue, QTypeInfo<T>::isPointer); } } -template <> -inline void qVariantSetValue<QVariant>(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<typename T> -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); diff --git a/src/corelib/kernel/qvariant_p.h b/src/corelib/kernel/qvariant_p.h index b22b7c231e..3d87beac83 100644 --- a/src/corelib/kernel/qvariant_p.h +++ b/src/corelib/kernel/qvariant_p.h @@ -88,7 +88,7 @@ inline T *v_cast(const QVariant::Private *nd, T * = 0) #else // every other compiler in this world template <typename T> -inline const T *v_cast(const QVariant::Private *d, T * = 0) +inline const T *v_cast(const QVariant::Private *d, T * = nullptr) { return !QVariantIntegrator<T>::CanUseInternalSpace ? static_cast<const T *>(d->data.shared->ptr) @@ -96,7 +96,7 @@ inline const T *v_cast(const QVariant::Private *d, T * = 0) } template <typename T> -inline T *v_cast(QVariant::Private *d, T * = 0) +inline T *v_cast(QVariant::Private *d, T * = nullptr) { return !QVariantIntegrator<T>::CanUseInternalSpace ? static_cast<T *>(d->data.shared->ptr) @@ -154,7 +154,7 @@ inline void v_construct(QVariant::Private *x, const T &t) // constructs a new variant if copy is 0, otherwise copy-constructs template <class T> -inline void v_construct(QVariant::Private *x, const void *copy, T * = 0) +inline void v_construct(QVariant::Private *x, const void *copy, T * = nullptr) { if (copy) v_construct<T>(x, *static_cast<const T *>(copy)); @@ -164,7 +164,7 @@ inline void v_construct(QVariant::Private *x, const void *copy, T * = 0) // deletes the internal structures template <class T> -inline void v_clear(QVariant::Private *d, T* = 0) +inline void v_clear(QVariant::Private *d, T* = nullptr) { if (!QVariantIntegrator<T>::CanUseInternalSpace) { @@ -264,7 +264,7 @@ class QVariantIsNull struct No { char unused[2]; }; Q_STATIC_ASSERT(sizeof(Yes) != sizeof(No)); - template<class C> static decltype(static_cast<const C*>(0)->isNull(), Yes()) test(int); + template<class C> static decltype(static_cast<const C*>(nullptr)->isNull(), Yes()) test(int); template<class C> static No test(...); public: static const bool Value = (sizeof(test<T>(0)) == sizeof(Yes)); |