summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/kernel')
-rw-r--r--src/corelib/kernel/qabstracteventdispatcher.cpp2
-rw-r--r--src/corelib/kernel/qcore_unix_p.h2
-rw-r--r--src/corelib/kernel/qcoreapplication.cpp4
-rw-r--r--src/corelib/kernel/qcoreevent.cpp8
-rw-r--r--src/corelib/kernel/qcoreevent.h2
-rw-r--r--src/corelib/kernel/qdeadlinetimer.cpp24
-rw-r--r--src/corelib/kernel/qdeadlinetimer.h50
-rw-r--r--src/corelib/kernel/qelapsedtimer.cpp6
-rw-r--r--src/corelib/kernel/qelapsedtimer.h30
-rw-r--r--src/corelib/kernel/qelapsedtimer_generic.cpp22
-rw-r--r--src/corelib/kernel/qelapsedtimer_mac.cpp24
-rw-r--r--src/corelib/kernel/qelapsedtimer_unix.cpp24
-rw-r--r--src/corelib/kernel/qelapsedtimer_win.cpp22
-rw-r--r--src/corelib/kernel/qeventdispatcher_unix_p.h12
-rw-r--r--src/corelib/kernel/qfunctions_fake_env_p.h4
-rw-r--r--src/corelib/kernel/qmetaobject.cpp6
-rw-r--r--src/corelib/kernel/qmetaobject_p.h2
-rw-r--r--src/corelib/kernel/qmetatype.cpp2
-rw-r--r--src/corelib/kernel/qobject.cpp546
-rw-r--r--src/corelib/kernel/qobject.h32
-rw-r--r--src/corelib/kernel/qobject_p.h172
-rw-r--r--src/corelib/kernel/qobjectdefs.h14
-rw-r--r--src/corelib/kernel/qobjectdefs_impl.h4
-rw-r--r--src/corelib/kernel/qsignalmapper.cpp2
-rw-r--r--src/corelib/kernel/qtestsupport_core.cpp2
-rw-r--r--src/corelib/kernel/qtimer.h2
-rw-r--r--src/corelib/kernel/qtranslator.cpp3
-rw-r--r--src/corelib/kernel/qvariant.cpp2
-rw-r--r--src/corelib/kernel/qvariant.h72
29 files changed, 635 insertions, 462 deletions
diff --git a/src/corelib/kernel/qabstracteventdispatcher.cpp b/src/corelib/kernel/qabstracteventdispatcher.cpp
index 0ecfc7a8c7..186c2e743b 100644
--- a/src/corelib/kernel/qabstracteventdispatcher.cpp
+++ b/src/corelib/kernel/qabstracteventdispatcher.cpp
@@ -162,7 +162,7 @@ QAbstractEventDispatcher::~QAbstractEventDispatcher()
Returns a pointer to the event dispatcher object for the specified
\a thread. If \a thread is zero, the current thread is used. If no
event dispatcher exists for the specified thread, this function
- returns 0.
+ returns \nullptr.
\b{Note:} If Qt is built without thread support, the \a thread
argument is ignored.
diff --git a/src/corelib/kernel/qcore_unix_p.h b/src/corelib/kernel/qcore_unix_p.h
index 32ef6408c2..7f58813535 100644
--- a/src/corelib/kernel/qcore_unix_p.h
+++ b/src/corelib/kernel/qcore_unix_p.h
@@ -347,7 +347,7 @@ static inline pid_t qt_safe_waitpid(pid_t pid, int *status, int options)
#endif
// in qelapsedtimer_mac.cpp or qtimestamp_unix.cpp
-timespec qt_gettime() Q_DECL_NOTHROW;
+timespec qt_gettime() noexcept;
void qt_nanosleep(timespec amount);
QByteArray qt_readlink(const char *path);
diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp
index 5da33a5aae..4100fad28e 100644
--- a/src/corelib/kernel/qcoreapplication.cpp
+++ b/src/corelib/kernel/qcoreapplication.cpp
@@ -369,7 +369,7 @@ uint QCoreApplicationPrivate::attribs =
(1 << Qt::AA_SynthesizeMouseForUnhandledTabletEvents);
struct QCoreApplicationData {
- QCoreApplicationData() Q_DECL_NOTHROW {
+ QCoreApplicationData() noexcept {
applicationNameSet = false;
applicationVersionSet = false;
}
@@ -2917,7 +2917,7 @@ bool QCoreApplication::hasPendingEvents()
/*!
Returns a pointer to the event dispatcher object for the main thread. If no
- event dispatcher exists for the thread, this function returns 0.
+ event dispatcher exists for the thread, this function returns \nullptr.
*/
QAbstractEventDispatcher *QCoreApplication::eventDispatcher()
{
diff --git a/src/corelib/kernel/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_unix_p.h b/src/corelib/kernel/qeventdispatcher_unix_p.h
index 8cfa4bbdf7..f37edfc967 100644
--- a/src/corelib/kernel/qeventdispatcher_unix_p.h
+++ b/src/corelib/kernel/qeventdispatcher_unix_p.h
@@ -64,10 +64,10 @@ class QEventDispatcherUNIXPrivate;
struct Q_CORE_EXPORT QSocketNotifierSetUNIX final
{
- inline QSocketNotifierSetUNIX() Q_DECL_NOTHROW;
+ inline QSocketNotifierSetUNIX() noexcept;
- inline bool isEmpty() const Q_DECL_NOTHROW;
- inline short events() const Q_DECL_NOTHROW;
+ inline bool isEmpty() const noexcept;
+ inline short events() const noexcept;
QSocketNotifier *notifiers[3];
};
@@ -150,19 +150,19 @@ public:
QAtomicInt interrupt; // bool
};
-inline QSocketNotifierSetUNIX::QSocketNotifierSetUNIX() Q_DECL_NOTHROW
+inline QSocketNotifierSetUNIX::QSocketNotifierSetUNIX() noexcept
{
notifiers[0] = nullptr;
notifiers[1] = nullptr;
notifiers[2] = nullptr;
}
-inline bool QSocketNotifierSetUNIX::isEmpty() const Q_DECL_NOTHROW
+inline bool QSocketNotifierSetUNIX::isEmpty() const noexcept
{
return !notifiers[0] && !notifiers[1] && !notifiers[2];
}
-inline short QSocketNotifierSetUNIX::events() const Q_DECL_NOTHROW
+inline short QSocketNotifierSetUNIX::events() const noexcept
{
short result = 0;
diff --git a/src/corelib/kernel/qfunctions_fake_env_p.h b/src/corelib/kernel/qfunctions_fake_env_p.h
index 7010d2cf5d..68d17ed4a1 100644
--- a/src/corelib/kernel/qfunctions_fake_env_p.h
+++ b/src/corelib/kernel/qfunctions_fake_env_p.h
@@ -72,8 +72,8 @@ Q_DECLARE_TYPEINFO(Variable, Q_MOVABLE_TYPE);
struct NameEquals {
typedef bool result_type;
const char *name;
- explicit NameEquals(const char *name) Q_DECL_NOTHROW : name(name) {}
- result_type operator()(const Variable &other) const Q_DECL_NOTHROW
+ explicit NameEquals(const char *name) noexcept : name(name) {}
+ result_type operator()(const Variable &other) const noexcept
{ return qstrcmp(other.name, name) == 0; }
};
diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp
index 8309bd22c2..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 {
@@ -349,7 +349,7 @@ bool QMetaObject::inherits(const QMetaObject *metaObject) const Q_DECL_NOEXCEPT
\internal
Returns \a obj if object \a obj inherits from this
- meta-object; otherwise returns 0.
+ meta-object; otherwise returns \nullptr.
*/
QObject *QMetaObject::cast(QObject *obj) const
{
@@ -361,7 +361,7 @@ QObject *QMetaObject::cast(QObject *obj) const
\internal
Returns \a obj if object \a obj inherits from this
- meta-object; otherwise returns 0.
+ meta-object; otherwise returns \nullptr.
*/
const QObject *QMetaObject::cast(const QObject *obj) const
{
diff --git a/src/corelib/kernel/qmetaobject_p.h b/src/corelib/kernel/qmetaobject_p.h
index 26d86fdf14..0cd9da2eac 100644
--- a/src/corelib/kernel/qmetaobject_p.h
+++ b/src/corelib/kernel/qmetaobject_p.h
@@ -232,7 +232,7 @@ struct QMetaObjectPrivate
const QMetaObject *smeta,
const QObject *receiver, int method_index, void **slot,
DisconnectType = DisconnectAll);
- static inline bool disconnectHelper(QObjectPrivate::Connection *c,
+ static inline bool disconnectHelper(QObjectPrivate::ConnectionData *connections, int signalIndex,
const QObject *receiver, int method_index, void **slot,
QBasicMutex *senderMutex, DisconnectType = DisconnectAll);
#endif
diff --git a/src/corelib/kernel/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 268f3949fd..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/
@@ -265,13 +265,13 @@ bool QObjectPrivate::isSender(const QObject *receiver, const char *signal) const
if (signal_index < 0 || !cd)
return false;
QBasicMutexLocker locker(signalSlotLock(q));
- if (signal_index < cd->signalVector.count()) {
- const QObjectPrivate::Connection *c = cd->signalVector.at(signal_index).first;
+ if (signal_index < cd->signalVectorCount()) {
+ const QObjectPrivate::Connection *c = cd->signalVector.load()->at(signal_index).first.load();
while (c) {
- if (c->receiver == receiver)
+ if (c->receiver.load() == receiver)
return true;
- c = c->nextConnectionList;
+ c = c->nextConnectionList.load();
}
}
return false;
@@ -280,20 +280,19 @@ bool QObjectPrivate::isSender(const QObject *receiver, const char *signal) const
// Used by QAccessibleWidget
QObjectList QObjectPrivate::receiverList(const char *signal) const
{
- Q_Q(const QObject);
QObjectList returnValue;
int signal_index = signalIndex(signal);
ConnectionData *cd = connections.load();
if (signal_index < 0 || !cd)
return returnValue;
- QBasicMutexLocker locker(signalSlotLock(q));
- if (signal_index < cd->signalVector.count()) {
- const QObjectPrivate::Connection *c = cd->signalVector.at(signal_index).first;
+ if (signal_index < cd->signalVectorCount()) {
+ const QObjectPrivate::Connection *c = cd->signalVector.load()->at(signal_index).first.load();
while (c) {
- if (c->receiver)
- returnValue << c->receiver;
- c = c->nextConnectionList;
+ QObject *r = c->receiver.load();
+ if (r)
+ returnValue << r;
+ c = c->nextConnectionList.load();
}
}
return returnValue;
@@ -327,20 +326,20 @@ void QObjectPrivate::addConnection(int signal, Connection *c)
Q_ASSERT(c->sender == q_ptr);
ensureConnectionData();
ConnectionData *cd = connections.load();
- if (signal >= cd->signalVector.count())
- cd->signalVector.resize(signal + 1);
+ cd->resizeSignalVector(signal + 1);
ConnectionList &connectionList = cd->connectionsForSignal(signal);
- if (connectionList.last) {
- connectionList.last->nextConnectionList = c;
+ if (connectionList.last.load()) {
+ Q_ASSERT(connectionList.last.load()->receiver.load());
+ connectionList.last.load()->nextConnectionList.store(c);
} else {
- connectionList.first = c;
+ connectionList.first.store(c);
}
- connectionList.last = c;
+ c->id = ++cd->currentConnectionId;
+ c->prevConnectionList = connectionList.last.load();
+ connectionList.last.store(c);
- cleanConnectionLists();
-
- QObjectPrivate *rd = QObjectPrivate::get(c->receiver);
+ QObjectPrivate *rd = QObjectPrivate::get(c->receiver.load());
rd->ensureConnectionData();
c->prev = &(rd->connections.load()->senders);
@@ -350,39 +349,99 @@ void QObjectPrivate::addConnection(int signal, Connection *c)
c->next->prev = &c->next;
}
-void QObjectPrivate::cleanConnectionLists()
+void QObjectPrivate::ConnectionData::removeConnection(QObjectPrivate::Connection *c)
{
- ConnectionData *cd = connections.load();
- if (cd->dirty && cd->ref == 1) {
- // remove broken connections
- for (int signal = -1; signal < cd->signalVector.count(); ++signal) {
- ConnectionList &connectionList = cd->connectionsForSignal(signal);
-
- // Set to the last entry in the connection list that was *not*
- // deleted. This is needed to update the list's last pointer
- // at the end of the cleanup.
- QObjectPrivate::Connection *last = 0;
-
- QObjectPrivate::Connection **prev = &connectionList.first;
- QObjectPrivate::Connection *c = *prev;
- while (c) {
- if (c->receiver) {
- last = c;
- prev = &c->nextConnectionList;
- c = *prev;
- } else {
- QObjectPrivate::Connection *next = c->nextConnectionList;
- *prev = next;
- c->deref();
- c = next;
- }
- }
+ Q_ASSERT(c->receiver.load());
+ ConnectionList &connections = signalVector.load()->at(c->signal_index);
+ c->receiver.store(nullptr);
+ QThreadData *td = c->receiverThreadData.load();
+ if (td)
+ td->deref();
+ c->receiverThreadData.store(nullptr);
+
+#ifndef QT_NO_DEBUG
+ bool found = false;
+ for (Connection *cc = connections.first.load(); cc; cc = cc->nextConnectionList.load()) {
+ if (cc == c) {
+ found = true;
+ break;
+ }
+ }
+ Q_ASSERT(found);
+#endif
+
+ // remove from the senders linked list
+ *c->prev = c->next;
+ if (c->next)
+ c->next->prev = c->prev;
+ c->prev = nullptr;
+
+ if (connections.first.load() == c)
+ connections.first.store(c->nextConnectionList.load());
+ if (connections.last.load() == c)
+ connections.last.store(c->prevConnectionList);
+ Q_ASSERT(signalVector.load()->at(c->signal_index).first.load() != c);
+ Q_ASSERT(signalVector.load()->at(c->signal_index).last.load() != c);
+
+ // keep c->nextConnectionList intact, as it might still get accessed by activate
+ Connection *n = c->nextConnectionList.load();
+ if (n)
+ n->prevConnectionList = c->prevConnectionList;
+ if (c->prevConnectionList)
+ c->prevConnectionList->nextConnectionList.store(n);
+ c->prevConnectionList = nullptr;
+
+ Q_ASSERT(c != orphaned.load());
+ // add c to orphanedConnections
+ c->nextInOrphanList = orphaned.load();
+ orphaned.store(c);
+
+#ifndef QT_NO_DEBUG
+ found = false;
+ for (Connection *cc = connections.first.load(); cc; cc = cc->nextConnectionList.load()) {
+ if (cc == c) {
+ found = true;
+ break;
+ }
+ }
+ Q_ASSERT(!found);
+#endif
+
+}
+
+void QObjectPrivate::ConnectionData::cleanOrphanedConnectionsImpl(QObject *sender)
+{
+ ConnectionOrSignalVector *c = nullptr;
+ {
+ 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);
+}
+
+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();
}
- cd->dirty = false;
+ o = next;
}
}
@@ -400,16 +459,19 @@ bool QObjectPrivate::isSignalConnected(uint signalIndex, bool checkDeclarative)
ConnectionData *cd = connections.load();
if (!cd)
return false;
+ SignalVector *signalVector = cd->signalVector.load();
+ if (!signalVector)
+ return false;
- if (cd->allsignals.first)
+ if (signalVector->at(-1).first.load())
return true;
- if (signalIndex < uint(cd->signalVector.count())) {
- const QObjectPrivate::Connection *c = cd->signalVector.at(signalIndex).first;
+ if (signalIndex < uint(cd->signalVectorCount())) {
+ const QObjectPrivate::Connection *c = signalVector->at(signalIndex).first.load();
while (c) {
- if (c->receiver)
+ if (c->receiver.load())
return true;
- c = c->nextConnectionList;
+ c = c->nextConnectionList.load();
}
}
return false;
@@ -420,17 +482,30 @@ bool QObjectPrivate::maybeSignalConnected(uint signalIndex) const
ConnectionData *cd = connections.load();
if (!cd)
return false;
+ SignalVector *signalVector = cd->signalVector.load();
+ if (!signalVector)
+ return false;
- if (cd->allsignals.first)
+ if (signalVector->at(-1).first)
return true;
- if (signalIndex < uint(cd->signalVector.count())) {
- const QObjectPrivate::Connection *c = cd->signalVector.at(signalIndex).first;
+ if (signalIndex < uint(cd->signalVectorCount())) {
+ const QObjectPrivate::Connection *c = signalVector->at(signalIndex).first;
return c != nullptr;
}
return false;
}
+/*!
+ \internal
+ */
+QAbstractMetaCallEvent::~QAbstractMetaCallEvent()
+{
+#if QT_CONFIG(thread)
+ if (semaphore_)
+ semaphore_->release();
+#endif
+}
/*!
\internal
@@ -438,8 +513,8 @@ bool QObjectPrivate::maybeSignalConnected(uint signalIndex) const
QMetaCallEvent::QMetaCallEvent(ushort method_offset, ushort method_relative, QObjectPrivate::StaticMetaCallFunction callFunction,
const QObject *sender, int signalId,
int nargs, int *types, void **args, QSemaphore *semaphore)
- : QEvent(MetaCall), slotObj_(0), sender_(sender), signalId_(signalId),
- nargs_(nargs), types_(types), args_(args), semaphore_(semaphore),
+ : QAbstractMetaCallEvent(sender, signalId, semaphore),
+ slotObj_(nullptr), nargs_(nargs), types_(types), args_(args),
callFunction_(callFunction), method_offset_(method_offset), method_relative_(method_relative)
{ }
@@ -448,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();
@@ -469,10 +544,6 @@ QMetaCallEvent::~QMetaCallEvent()
free(types_);
free(args_);
}
-#if QT_CONFIG(thread)
- if (semaphore_)
- semaphore_->release();
-#endif
if (slotObj_)
slotObj_->destroyIfLastRef();
}
@@ -900,52 +971,27 @@ QObject::~QObject()
QBasicMutexLocker locker(signalSlotMutex);
// disconnect all receivers
- int receiverCount = cd->signalVector.count();
+ int receiverCount = cd->signalVectorCount();
for (int signal = -1; signal < receiverCount; ++signal) {
QObjectPrivate::ConnectionList &connectionList = cd->connectionsForSignal(signal);
- while (QObjectPrivate::Connection *c = connectionList.first) {
- if (!c->receiver) {
- connectionList.first = c->nextConnectionList;
- c->deref();
- continue;
- }
+ while (QObjectPrivate::Connection *c = connectionList.first.load()) {
+ Q_ASSERT(c->receiver);
- QBasicMutex *m = signalSlotLock(c->receiver);
+ QBasicMutex *m = signalSlotLock(c->receiver.load());
bool needToUnlock = QOrderedMutexLocker::relock(signalSlotMutex, m);
-
if (c->receiver) {
- *c->prev = c->next;
- if (c->next) c->next->prev = c->prev;
+ cd->removeConnection(c);
+ Q_ASSERT(connectionList.first.load() != c);
}
- c->receiver = 0;
if (needToUnlock)
m->unlock();
-
- connectionList.first = c->nextConnectionList;
-
- // The destroy operation must happen outside the lock
- if (c->isSlotObject) {
- c->isSlotObject = false;
- locker.unlock();
- c->slotObj->destroyIfLastRef();
- locker.relock();
- }
- c->deref();
}
}
/* Disconnect all senders:
- * This loop basically just does
- * for (node = d->senders; node; node = node->next) { ... }
- *
- * We need to temporarily unlock the receiver mutex to destroy the functors or to lock the
- * sender's mutex. And when the mutex is released, node->next might be destroyed by another
- * thread. That's why we set node->prev to &node, that way, if node is destroyed, node will
- * be updated.
*/
- QObjectPrivate::Connection *node = cd->senders;
- while (node) {
+ while (QObjectPrivate::Connection *node = cd->senders) {
Q_ASSERT(node->receiver);
QObject *sender = node->sender;
// Send disconnectNotify before removing the connection from sender's connection list.
@@ -953,19 +999,17 @@ QObject::~QObject()
// and not finish until we release it.
sender->disconnectNotify(QMetaObjectPrivate::signal(sender->metaObject(), node->signal_index));
QBasicMutex *m = signalSlotLock(sender);
- node->prev = &node;
bool needToUnlock = QOrderedMutexLocker::relock(signalSlotMutex, m);
//the node has maybe been removed while the mutex was unlocked in relock?
- if (!node || node->sender != sender) {
+ if (node != cd->senders) {
// We hold the wrong mutex
Q_ASSERT(needToUnlock);
m->unlock();
continue;
}
- node->receiver = 0;
+
QObjectPrivate::ConnectionData *senderData = sender->d_func()->connections.load();
- if (senderData)
- senderData->dirty = true;
+ Q_ASSERT(senderData);
QtPrivate::QSlotObjectBase *slotObj = nullptr;
if (node->isSlotObject) {
@@ -973,20 +1017,20 @@ QObject::~QObject()
node->isSlotObject = false;
}
- node = node->next;
+ senderData->removeConnection(node);
if (needToUnlock)
m->unlock();
if (slotObj) {
- if (node)
- node->prev = &node;
locker.unlock();
slotObj->destroyIfLastRef();
locker.relock();
}
}
- cd->objectDeleted = true;
+ // invalidate all connections on the object and make sure
+ // activate() will skip them
+ cd->currentConnectionId.store(0);
}
if (cd && !cd->ref.deref())
delete cd;
@@ -1217,7 +1261,7 @@ bool QObject::event(QEvent *e)
case QEvent::MetaCall:
{
- QMetaCallEvent *mce = static_cast<QMetaCallEvent*>(e);
+ QAbstractMetaCallEvent *mce = static_cast<QAbstractMetaCallEvent*>(e);
if (!d_func()->connections.load()) {
QBasicMutexLocker locker(signalSlotLock(this));
@@ -1383,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;
@@ -1478,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(&currentData->postEventList.mutex,
&targetData->postEventList.mutex);
@@ -1528,9 +1575,29 @@ void QObjectPrivate::setThreadData_helper(QThreadData *currentData, QThreadData
// the current emitting thread shouldn't restore currentSender after calling moveToThread()
ConnectionData *cd = connections.load();
- if (cd && cd->currentSender) {
- cd->currentSender->receiverDeleted();
- cd->currentSender = nullptr;
+ if (cd) {
+ if (cd->currentSender) {
+ cd->currentSender->receiverDeleted();
+ cd->currentSender = nullptr;
+ }
+
+ // adjust the receiverThreadId values in the Connections
+ if (cd) {
+ auto *c = cd->senders;
+ while (c) {
+ QObject *r = c->receiver.load();
+ if (r) {
+ Q_ASSERT(r == q);
+ targetData->ref();
+ QThreadData *old = c->receiverThreadData.load();
+ if (old)
+ old->deref();
+ c->receiverThreadData.store(targetData);
+ }
+ c = c->next;
+ }
+ }
+
}
// set new thread data
@@ -2316,7 +2383,7 @@ static void err_info_about_objects(const char * func,
/*!
Returns a pointer to the object that sent the signal, if called in
- a slot activated by a signal; otherwise it returns 0. The pointer
+ a slot activated by a signal; otherwise it returns \nullptr. The pointer
is valid only during the execution of the slot that calls this
function from this object's thread context.
@@ -2448,12 +2515,11 @@ int QObject::receivers(const char *signal) const
QObjectPrivate::ConnectionData *cd = d->connections.load();
QBasicMutexLocker locker(signalSlotLock(this));
- if (cd && signal_index < cd->signalVector.count()) {
- const QObjectPrivate::Connection *c =
- cd->signalVector.at(signal_index).first;
+ if (cd && signal_index < cd->signalVectorCount()) {
+ const QObjectPrivate::Connection *c = cd->signalVector.load()->at(signal_index).first.load();
while (c) {
- receivers += c->receiver ? 1 : 0;
- c = c->nextConnectionList;
+ receivers += c->receiver.load() ? 1 : 0;
+ c = c->nextConnectionList.load();
}
}
}
@@ -3264,15 +3330,15 @@ QObjectPrivate::Connection *QMetaObjectPrivate::connect(const QObject *sender,
QObjectPrivate::ConnectionData *scd = QObjectPrivate::get(s)->connections.load();
if (type & Qt::UniqueConnection && scd) {
- if (scd->signalVector.count() > signal_index) {
- const QObjectPrivate::Connection *c2 = scd->signalVector.at(signal_index).first;
+ if (scd->signalVectorCount() > signal_index) {
+ const QObjectPrivate::Connection *c2 = scd->signalVector.load()->at(signal_index).first.load();
int method_index_absolute = method_index + method_offset;
while (c2) {
- if (!c2->isSlotObject && c2->receiver == receiver && c2->method() == method_index_absolute)
+ if (!c2->isSlotObject && c2->receiver.load() == receiver && c2->method() == method_index_absolute)
return nullptr;
- c2 = c2->nextConnectionList;
+ c2 = c2->nextConnectionList.load();
}
}
type &= Qt::UniqueConnection - 1;
@@ -3281,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());
@@ -3333,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,
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;
QBasicMutex *receiverMutex = nullptr;
- if (c->receiver) {
- receiverMutex = signalSlotLock(c->receiver);
+ if (r) {
+ receiverMutex = signalSlotLock(r);
// need to relock this receiver and sender in the correct order
needToUnlock = QOrderedMutexLocker::relock(senderMutex, receiverMutex);
}
- if (c->receiver) {
- *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;
}
@@ -3406,24 +3465,20 @@ bool QMetaObjectPrivate::disconnect(const QObject *sender,
if (signal_index < 0) {
// remove from all connection lists
- for (int sig_index = -1; sig_index < scd->signalVector.count(); ++sig_index) {
- QObjectPrivate::Connection *c = scd->connectionsForSignal(sig_index).first;
- if (disconnectHelper(c, receiver, method_index, slot, senderMutex, disconnectType)) {
+ 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;
- scd->dirty = true;
- }
}
- } else if (signal_index < scd->signalVector.count()) {
- QObjectPrivate::Connection *c = scd->signalVector.at(signal_index).first;
- if (disconnectHelper(c, receiver, method_index, slot, senderMutex, disconnectType)) {
+ } else if (signal_index < scd->signalVectorCount()) {
+ if (disconnectHelper(connections.data(), signal_index, receiver, method_index, slot, senderMutex, disconnectType))
success = true;
- scd->dirty = true;
- }
}
}
locker.unlock();
if (success) {
+ scd->cleanOrphanedConnections(s);
+
QMetaMethod smethod = QMetaObjectPrivate::signal(smeta, signal_index);
if (smethod.isValid())
s->disconnectNotify(smethod);
@@ -3539,8 +3594,7 @@ void QMetaObject::connectSlotsByName(QObject *o)
\a signal must be in the signal index range (see QObjectPrivate::signalIndex()).
*/
-static void queued_activate(QObject *sender, int signal, QObjectPrivate::Connection *c, void **argv,
- QBasicMutexLocker &locker)
+static void queued_activate(QObject *sender, int signal, QObjectPrivate::Connection *c, void **argv)
{
const int *argumentTypes = c->argumentTypes.load();
if (!argumentTypes) {
@@ -3570,27 +3624,25 @@ static void queued_activate(QObject *sender, int signal, QObjectPrivate::Connect
for (int n = 1; n < nargs; ++n)
types[n] = argumentTypes[n-1];
- locker.unlock();
for (int n = 1; n < nargs; ++n)
args[n] = QMetaType::create(types[n], argv[n]);
- locker.relock();
-
- if (!c->receiver) {
- locker.unlock();
- // we have been disconnected while the mutex was unlocked
- for (int n = 1; n < nargs; ++n)
- QMetaType::destroy(types[n], args[n]);
- free(types);
- free(args);
- locker.relock();
- return;
- }
+ }
+
+ QBasicMutexLocker locker(signalSlotLock(c->receiver.load()));
+ if (!c->receiver.load()) {
+ // the connection has been disconnected before we got the lock
+ locker.unlock();
+ for (int n = 1; n < nargs; ++n)
+ QMetaType::destroy(types[n], args[n]);
+ free(types);
+ free(args);
+ return;
}
QMetaCallEvent *ev = c->isSlotObject ?
new QMetaCallEvent(c->slotObj, sender, signal, nargs, types, args) :
new QMetaCallEvent(c->method_offset, c->method_relative, c->callFunction, sender, signal, nargs, types, args);
- QCoreApplication::postEvent(c->receiver, ev);
+ QCoreApplication::postEvent(c->receiver.load(), ev);
}
template <bool callbacks_enabled>
@@ -3630,38 +3682,53 @@ void doActivate(QObject *sender, int signal_index, void **argv)
signal_spy_set->signal_begin_callback(sender, signal_index, argv);
Q_TRACE(QMetaObject_activate_begin_signal, sender, signal_index);
+ bool senderDeleted = false;
{
- QBasicMutexLocker locker(signalSlotLock(sender));
Q_ASSERT(sp->connections);
QObjectPrivate::ConnectionDataPointer connections(sp->connections.load());
+ QObjectPrivate::SignalVector *signalVector = connections->signalVector.load();
const QObjectPrivate::ConnectionList *list;
- if (signal_index < connections->signalVector.count())
- list = &connections->signalVector.at(signal_index);
+ if (signal_index < signalVector->count())
+ list = &signalVector->at(signal_index);
else
- list = &connections->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;
+
+ QThreadData *td = c->receiverThreadData.load();
+ if (!td)
continue;
- QObject * const receiver = c->receiver;
- const bool receiverInSameThread = currentThreadId == QObjectPrivate::get(receiver)->threadData->threadId.load();
+ 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) {
@@ -3672,13 +3739,16 @@ void doActivate(QObject *sender, int signal_index, void **argv)
receiver->metaObject()->className(), receiver);
}
QSemaphore semaphore;
- QMetaCallEvent *ev = c->isSlotObject ?
- new QMetaCallEvent(c->slotObj, sender, signal_index, 0, 0, argv, &semaphore) :
- new QMetaCallEvent(c->method_offset, c->method_relative, c->callFunction, sender, signal_index, 0, 0, argv, &semaphore);
- QCoreApplication::postEvent(receiver, ev);
- locker.unlock();
+ {
+ QBasicMutexLocker locker(signalSlotLock(sender));
+ if (!c->receiver)
+ continue;
+ QMetaCallEvent *ev = c->isSlotObject ?
+ new QMetaCallEvent(c->slotObj, sender, signal_index, 0, 0, argv, &semaphore) :
+ new QMetaCallEvent(c->method_offset, c->method_relative, c->callFunction, sender, signal_index, 0, 0, argv, &semaphore);
+ QCoreApplication::postEvent(receiver, ev);
+ }
semaphore.acquire();
- locker.relock();
continue;
#endif
}
@@ -3688,22 +3758,13 @@ void doActivate(QObject *sender, int signal_index, void **argv)
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 method_relative = c->method_relative;
const auto callFunction = c->callFunction;
- locker.unlock();
const int methodIndex = (Q_HAS_TRACEPOINTS || callbacks_enabled) ? c->method() : 0;
if (callbacks_enabled && signal_spy_set->slot_begin_callback != nullptr)
signal_spy_set->slot_begin_callback(receiver, methodIndex, argv);
@@ -3714,10 +3775,8 @@ void doActivate(QObject *sender, int signal_index, void **argv)
Q_TRACE(QMetaObject_activate_end_slot, receiver, methodIndex);
if (callbacks_enabled && signal_spy_set->slot_end_callback != nullptr)
signal_spy_set->slot_end_callback(receiver, methodIndex);
- locker.relock();
} else {
const int method = c->method_relative + c->method_offset;
- locker.unlock();
if (callbacks_enabled && signal_spy_set->slot_begin_callback != nullptr) {
signal_spy_set->slot_begin_callback(receiver, method, argv);
@@ -3729,21 +3788,18 @@ void doActivate(QObject *sender, int signal_index, void **argv)
Q_TRACE(QMetaObject_activate_end_slot, receiver, method);
if (callbacks_enabled && signal_spy_set->slot_end_callback != nullptr)
signal_spy_set->slot_end_callback(receiver, method);
-
- locker.relock();
}
+ } while ((c = c->nextConnectionList.load()) != nullptr && c->id <= highestConnectionId);
- if (connections->objectDeleted)
- break;
- } while (c != last && (c = c->nextConnectionList) != 0);
-
- if (connections->objectDeleted)
- break;
- } while (list != &connections->allsignals &&
+ } while (list != &signalVector->at(-1) &&
//start over for all signals;
- ((list = &connections->allsignals), true));
+ ((list = &signalVector->at(-1)), true));
+ if (connections->currentConnectionId.load() == 0)
+ senderDeleted = true;
}
+ if (!senderDeleted)
+ sp->connections.load()->cleanOrphanedConnections(sender);
if (callbacks_enabled && signal_spy_set->signal_end_callback != nullptr)
signal_spy_set->signal_end_callback(sender, signal_index);
@@ -4038,31 +4094,34 @@ void QObject::dumpObjectInfo() const
qDebug(" SIGNALS OUT");
QObjectPrivate::ConnectionData *cd = d->connections.load();
- if (cd && cd->signalVector.count()) {
- for (int signal_index = 0; signal_index < cd->signalVector.count(); ++signal_index) {
+ if (cd && cd->signalVectorCount()) {
+ 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 = cd->signalVector.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 {
@@ -4810,15 +4869,15 @@ QMetaObject::Connection QObjectPrivate::connectImpl(const QObject *sender, int s
if (type & Qt::UniqueConnection && slot && QObjectPrivate::get(s)->connections.load()) {
QObjectPrivate::ConnectionData *connections = QObjectPrivate::get(s)->connections.load();
- if (connections->signalVector.count() > signal_index) {
- const QObjectPrivate::Connection *c2 = connections->signalVector.at(signal_index).first;
+ if (connections->signalVectorCount() > signal_index) {
+ const QObjectPrivate::Connection *c2 = connections->signalVector.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);
@@ -4827,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;
@@ -4859,30 +4921,30 @@ 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;
QBasicMutex *senderMutex = signalSlotLock(c->sender);
- QBasicMutex *receiverMutex = signalSlotLock(c->receiver);
+ QBasicMutex *receiverMutex = signalSlotLock(receiver);
+ QObjectPrivate::ConnectionData *connections;
{
QOrderedMutexLocker locker(senderMutex, receiverMutex);
- QObjectPrivate::ConnectionData *connections = QObjectPrivate::get(c->sender)->connections.load();
- Q_ASSERT(connections);
- connections->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 = nullptr;
+ connections = QObjectPrivate::get(c->sender)->connections.load();
+ Q_ASSERT(connections);
+ connections->removeConnection(c);
}
- // destroy the QSlotObject, if possible
- if (c->isSlotObject) {
- c->slotObj->destroyIfLastRef();
- c->isSlotObject = false;
- }
+ connections->cleanOrphanedConnections(c->sender);
c->sender->disconnectNotify(QMetaObjectPrivate::signal(c->sender->metaObject(),
c->signal_index));
@@ -5069,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..6d7b9521c2 100644
--- a/src/corelib/kernel/qobject.h
+++ b/src/corelib/kernel/qobject.h
@@ -142,8 +142,8 @@ public:
inline bool isWidgetType() const { return d_ptr->isWidget; }
inline bool isWindowType() const { return d_ptr->isWindow; }
- inline bool signalsBlocked() const Q_DECL_NOTHROW { return d_ptr->blockSig; }
- bool blockSignals(bool b) Q_DECL_NOTHROW;
+ inline bool signalsBlocked() const noexcept { return d_ptr->blockSig; }
+ bool blockSignals(bool b) noexcept;
QThread *thread() const;
void moveToThread(QThread *thread);
@@ -436,7 +436,7 @@ protected:
QScopedPointer<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,17 @@ Q_CORE_EXPORT QDebug operator<<(QDebug, const QObject *);
class QSignalBlocker
{
public:
- inline explicit QSignalBlocker(QObject *o) Q_DECL_NOTHROW;
- inline explicit QSignalBlocker(QObject &o) Q_DECL_NOTHROW;
+ inline explicit QSignalBlocker(QObject *o) noexcept;
+ inline explicit QSignalBlocker(QObject &o) noexcept;
inline ~QSignalBlocker();
#ifdef Q_COMPILER_RVALUE_REFS
- inline QSignalBlocker(QSignalBlocker &&other) Q_DECL_NOTHROW;
- inline QSignalBlocker &operator=(QSignalBlocker &&other) Q_DECL_NOTHROW;
+ inline QSignalBlocker(QSignalBlocker &&other) noexcept;
+ inline QSignalBlocker &operator=(QSignalBlocker &&other) noexcept;
#endif
- inline void reblock() Q_DECL_NOTHROW;
- inline void unblock() Q_DECL_NOTHROW;
+ inline void reblock() noexcept;
+ inline void unblock() noexcept;
private:
Q_DISABLE_COPY(QSignalBlocker)
QObject * m_o;
@@ -558,20 +558,20 @@ private:
bool m_inhibited;
};
-QSignalBlocker::QSignalBlocker(QObject *o) Q_DECL_NOTHROW
+QSignalBlocker::QSignalBlocker(QObject *o) noexcept
: m_o(o),
m_blocked(o && o->blockSignals(true)),
m_inhibited(false)
{}
-QSignalBlocker::QSignalBlocker(QObject &o) Q_DECL_NOTHROW
+QSignalBlocker::QSignalBlocker(QObject &o) noexcept
: m_o(&o),
m_blocked(o.blockSignals(true)),
m_inhibited(false)
{}
#ifdef Q_COMPILER_RVALUE_REFS
-QSignalBlocker::QSignalBlocker(QSignalBlocker &&other) Q_DECL_NOTHROW
+QSignalBlocker::QSignalBlocker(QSignalBlocker &&other) noexcept
: m_o(other.m_o),
m_blocked(other.m_blocked),
m_inhibited(other.m_inhibited)
@@ -579,7 +579,7 @@ QSignalBlocker::QSignalBlocker(QSignalBlocker &&other) Q_DECL_NOTHROW
other.m_o = nullptr;
}
-QSignalBlocker &QSignalBlocker::operator=(QSignalBlocker &&other) Q_DECL_NOTHROW
+QSignalBlocker &QSignalBlocker::operator=(QSignalBlocker &&other) noexcept
{
if (this != &other) {
// if both *this and other block the same object's signals:
@@ -602,13 +602,13 @@ QSignalBlocker::~QSignalBlocker()
m_o->blockSignals(m_blocked);
}
-void QSignalBlocker::reblock() Q_DECL_NOTHROW
+void QSignalBlocker::reblock() noexcept
{
if (m_o) m_o->blockSignals(true);
m_inhibited = false;
}
-void QSignalBlocker::unblock() Q_DECL_NOTHROW
+void QSignalBlocker::unblock() noexcept
{
if (m_o) m_o->blockSignals(m_blocked);
m_inhibited = true;
diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h
index 863689fddd..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/
**
@@ -124,45 +124,76 @@ 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
@@ -195,6 +226,22 @@ public:
int signal;
};
+ 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.
@@ -210,25 +257,65 @@ public:
linked list.
*/
struct ConnectionData {
- bool objectDeleted = false; //the QObject owner of this vector has been destroyed while the vector was inUse
- struct Ref {
- int _ref = 0;
- void ref() { ++_ref; }
- int deref() { return --_ref; }
- operator int() const { return _ref; }
- };
-
- Ref ref;
- bool dirty = false; //some Connection have been disconnected (their receiver is 0) but not removed from the list yet
- ConnectionList allsignals;
- QVector<ConnectionList> signalVector;
+ // 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 signal < 0 ? allsignals : signalVector[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);
@@ -245,7 +332,6 @@ public:
QObjectList senderList() const;
void addConnection(int signal, Connection *c);
- void cleanConnectionLists();
static QObjectPrivate *get(QObject *o) {
return o->d_func();
@@ -396,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,
@@ -407,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..a437a994fd 100644
--- a/src/corelib/kernel/qobjectdefs.h
+++ b/src/corelib/kernel/qobjectdefs.h
@@ -119,13 +119,13 @@ class QString;
#define Q_ENUMS(x) QT_ANNOTATE_CLASS(qt_enums, x)
#define Q_FLAGS(x) QT_ANNOTATE_CLASS(qt_enums, x)
#define Q_ENUM_IMPL(ENUM) \
- friend Q_DECL_CONSTEXPR const QMetaObject *qt_getEnumMetaObject(ENUM) Q_DECL_NOEXCEPT { return &staticMetaObject; } \
- friend Q_DECL_CONSTEXPR const char *qt_getEnumName(ENUM) Q_DECL_NOEXCEPT { return #ENUM; }
+ friend Q_DECL_CONSTEXPR const QMetaObject *qt_getEnumMetaObject(ENUM) noexcept { return &staticMetaObject; } \
+ friend Q_DECL_CONSTEXPR const char *qt_getEnumName(ENUM) noexcept { return #ENUM; }
#define Q_ENUM(x) Q_ENUMS(x) Q_ENUM_IMPL(x)
#define Q_FLAG(x) Q_FLAGS(x) Q_ENUM_IMPL(x)
#define Q_ENUM_NS_IMPL(ENUM) \
- inline Q_DECL_CONSTEXPR const QMetaObject *qt_getEnumMetaObject(ENUM) Q_DECL_NOEXCEPT { return &staticMetaObject; } \
- inline Q_DECL_CONSTEXPR const char *qt_getEnumName(ENUM) Q_DECL_NOEXCEPT { return #ENUM; }
+ inline Q_DECL_CONSTEXPR const QMetaObject *qt_getEnumMetaObject(ENUM) noexcept { return &staticMetaObject; } \
+ inline Q_DECL_CONSTEXPR const char *qt_getEnumName(ENUM) noexcept { return #ENUM; }
#define Q_ENUM_NS(x) Q_ENUMS(x) Q_ENUM_NS_IMPL(x)
#define Q_FLAG_NS(x) Q_FLAGS(x) Q_ENUM_NS_IMPL(x)
#define Q_SCRIPTABLE QT_ANNOTATE_FUNCTION(qt_scriptable)
@@ -340,7 +340,7 @@ struct Q_CORE_EXPORT QMetaObject
const char *className() const;
const QMetaObject *superClass() const;
- bool inherits(const QMetaObject *metaObject) const Q_DECL_NOEXCEPT;
+ bool inherits(const QMetaObject *metaObject) const noexcept;
QObject *cast(QObject *obj) const;
const QObject *cast(const QObject *obj) const;
@@ -605,8 +605,8 @@ public:
operator RestrictedBool() const { return d_ptr && isConnected_helper() ? &Connection::d_ptr : nullptr; }
#endif
- Connection(Connection &&o) Q_DECL_NOTHROW : d_ptr(o.d_ptr) { o.d_ptr = nullptr; }
- Connection &operator=(Connection &&other) Q_DECL_NOTHROW
+ Connection(Connection &&o) noexcept : d_ptr(o.d_ptr) { o.d_ptr = nullptr; }
+ Connection &operator=(Connection &&other) noexcept
{ qSwap(d_ptr, other.d_ptr); return *this; }
};
diff --git a/src/corelib/kernel/qobjectdefs_impl.h b/src/corelib/kernel/qobjectdefs_impl.h
index aa6bd84e95..31ecc8b20d 100644
--- a/src/corelib/kernel/qobjectdefs_impl.h
+++ b/src/corelib/kernel/qobjectdefs_impl.h
@@ -386,8 +386,8 @@ namespace QtPrivate {
public:
explicit QSlotObjectBase(ImplFn fn) : m_ref(1), m_impl(fn) {}
- inline int ref() Q_DECL_NOTHROW { return m_ref.ref(); }
- inline void destroyIfLastRef() Q_DECL_NOTHROW
+ inline int ref() noexcept { return m_ref.ref(); }
+ inline void destroyIfLastRef() noexcept
{ if (!m_ref.deref()) m_impl(Destroy, this, nullptr, nullptr, nullptr); }
inline bool compare(void **a) { bool ret = false; m_impl(Compare, this, nullptr, a, &ret); return ret; }
diff --git a/src/corelib/kernel/qsignalmapper.cpp b/src/corelib/kernel/qsignalmapper.cpp
index d56965281e..02a1281f92 100644
--- a/src/corelib/kernel/qsignalmapper.cpp
+++ b/src/corelib/kernel/qsignalmapper.cpp
@@ -61,7 +61,7 @@ public:
/*!
\class QSignalMapper
\inmodule QtCore
- \obsolete
+ \obsolete The recommended solution is connecting the signal to a lambda.
\brief The QSignalMapper class bundles signals from identifiable senders.
\ingroup objectmodel
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.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/qtranslator.cpp b/src/corelib/kernel/qtranslator.cpp
index dc39490ab0..a2111a084f 100644
--- a/src/corelib/kernel/qtranslator.cpp
+++ b/src/corelib/kernel/qtranslator.cpp
@@ -66,6 +66,7 @@
#endif
#include <stdlib.h>
+#include <new>
#include "qobject_p.h"
@@ -585,7 +586,7 @@ bool QTranslatorPrivate::do_load(const QString &realname, const QString &directo
#endif // QT_USE_MMAP
if (!ok) {
- d->unmapPointer = new char[d->unmapLength];
+ d->unmapPointer = new (std::nothrow) char[d->unmapLength];
if (d->unmapPointer) {
file.seek(0);
qint64 readResult = file.read(d->unmapPointer, d->unmapLength);
diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp
index 77d2c8cbe1..cd4e233af0 100644
--- a/src/corelib/kernel/qvariant.cpp
+++ b/src/corelib/kernel/qvariant.cpp
@@ -4282,6 +4282,7 @@ QDebug operator<<(QDebug dbg, const QVariant::Type p)
\sa fromValue()
*/
+#if QT_DEPRECATED_SINCE(5, 14)
/*!
\fn template<typename T> QVariant qVariantFromValue(const T &value)
\relates QVariant
@@ -4319,6 +4320,7 @@ QDebug operator<<(QDebug dbg, const QVariant::Type p)
\sa QVariant::setValue()
*/
+#endif
/*!
\fn template<typename T> T qvariant_cast(const QVariant &value)
diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h
index f95502e75f..6b35bfa9e9 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);
@@ -271,13 +268,13 @@ class Q_CORE_EXPORT QVariant
QVariant& operator=(const QVariant &other);
#ifdef Q_COMPILER_RVALUE_REFS
- inline QVariant(QVariant &&other) Q_DECL_NOTHROW : d(other.d)
+ inline QVariant(QVariant &&other) noexcept : d(other.d)
{ other.d = Private(); }
- inline QVariant &operator=(QVariant &&other) Q_DECL_NOTHROW
+ inline QVariant &operator=(QVariant &&other) noexcept
{ qSwap(d, other.d); return *this; }
#endif
- inline void swap(QVariant &other) Q_DECL_NOTHROW { qSwap(d, other.d); }
+ inline void swap(QVariant &other) noexcept { qSwap(d, other.d); }
Type type() const;
int userType() const;
@@ -365,7 +362,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 +387,15 @@ class Q_CORE_EXPORT QVariant
};
struct Private
{
- inline Private() Q_DECL_NOTHROW : type(Invalid), is_shared(false), is_null(true)
+ inline Private() noexcept : type(Invalid), is_shared(false), is_null(true)
{ data.ptr = nullptr; }
// Internal constructor for initialized variants.
- explicit inline Private(uint variantType) Q_DECL_NOTHROW
+ explicit inline Private(uint variantType) noexcept
: type(variantType), is_shared(false), is_null(false)
{}
- inline Private(const Private &other) Q_DECL_NOTHROW
+ inline Private(const Private &other) noexcept
: data(other.data), type(other.type),
is_shared(other.is_shared), is_null(other.is_null)
{}
@@ -516,50 +513,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);