summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/kernel')
-rw-r--r--src/corelib/kernel/kernel.pri8
-rw-r--r--src/corelib/kernel/qabstracteventdispatcher.cpp6
-rw-r--r--src/corelib/kernel/qabstracteventdispatcher.h4
-rw-r--r--src/corelib/kernel/qabstractnativeeventfilter.cpp1
-rw-r--r--src/corelib/kernel/qabstractnativeeventfilter.h4
-rw-r--r--src/corelib/kernel/qbasictimer.cpp85
-rw-r--r--src/corelib/kernel/qbasictimer.h31
-rw-r--r--src/corelib/kernel/qcore_foundation.mm18
-rw-r--r--src/corelib/kernel/qcore_mac.cpp3
-rw-r--r--src/corelib/kernel/qcore_mac_objc.mm8
-rw-r--r--src/corelib/kernel/qcore_mac_p.h22
-rw-r--r--src/corelib/kernel/qcore_unix.cpp4
-rw-r--r--src/corelib/kernel/qcore_unix_p.h10
-rw-r--r--src/corelib/kernel/qcoreapplication.cpp149
-rw-r--r--src/corelib/kernel/qcoreapplication.h4
-rw-r--r--src/corelib/kernel/qcoreapplication_p.h14
-rw-r--r--src/corelib/kernel/qcoreapplication_win.cpp9
-rw-r--r--src/corelib/kernel/qcoreevent.cpp14
-rw-r--r--src/corelib/kernel/qcoreevent.h2
-rw-r--r--src/corelib/kernel/qcoreglobaldata.cpp4
-rw-r--r--src/corelib/kernel/qdeadlinetimer.cpp24
-rw-r--r--src/corelib/kernel/qdeadlinetimer.h50
-rw-r--r--src/corelib/kernel/qelapsedtimer.cpp8
-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_cf.mm15
-rw-r--r--src/corelib/kernel/qeventdispatcher_cf_p.h6
-rw-r--r--src/corelib/kernel/qeventdispatcher_glib.cpp6
-rw-r--r--src/corelib/kernel/qeventdispatcher_glib_p.h6
-rw-r--r--src/corelib/kernel/qeventdispatcher_unix.cpp8
-rw-r--r--src/corelib/kernel/qeventdispatcher_unix_p.h22
-rw-r--r--src/corelib/kernel/qeventdispatcher_win.cpp172
-rw-r--r--src/corelib/kernel/qeventdispatcher_win_p.h5
-rw-r--r--src/corelib/kernel/qeventdispatcher_winrt.cpp23
-rw-r--r--src/corelib/kernel/qeventdispatcher_winrt_p.h2
-rw-r--r--src/corelib/kernel/qeventloop.cpp12
-rw-r--r--src/corelib/kernel/qeventloop_p.h4
-rw-r--r--src/corelib/kernel/qfunctions_fake_env_p.h4
-rw-r--r--src/corelib/kernel/qjni.cpp8
-rw-r--r--src/corelib/kernel/qmetaobject.cpp63
-rw-r--r--src/corelib/kernel/qmetaobject.h3
-rw-r--r--src/corelib/kernel/qmetaobject_moc_p.h4
-rw-r--r--src/corelib/kernel/qmetaobject_p.h18
-rw-r--r--src/corelib/kernel/qmetaobjectbuilder.cpp12
-rw-r--r--src/corelib/kernel/qmetaobjectbuilder_p.h8
-rw-r--r--src/corelib/kernel/qmetatype.cpp79
-rw-r--r--src/corelib/kernel/qmetatype.h22
-rw-r--r--src/corelib/kernel/qmetatype_p.h18
-rw-r--r--src/corelib/kernel/qmetatypeswitcher_p.h2
-rw-r--r--src/corelib/kernel/qobject.cpp1271
-rw-r--r--src/corelib/kernel/qobject.h52
-rw-r--r--src/corelib/kernel/qobject_p.h319
-rw-r--r--src/corelib/kernel/qobjectdefs.h74
-rw-r--r--src/corelib/kernel/qobjectdefs_impl.h4
-rw-r--r--src/corelib/kernel/qpointer.h26
-rw-r--r--src/corelib/kernel/qpoll.cpp9
-rw-r--r--src/corelib/kernel/qppsattribute.cpp2
-rw-r--r--src/corelib/kernel/qppsattribute_p.h2
-rw-r--r--src/corelib/kernel/qsharedmemory.cpp19
-rw-r--r--src/corelib/kernel/qsharedmemory.h29
-rw-r--r--src/corelib/kernel/qsharedmemory_p.h16
-rw-r--r--src/corelib/kernel/qsharedmemory_unix.cpp7
-rw-r--r--src/corelib/kernel/qsharedmemory_win.cpp5
-rw-r--r--src/corelib/kernel/qsignalmapper.cpp8
-rw-r--r--src/corelib/kernel/qsignalmapper.h6
-rw-r--r--src/corelib/kernel/qsocketnotifier.cpp6
-rw-r--r--src/corelib/kernel/qsystemerror.cpp2
-rw-r--r--src/corelib/kernel/qsystemsemaphore_systemv.cpp6
-rw-r--r--src/corelib/kernel/qtcore_eval.cpp560
-rw-r--r--src/corelib/kernel/qtestsupport_core.cpp2
-rw-r--r--src/corelib/kernel/qtimer.cpp33
-rw-r--r--src/corelib/kernel/qtimer.h2
-rw-r--r--src/corelib/kernel/qtimerinfo_unix.cpp8
-rw-r--r--src/corelib/kernel/qtranslator.cpp3
-rw-r--r--src/corelib/kernel/qvariant.cpp65
-rw-r--r--src/corelib/kernel/qvariant.h100
-rw-r--r--src/corelib/kernel/qvariant_p.h10
-rw-r--r--src/corelib/kernel/qwineventnotifier.cpp6
-rw-r--r--src/corelib/kernel/qwinregistry.cpp120
-rw-r--r--src/corelib/kernel/qwinregistry_p.h89
83 files changed, 2064 insertions, 1923 deletions
diff --git a/src/corelib/kernel/kernel.pri b/src/corelib/kernel/kernel.pri
index 3f7bf3cd47..bd3cabc01a 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 \
@@ -88,8 +88,10 @@ win32 {
SOURCES += kernel/qeventdispatcher_winrt.cpp
HEADERS += kernel/qeventdispatcher_winrt_p.h
} else {
- SOURCES += kernel/qeventdispatcher_win.cpp
- HEADERS += kernel/qeventdispatcher_win_p.h
+ SOURCES += kernel/qeventdispatcher_win.cpp \
+ kernel/qwinregistry.cpp
+ HEADERS += kernel/qeventdispatcher_win_p.h \
+ kernel/qwinregistry_p.h
}
!winrt: LIBS_PRIVATE += -lversion
diff --git a/src/corelib/kernel/qabstracteventdispatcher.cpp b/src/corelib/kernel/qabstracteventdispatcher.cpp
index ea08ff571f..7215b3f2bd 100644
--- a/src/corelib/kernel/qabstracteventdispatcher.cpp
+++ b/src/corelib/kernel/qabstracteventdispatcher.cpp
@@ -170,7 +170,7 @@ QAbstractEventDispatcher::~QAbstractEventDispatcher()
QAbstractEventDispatcher *QAbstractEventDispatcher::instance(QThread *thread)
{
QThreadData *data = thread ? QThreadData::get2(thread) : QThreadData::current();
- return data->eventDispatcher.load();
+ return data->eventDispatcher.loadRelaxed();
}
/*!
@@ -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/qbasictimer.cpp b/src/corelib/kernel/qbasictimer.cpp
index 637c98cd40..ea8f8e2c77 100644
--- a/src/corelib/kernel/qbasictimer.cpp
+++ b/src/corelib/kernel/qbasictimer.cpp
@@ -65,6 +65,10 @@ QT_BEGIN_NAMESPACE
has not been stopped. The timer's ID can be retrieved using
timerId().
+ Objects of this class cannot be copied, but can be moved, so you
+ can maintain a list of basic timers by holding them in container
+ that supports move-only types, e.g. std::vector.
+
The \l{widgets/wiggly}{Wiggly} example uses QBasicTimer to repaint
a widget at regular intervals.
@@ -79,6 +83,51 @@ QT_BEGIN_NAMESPACE
\sa start()
*/
+
+/*!
+ \fn QBasicTimer::QBasicTimer(QBasicTimer &&other)
+ \since 5.14
+
+ Move-constructs a basic timer from \a other, which is left
+ \l{isActive()}{inactive}.
+
+ \sa isActive(), swap()
+*/
+
+/*!
+ \fn QBasicTimer &QBasicTimer::operator=(QBasicTimer &&other)
+ \since 5.14
+
+ Move-assigns \a other to this basic timer. The timer
+ previously represented by this basic timer is stopped.
+ \a other is left as \l{isActive()}{inactive}.
+
+ \sa stop(), isActive(), swap()
+*/
+
+#if QT_DEPRECATED_SINCE(5, 14)
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
+/*!
+ \internal
+*/
+QBasicTimer::QBasicTimer(const QBasicTimer &other)
+ : id{other.id}
+{
+ qWarning("QBasicTimer can't be copied");
+}
+
+/*!
+ \internal
+*/
+QBasicTimer &QBasicTimer::operator=(const QBasicTimer &other)
+{
+ id = other.id;
+ qWarning("QBasicTimer can't be assigned to");
+ return *this;
+}
+#endif
+#endif
+
/*!
\fn QBasicTimer::~QBasicTimer()
@@ -95,6 +144,15 @@ QT_BEGIN_NAMESPACE
*/
/*!
+ \fn QBasicTimer::swap(QBasicTimer &other)
+ \fn swap(QBasicTimer &lhs, QBasicTimer &rhs)
+ \since 5.14
+
+ Swaps string \a other with this string, or \a lhs with \a rhs.
+ This operation is very fast and never fails.
+*/
+
+/*!
\fn int QBasicTimer::timerId() const
Returns the timer's ID.
@@ -115,24 +173,7 @@ QT_BEGIN_NAMESPACE
*/
void QBasicTimer::start(int msec, QObject *obj)
{
- QAbstractEventDispatcher *eventDispatcher = QAbstractEventDispatcher::instance();
- if (Q_UNLIKELY(!eventDispatcher)) {
- qWarning("QBasicTimer::start: QBasicTimer can only be used with threads started with QThread");
- return;
- }
- if (Q_UNLIKELY(obj && obj->thread() != eventDispatcher->thread())) {
- qWarning("QBasicTimer::start: Timers cannot be started from another thread");
- return;
- }
- if (id) {
- if (Q_LIKELY(eventDispatcher->unregisterTimer(id)))
- QAbstractEventDispatcherPrivate::releaseTimerId(id);
- else
- qWarning("QBasicTimer::start: Stopping previous timer failed. Possibly trying to stop from a different thread");
- }
- id = 0;
- if (obj)
- id = eventDispatcher->registerTimer(msec, Qt::CoarseTimer, obj);
+ start(msec, Qt::CoarseTimer, obj);
}
/*!
@@ -161,13 +202,7 @@ void QBasicTimer::start(int msec, Qt::TimerType timerType, QObject *obj)
qWarning("QBasicTimer::start: Timers cannot be started from another thread");
return;
}
- if (id) {
- if (Q_LIKELY(eventDispatcher->unregisterTimer(id)))
- QAbstractEventDispatcherPrivate::releaseTimerId(id);
- else
- qWarning("QBasicTimer::start: Stopping previous timer failed. Possibly trying to stop from a different thread");
- }
- id = 0;
+ stop();
if (obj)
id = eventDispatcher->registerTimer(msec, timerType, obj);
}
diff --git a/src/corelib/kernel/qbasictimer.h b/src/corelib/kernel/qbasictimer.h
index bfd6ffd125..769898f835 100644
--- a/src/corelib/kernel/qbasictimer.h
+++ b/src/corelib/kernel/qbasictimer.h
@@ -51,12 +51,35 @@ class QObject;
class Q_CORE_EXPORT QBasicTimer
{
int id;
+#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
+ Q_DISABLE_COPY(QBasicTimer)
+#elif QT_DEPRECATED_SINCE(5, 14)
public:
- inline QBasicTimer() : id(0) {}
+ // Just here to preserve BC, we can't remove them yet
+ QT_DEPRECATED_X("copy-construction is unsupported; use move-construction instead")
+ QBasicTimer(const QBasicTimer &);
+ QT_DEPRECATED_X("copy-assignment is unsupported; use move-assignment instead")
+ QBasicTimer &operator=(const QBasicTimer &);
+#endif
+
+public:
+ constexpr QBasicTimer() noexcept : id{0} {}
inline ~QBasicTimer() { if (id) stop(); }
- inline bool isActive() const { return id != 0; }
- inline int timerId() const { return id; }
+ QBasicTimer(QBasicTimer &&other) noexcept
+ : id{qExchange(other.id, 0)}
+ {}
+
+ QBasicTimer& operator=(QBasicTimer &&other) noexcept
+ {
+ QBasicTimer{std::move(other)}.swap(*this);
+ return *this;
+ }
+
+ void swap(QBasicTimer &other) noexcept { qSwap(id, other.id); }
+
+ bool isActive() const noexcept { return id != 0; }
+ int timerId() const noexcept { return id; }
void start(int msec, QObject *obj);
void start(int msec, Qt::TimerType timerType, QObject *obj);
@@ -64,6 +87,8 @@ public:
};
Q_DECLARE_TYPEINFO(QBasicTimer, Q_MOVABLE_TYPE);
+inline void swap(QBasicTimer &lhs, QBasicTimer &rhs) noexcept { lhs.swap(rhs); }
+
QT_END_NAMESPACE
#endif // QBASICTIMER_H
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.cpp b/src/corelib/kernel/qcore_mac.cpp
index b048576f5b..e59835be48 100644
--- a/src/corelib/kernel/qcore_mac.cpp
+++ b/src/corelib/kernel/qcore_mac.cpp
@@ -44,6 +44,7 @@
#include "qpair.h"
#include "qmutex.h"
#include "qvarlengtharray.h"
+#include "private/qlocking_p.h"
QT_BEGIN_NAMESPACE
@@ -135,7 +136,7 @@ os_log_type_t AppleUnifiedLogger::logTypeForMessageType(QtMsgType msgType)
os_log_t AppleUnifiedLogger::cachedLog(const QString &subsystem, const QString &category)
{
static QBasicMutex mutex;
- QMutexLocker locker(&mutex);
+ const auto locker = qt_scoped_lock(mutex);
static QHash<QPair<QString, QString>, os_log_t> logs;
const auto cacheKey = qMakePair(subsystem, category);
diff --git a/src/corelib/kernel/qcore_mac_objc.mm b/src/corelib/kernel/qcore_mac_objc.mm
index 15df303502..b1f3b74cd4 100644
--- a/src/corelib/kernel/qcore_mac_objc.mm
+++ b/src/corelib/kernel/qcore_mac_objc.mm
@@ -211,6 +211,12 @@ QDebug operator<<(QDebug debug, const QMacAutoReleasePool *pool)
debug << "QMacAutoReleasePool(" << (const void *)pool << ')';
return debug;
}
+
+QDebug operator<<(QDebug debug, const QCFString &string)
+{
+ debug << static_cast<QString>(string);
+ return debug;
+}
#endif // !QT_NO_DEBUG_STREAM
#ifdef Q_OS_MACOS
@@ -371,7 +377,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 168e0418e4..535d3579b2 100644
--- a/src/corelib/kernel/qcore_mac_p.h
+++ b/src/corelib/kernel/qcore_mac_p.h
@@ -86,16 +86,24 @@ template <typename T, typename U, U (*RetainFunction)(U), void (*ReleaseFunction
class QAppleRefCounted
{
public:
- QAppleRefCounted(const T &t = T()) : value(t) {}
- QAppleRefCounted(QAppleRefCounted &&other) : value(other.value) { other.value = T(); }
+ QAppleRefCounted() : value() {}
+ QAppleRefCounted(const T &t) : value(t) {}
+ QAppleRefCounted(T &&t) noexcept(std::is_nothrow_move_constructible<T>::value)
+ : value(std::move(t)) {}
+ QAppleRefCounted(QAppleRefCounted &&other)
+ noexcept(std::is_nothrow_move_assignable<T>::value &&
+ std::is_nothrow_move_constructible<T>::value)
+ : value(qExchange(other.value, T())) {}
QAppleRefCounted(const QAppleRefCounted &other) : value(other.value) { if (value) RetainFunction(value); }
~QAppleRefCounted() { if (value) ReleaseFunction(value); }
operator T() const { return value; }
- 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; }
QAppleRefCounted &operator=(QAppleRefCounted &&other)
+ noexcept(std::is_nothrow_move_assignable<T>::value &&
+ std::is_nothrow_move_constructible<T>::value)
{ QAppleRefCounted moved(std::move(other)); swap(moved); return *this; }
T *operator&() { return &value; }
protected:
@@ -129,8 +137,10 @@ private:
template <typename T>
class QCFType : public QAppleRefCounted<T, CFTypeRef, CFRetain, CFRelease>
{
+ using Base = QAppleRefCounted<T, CFTypeRef, CFRetain, CFRelease>;
public:
- using QAppleRefCounted<T, CFTypeRef, CFRetain, CFRelease>::QAppleRefCounted;
+ using Base::Base;
+ explicit QCFType(CFTypeRef r) : Base(static_cast<T>(r)) {}
template <typename X> X as() const { return reinterpret_cast<X>(this->value); }
static QCFType constructFromGet(const T &t)
{
@@ -143,6 +153,7 @@ public:
class Q_CORE_EXPORT QCFString : public QCFType<CFStringRef>
{
public:
+ using QCFType<CFStringRef>::QCFType;
inline QCFString(const QString &str) : QCFType<CFStringRef>(0), string(str) {}
inline QCFString(const CFStringRef cfstr = 0) : QCFType<CFStringRef>(cfstr) {}
inline QCFString(const QCFType<CFStringRef> &other) : QCFType<CFStringRef>(other) {}
@@ -160,7 +171,8 @@ Q_CORE_EXPORT bool qt_mac_applicationIsInDarkMode();
#endif
#ifndef QT_NO_DEBUG_STREAM
-QDebug operator<<(QDebug debug, const QMacAutoReleasePool *pool);
+Q_CORE_EXPORT QDebug operator<<(QDebug debug, const QMacAutoReleasePool *pool);
+Q_CORE_EXPORT QDebug operator<<(QDebug debug, const QCFString &string);
#endif
Q_CORE_EXPORT bool qt_apple_isApplicationExtension();
diff --git a/src/corelib/kernel/qcore_unix.cpp b/src/corelib/kernel/qcore_unix.cpp
index 18c031f137..ff0c957770 100644
--- a/src/corelib/kernel/qcore_unix.cpp
+++ b/src/corelib/kernel/qcore_unix.cpp
@@ -132,8 +132,10 @@ static inline int qt_ppoll(struct pollfd *fds, nfds_t nfds, const struct timespe
return ::ppoll(fds, nfds, timeout_ts, nullptr);
#elif QT_CONFIG(poll_poll)
return ::poll(fds, nfds, timespecToMillisecs(timeout_ts));
-#else
+#elif QT_CONFIG(poll_select)
return qt_poll(fds, nfds, timeout_ts);
+#else
+ // configure.json reports an error when everything is not available
#endif
}
diff --git a/src/corelib/kernel/qcore_unix_p.h b/src/corelib/kernel/qcore_unix_p.h
index 5a2a29a327..6ec7d28318 100644
--- a/src/corelib/kernel/qcore_unix_p.h
+++ b/src/corelib/kernel/qcore_unix_p.h
@@ -52,8 +52,8 @@
// We mean it.
//
-#include <QtCore/private/qglobal_p.h>
#include "qplatformdefs.h"
+#include <QtCore/private/qglobal_p.h>
#include "qatomic.h"
#include "qbytearray.h"
@@ -164,15 +164,15 @@ inline void qt_ignore_sigpipe()
{
// Set to ignore SIGPIPE once only.
static QBasicAtomicInt atom = Q_BASIC_ATOMIC_INITIALIZER(0);
- if (!atom.load()) {
+ if (!atom.loadRelaxed()) {
// More than one thread could turn off SIGPIPE at the same time
// But that's acceptable because they all would be doing the same
// action
struct sigaction noaction;
memset(&noaction, 0, sizeof(noaction));
noaction.sa_handler = SIG_IGN;
- ::sigaction(SIGPIPE, &noaction, 0);
- atom.store(1);
+ ::sigaction(SIGPIPE, &noaction, nullptr);
+ atom.storeRelaxed(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 75597f8739..e25049f821 100644
--- a/src/corelib/kernel/qcoreapplication.cpp
+++ b/src/corelib/kernel/qcoreapplication.cpp
@@ -55,6 +55,7 @@
#include <qfileinfo.h>
#include <qmutex.h>
#include <private/qloggingregistry_p.h>
+#include <qscopeguard.h>
#include <qstandardpaths.h>
#ifndef QT_NO_QOBJECT
#include <qthread.h>
@@ -70,6 +71,7 @@
#include <private/qfactoryloader_p.h>
#include <private/qfunctions_p.h>
#include <private/qlocale_p.h>
+#include <private/qlocking_p.h>
#include <private/qhooks_p.h>
#ifndef QT_NO_QOBJECT
@@ -217,16 +219,25 @@ QString QCoreApplicationPrivate::appVersion() const
}
#endif
-QString *QCoreApplicationPrivate::cachedApplicationFilePath = 0;
+QString *QCoreApplicationPrivate::cachedApplicationFilePath = nullptr;
bool QCoreApplicationPrivate::checkInstance(const char *function)
{
- bool b = (QCoreApplication::self != 0);
+ bool b = (QCoreApplication::self != nullptr);
if (!b)
qWarning("QApplication::%s: Please instantiate the QApplication object first", function);
return b;
}
+#if QT_CONFIG(commandlineparser)
+void QCoreApplicationPrivate::addQtOptions(QList<QCommandLineOption> *options)
+{
+ options->append(QCommandLineOption(QStringLiteral("qmljsdebugger"),
+ QStringLiteral("Activates the QML/JS debugger with a specified port. The value must be of format port:1234[,block]. \"block\" makes the application wait for a connection."),
+ QStringLiteral("value")));
+}
+#endif
+
void QCoreApplicationPrivate::processCommandLineArguments()
{
int j = argc ? 1 : 0;
@@ -251,22 +262,13 @@ void QCoreApplicationPrivate::processCommandLineArguments()
}
if (j < argc) {
- argv[j] = 0;
+ argv[j] = nullptr;
argc = j;
}
}
// 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()
{
}
@@ -294,7 +296,7 @@ void qAddPreRoutine(QtStartUpFunction p)
// Due to C++11 parallel dynamic initialization, this can be called
// from multiple threads.
- QMutexLocker locker(&globalRoutinesMutex);
+ const auto locker = qt_scoped_lock(globalRoutinesMutex);
list->prepend(p); // in case QCoreApplication is re-created, see qt_call_pre_routines
}
@@ -303,7 +305,7 @@ void qAddPostRoutine(QtCleanUpFunction p)
QVFuncList *list = postRList();
if (!list)
return;
- QMutexLocker locker(&globalRoutinesMutex);
+ const auto locker = qt_scoped_lock(globalRoutinesMutex);
list->prepend(p);
}
@@ -312,7 +314,7 @@ void qRemovePostRoutine(QtCleanUpFunction p)
QVFuncList *list = postRList();
if (!list)
return;
- QMutexLocker locker(&globalRoutinesMutex);
+ const auto locker = qt_scoped_lock(globalRoutinesMutex);
list->removeAll(p);
}
@@ -323,7 +325,7 @@ static void qt_call_pre_routines()
QVFuncList list;
{
- QMutexLocker locker(&globalRoutinesMutex);
+ const auto locker = qt_scoped_lock(globalRoutinesMutex);
// Unlike qt_call_post_routines, we don't empty the list, because
// Q_COREAPP_STARTUP_FUNCTION is a macro, so the user expects
// the function to be executed every time QCoreApplication is created.
@@ -342,7 +344,7 @@ void Q_CORE_EXPORT qt_call_post_routines()
QVFuncList list;
{
// extract the current list and make the stored list empty
- QMutexLocker locker(&globalRoutinesMutex);
+ const auto locker = qt_scoped_lock(globalRoutinesMutex);
qSwap(*postRList, list);
}
@@ -370,25 +372,25 @@ Q_CORE_EXPORT uint qGlobalPostedEventsCount()
return currentThreadData->postEventList.size() - currentThreadData->postEventList.startOffset;
}
-QAbstractEventDispatcher *QCoreApplicationPrivate::eventDispatcher = 0;
+QAbstractEventDispatcher *QCoreApplicationPrivate::eventDispatcher = nullptr;
#endif // QT_NO_QOBJECT
-QCoreApplication *QCoreApplication::self = 0;
+QCoreApplication *QCoreApplication::self = nullptr;
uint QCoreApplicationPrivate::attribs =
(1 << Qt::AA_SynthesizeMouseForUnhandledTouchEvents) |
(1 << Qt::AA_SynthesizeMouseForUnhandledTabletEvents);
struct QCoreApplicationData {
- QCoreApplicationData() Q_DECL_NOTHROW {
+ QCoreApplicationData() noexcept {
applicationNameSet = false;
applicationVersionSet = false;
}
~QCoreApplicationData() {
#ifndef QT_NO_QOBJECT
// cleanup the QAdoptedThread created for the main() thread
- if (QCoreApplicationPrivate::theMainThread) {
- QThreadData *data = QThreadData::get2(QCoreApplicationPrivate::theMainThread);
+ if (auto *t = QCoreApplicationPrivate::theMainThread.loadAcquire()) {
+ QThreadData *data = QThreadData::get2(t);
data->deref(); // deletes the data and the adopted thread
}
#endif
@@ -458,12 +460,12 @@ QCoreApplicationPrivate::QCoreApplicationPrivate(int &aargc, char **aargv, uint
, aboutToQuitEmitted(false)
, threadData_clean(false)
#else
- , q_ptr(0)
+ , q_ptr(nullptr)
#endif
{
app_compile_version = flags & 0xffffff;
static const char *const empty = "";
- if (argc == 0 || argv == 0) {
+ if (argc == 0 || argv == nullptr) {
argc = 0;
argv = const_cast<char **>(&empty);
}
@@ -488,7 +490,7 @@ QCoreApplicationPrivate::QCoreApplicationPrivate(int &aargc, char **aargv, uint
#endif
QThread *cur = QThread::currentThread(); // note: this may end up setting theMainThread!
- if (cur != theMainThread)
+ if (cur != theMainThread.loadAcquire())
qWarning("WARNING: QApplication was not created in the main() thread.");
#endif
}
@@ -522,7 +524,7 @@ void QCoreApplicationPrivate::cleanupThreadData()
#endif
// need to clear the state of the mainData, just in case a new QCoreApplication comes along.
- QMutexLocker locker(&threadData->postEventList.mutex);
+ const auto locker = qt_scoped_lock(threadData->postEventList.mutex);
for (int i = 0; i < threadData->postEventList.size(); ++i) {
const QPostEvent &pe = threadData->postEventList.at(i);
if (pe.event) {
@@ -554,8 +556,8 @@ void QCoreApplicationPrivate::eventDispatcherReady()
QBasicAtomicPointer<QThread> QCoreApplicationPrivate::theMainThread = Q_BASIC_ATOMIC_INITIALIZER(0);
QThread *QCoreApplicationPrivate::mainThread()
{
- Q_ASSERT(theMainThread.load() != 0);
- return theMainThread.load();
+ Q_ASSERT(theMainThread.loadRelaxed() != 0);
+ return theMainThread.loadRelaxed();
}
bool QCoreApplicationPrivate::threadRequiresCoreApplication()
@@ -856,7 +858,7 @@ void QCoreApplicationPrivate::init()
#ifndef QT_NO_QOBJECT
// use the event dispatcher created by the app programmer (if any)
Q_ASSERT(!eventDispatcher);
- eventDispatcher = threadData->eventDispatcher.load();
+ eventDispatcher = threadData->eventDispatcher.loadRelaxed();
// otherwise we create one
if (!eventDispatcher)
@@ -864,7 +866,7 @@ void QCoreApplicationPrivate::init()
Q_ASSERT(eventDispatcher);
if (!eventDispatcher->parent()) {
- eventDispatcher->moveToThread(threadData->thread);
+ eventDispatcher->moveToThread(threadData->thread.loadAcquire());
eventDispatcher->setParent(q);
}
@@ -872,11 +874,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();
@@ -898,7 +895,7 @@ QCoreApplication::~QCoreApplication()
{
qt_call_post_routines();
- self = 0;
+ self = nullptr;
#ifndef QT_NO_QOBJECT
QCoreApplicationPrivate::is_app_closing = true;
QCoreApplicationPrivate::is_app_running = false;
@@ -906,7 +903,7 @@ QCoreApplication::~QCoreApplication()
#if QT_CONFIG(thread)
// Synchronize and stop the global thread pool threads.
- QThreadPool *globalThreadPool = 0;
+ QThreadPool *globalThreadPool = nullptr;
QT_TRY {
globalThreadPool = QThreadPool::globalInstance();
} QT_CATCH (...) {
@@ -917,10 +914,10 @@ QCoreApplication::~QCoreApplication()
#endif
#ifndef QT_NO_QOBJECT
- d_func()->threadData->eventDispatcher = 0;
+ d_func()->threadData->eventDispatcher = nullptr;
if (QCoreApplicationPrivate::eventDispatcher)
QCoreApplicationPrivate::eventDispatcher->closingDown();
- QCoreApplicationPrivate::eventDispatcher = 0;
+ QCoreApplicationPrivate::eventDispatcher = nullptr;
#endif
#if QT_CONFIG(library)
@@ -1188,7 +1185,7 @@ static bool doNotify(QObject *receiver, QEvent *event)
bool QCoreApplicationPrivate::sendThroughApplicationEventFilters(QObject *receiver, QEvent *event)
{
// We can't access the application event filters outside of the main thread (race conditions)
- Q_ASSERT(receiver->d_func()->threadData->thread == mainThread());
+ Q_ASSERT(receiver->d_func()->threadData->thread.loadAcquire() == mainThread());
if (extraData) {
// application event filters are only called for objects in the GUI thread
@@ -1241,7 +1238,7 @@ bool QCoreApplicationPrivate::notify_helper(QObject *receiver, QEvent * event)
// send to all application event filters (only does anything in the main thread)
if (QCoreApplication::self
- && receiver->d_func()->threadData->thread == mainThread()
+ && receiver->d_func()->threadData->thread.loadAcquire() == mainThread()
&& QCoreApplication::self->d_func()->sendThroughApplicationEventFilters(receiver, event)) {
filtered = true;
return filtered;
@@ -1313,7 +1310,7 @@ void QCoreApplication::processEvents(QEventLoop::ProcessEventsFlags flags)
QThreadData *data = QThreadData::current();
if (!data->hasEventDispatcher())
return;
- data->eventDispatcher.load()->processEvents(flags);
+ data->eventDispatcher.loadRelaxed()->processEvents(flags);
}
/*!
@@ -1345,7 +1342,7 @@ void QCoreApplication::processEvents(QEventLoop::ProcessEventsFlags flags, int m
return;
QElapsedTimer start;
start.start();
- while (data->eventDispatcher.load()->processEvents(flags & ~QEventLoop::WaitForMoreEvents)) {
+ while (data->eventDispatcher.loadRelaxed()->processEvents(flags & ~QEventLoop::WaitForMoreEvents)) {
if (start.elapsed() > ms)
break;
}
@@ -1710,7 +1707,7 @@ void QCoreApplicationPrivate::sendPostedEvents(QObject *receiver, int event_type
++data->postEventList.recursion;
- QMutexLocker locker(&data->postEventList.mutex);
+ auto locker = qt_unique_lock(data->postEventList.mutex);
// by default, we assume that the event dispatcher can go to sleep after
// processing all events. if any new events are posted while we send
@@ -1749,7 +1746,7 @@ void QCoreApplicationPrivate::sendPostedEvents(QObject *receiver, int event_type
--data->postEventList.recursion;
if (!data->postEventList.recursion && !data->canWait && data->hasEventDispatcher())
- data->eventDispatcher.load()->wakeUp();
+ data->eventDispatcher.loadRelaxed()->wakeUp();
// clear the global list, i.e. remove everything that was
// delivered.
@@ -1826,13 +1823,8 @@ void QCoreApplicationPrivate::sendPostedEvents(QObject *receiver, int event_type
// for the next event.
const_cast<QPostEvent &>(pe).event = 0;
- struct MutexUnlocker
- {
- QMutexLocker &m;
- MutexUnlocker(QMutexLocker &m) : m(m) { m.unlock(); }
- ~MutexUnlocker() { m.relock(); }
- };
- MutexUnlocker unlocker(locker);
+ locker.unlock();
+ const auto relocker = qScopeGuard([&locker] { locker.lock(); });
QScopedPointer<QEvent> event_deleter(e); // will delete the event (with the mutex unlocked)
@@ -1869,7 +1861,7 @@ void QCoreApplicationPrivate::sendPostedEvents(QObject *receiver, int event_type
void QCoreApplication::removePostedEvents(QObject *receiver, int eventType)
{
QThreadData *data = receiver ? receiver->d_func()->threadData : QThreadData::current();
- QMutexLocker locker(&data->postEventList.mutex);
+ auto locker = qt_unique_lock(data->postEventList.mutex);
// the QObject destructor calls this function directly. this can
// happen while the event loop is in the middle of posting events,
@@ -1932,7 +1924,7 @@ void QCoreApplicationPrivate::removePostedEvent(QEvent * event)
QThreadData *data = QThreadData::current();
- QMutexLocker locker(&data->postEventList.mutex);
+ const auto locker = qt_scoped_lock(data->postEventList.mutex);
if (data->postEventList.size() == 0) {
#if defined(QT_DEBUG)
@@ -2000,7 +1992,7 @@ void QCoreApplicationPrivate::deref()
void QCoreApplicationPrivate::maybeQuit()
{
- if (quitLockRef.load() == 0 && in_exec && quitLockRefEnabled && shouldQuit())
+ if (quitLockRef.loadRelaxed() == 0 && in_exec && quitLockRefEnabled && shouldQuit())
QCoreApplication::postEvent(QCoreApplication::instance(), new QEvent(QEvent::Quit));
}
@@ -2662,7 +2654,7 @@ QString QCoreApplication::applicationVersion()
#if QT_CONFIG(library)
-Q_GLOBAL_STATIC_WITH_ARGS(QMutex, libraryPathMutex, (QMutex::Recursive))
+Q_GLOBAL_STATIC(QRecursiveMutex, libraryPathMutex)
/*!
Returns a list of paths that the application will search when
@@ -2701,7 +2693,14 @@ Q_GLOBAL_STATIC_WITH_ARGS(QMutex, libraryPathMutex, (QMutex::Recursive))
QStringList QCoreApplication::libraryPaths()
{
QMutexLocker locker(libraryPathMutex());
+ return libraryPathsLocked();
+}
+/*!
+ \internal
+*/
+QStringList QCoreApplication::libraryPathsLocked()
+{
if (coreappdata()->manual_libpaths)
return *(coreappdata()->manual_libpaths);
@@ -2709,18 +2708,22 @@ QStringList QCoreApplication::libraryPaths()
QStringList *app_libpaths = new QStringList;
coreappdata()->app_libpaths.reset(app_libpaths);
- QString libPathEnv = qEnvironmentVariable("QT_PLUGIN_PATH");
- if (!libPathEnv.isEmpty()) {
- QStringList paths = libPathEnv.split(QDir::listSeparator(), QString::SkipEmptyParts);
- for (QStringList::const_iterator it = paths.constBegin(); it != paths.constEnd(); ++it) {
- QString canonicalPath = QDir(*it).canonicalPath();
- if (!canonicalPath.isEmpty()
- && !app_libpaths->contains(canonicalPath)) {
- app_libpaths->append(canonicalPath);
+ auto setPathsFromEnv = [&](QString libPathEnv) {
+ if (!libPathEnv.isEmpty()) {
+ QStringList paths = libPathEnv.split(QDir::listSeparator(), QString::SkipEmptyParts);
+ for (QStringList::const_iterator it = paths.constBegin(); it != paths.constEnd(); ++it) {
+ QString canonicalPath = QDir(*it).canonicalPath();
+ if (!canonicalPath.isEmpty()
+ && !app_libpaths->contains(canonicalPath)) {
+ app_libpaths->append(canonicalPath);
+ }
}
}
- }
-
+ };
+ setPathsFromEnv(qEnvironmentVariable("QT_PLUGIN_PATH"));
+#ifdef Q_OS_ANDROID
+ setPathsFromEnv(qEnvironmentVariable("QT_BUNDLED_LIBS_PATH"));
+#endif
#ifdef Q_OS_DARWIN
// Check the main bundle's PlugIns directory as this is a standard location for Apple OSes.
// Note that the QLibraryInfo::PluginsPath below will coincidentally be the same as this value
@@ -2777,7 +2780,7 @@ void QCoreApplication::setLibraryPaths(const QStringList &paths)
// When the application is constructed it should still amend the paths. So we keep the originals
// around, and even create them if they don't exist, yet.
if (!coreappdata()->app_libpaths)
- libraryPaths();
+ libraryPathsLocked();
if (coreappdata()->manual_libpaths)
*(coreappdata()->manual_libpaths) = paths;
@@ -2820,7 +2823,7 @@ void QCoreApplication::addLibraryPath(const QString &path)
return;
} else {
// make sure that library paths are initialized
- libraryPaths();
+ libraryPathsLocked();
QStringList *app_libpaths = coreappdata()->app_libpaths.data();
if (app_libpaths->contains(canonicalPath))
return;
@@ -2859,7 +2862,7 @@ void QCoreApplication::removeLibraryPath(const QString &path)
return;
} else {
// make sure that library paths is initialized
- libraryPaths();
+ libraryPathsLocked();
QStringList *app_libpaths = coreappdata()->app_libpaths.data();
if (!app_libpaths->contains(canonicalPath))
return;
@@ -2912,7 +2915,7 @@ void QCoreApplication::installNativeEventFilter(QAbstractNativeEventFilter *filt
return;
}
- QAbstractEventDispatcher *eventDispatcher = QAbstractEventDispatcher::instance(QCoreApplicationPrivate::theMainThread);
+ QAbstractEventDispatcher *eventDispatcher = QAbstractEventDispatcher::instance(QCoreApplicationPrivate::theMainThread.loadAcquire());
if (!filterObj || !eventDispatcher)
return;
eventDispatcher->installNativeEventFilter(filterObj);
@@ -2968,8 +2971,8 @@ bool QCoreApplication::hasPendingEvents()
*/
QAbstractEventDispatcher *QCoreApplication::eventDispatcher()
{
- if (QCoreApplicationPrivate::theMainThread)
- return QCoreApplicationPrivate::theMainThread.load()->eventDispatcher();
+ if (QCoreApplicationPrivate::theMainThread.loadAcquire())
+ return QCoreApplicationPrivate::theMainThread.loadRelaxed()->eventDispatcher();
return 0;
}
@@ -2981,7 +2984,7 @@ QAbstractEventDispatcher *QCoreApplication::eventDispatcher()
*/
void QCoreApplication::setEventDispatcher(QAbstractEventDispatcher *eventDispatcher)
{
- QThread *mainThread = QCoreApplicationPrivate::theMainThread;
+ QThread *mainThread = QCoreApplicationPrivate::theMainThread.loadAcquire();
if (!mainThread)
mainThread = QThread::currentThread(); // will also setup theMainThread
mainThread->setEventDispatcher(eventDispatcher);
diff --git a/src/corelib/kernel/qcoreapplication.h b/src/corelib/kernel/qcoreapplication.h
index 3581970765..71ea124fbe 100644
--- a/src/corelib/kernel/qcoreapplication.h
+++ b/src/corelib/kernel/qcoreapplication.h
@@ -208,6 +208,9 @@ private:
static bool notifyInternal2(QObject *receiver, QEvent *);
static bool forwardEvent(QObject *receiver, QEvent *event, QEvent *originatingEvent = nullptr);
#endif
+#if QT_CONFIG(library)
+ static QStringList libraryPathsLocked();
+#endif
static QCoreApplication *self;
@@ -227,6 +230,7 @@ private:
#endif
friend Q_CORE_EXPORT QString qAppName();
friend class QClassFactory;
+ friend class QCommandLineParserPrivate;
};
#ifdef QT_NO_DEPRECATED
diff --git a/src/corelib/kernel/qcoreapplication_p.h b/src/corelib/kernel/qcoreapplication_p.h
index b3479414ab..3bad42d076 100644
--- a/src/corelib/kernel/qcoreapplication_p.h
+++ b/src/corelib/kernel/qcoreapplication_p.h
@@ -52,6 +52,9 @@
//
#include "QtCore/qcoreapplication.h"
+#if QT_CONFIG(commandlineparser)
+#include "QtCore/qcommandlineoption.h"
+#endif
#include "QtCore/qtranslator.h"
#if QT_CONFIG(settings)
#include "QtCore/qsettings.h"
@@ -84,6 +87,11 @@ public:
};
QCoreApplicationPrivate(int &aargc, char **aargv, uint flags);
+
+ // If not inheriting from QObjectPrivate: force this class to be polymorphic
+#ifdef QT_NO_QOBJECT
+ virtual
+#endif
~QCoreApplicationPrivate();
void init();
@@ -99,6 +107,10 @@ public:
static bool checkInstance(const char *method);
+#if QT_CONFIG(commandlineparser)
+ virtual void addQtOptions(QList<QCommandLineOption> *options);
+#endif
+
#ifndef QT_NO_QOBJECT
bool sendThroughApplicationEventFilters(QObject *, QEvent *);
static bool sendThroughObjectEventFilters(QObject *, QEvent *);
@@ -149,7 +161,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/qcoreapplication_win.cpp b/src/corelib/kernel/qcoreapplication_win.cpp
index 4f4a29b41b..961b96710e 100644
--- a/src/corelib/kernel/qcoreapplication_win.cpp
+++ b/src/corelib/kernel/qcoreapplication_win.cpp
@@ -47,6 +47,7 @@
#ifndef QT_NO_QOBJECT
#include "qmutex.h"
#include <private/qthread_p.h>
+#include <private/qlocking_p.h>
#endif
#include "qtextstream.h"
#include <ctype.h>
@@ -64,8 +65,6 @@ using namespace Microsoft::WRL::Wrappers;
QT_BEGIN_NAMESPACE
-int appCmdShow = 0;
-
Q_CORE_EXPORT QString qAppFileName() // get application file name
{
/*
@@ -175,16 +174,12 @@ Q_CORE_EXPORT HINSTANCE qWinAppPrevInst() // get Windows prev app
Q_CORE_EXPORT int qWinAppCmdShow() // get main window show command
{
-#if defined(Q_OS_WINCE)
- return appCmdShow;
-#else
STARTUPINFO startupInfo;
GetStartupInfo(&startupInfo);
return (startupInfo.dwFlags & STARTF_USESHOWWINDOW)
? startupInfo.wShowWindow
: SW_SHOWDEFAULT;
-#endif
}
#endif
@@ -925,7 +920,7 @@ void QCoreApplicationPrivate::removePostedTimerEvent(QObject *object, int timerI
{
QThreadData *data = object->d_func()->threadData;
- QMutexLocker locker(&data->postEventList.mutex);
+ const auto locker = qt_scoped_lock(data->postEventList.mutex);
if (data->postEventList.size() == 0)
return;
for (int i = 0; i < data->postEventList.size(); ++i) {
diff --git a/src/corelib/kernel/qcoreevent.cpp b/src/corelib/kernel/qcoreevent.cpp
index cacbb1e495..4cfc749386 100644
--- a/src/corelib/kernel/qcoreevent.cpp
+++ b/src/corelib/kernel/qcoreevent.cpp
@@ -421,10 +421,10 @@ 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();
+ const uint old = entry.loadRelaxed();
const uint bit = 1U << (which % BitsPerInt);
return !(old & bit) // wasn't taken
&& entry.testAndSetRelaxed(old, old | bit); // still wasn't taken
@@ -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
@@ -445,10 +445,10 @@ struct QBasicAtomicBitField {
// Then again, this should never execute many iterations, so
// leave like this for now:
- for (uint i = next.load(); i < NumBits; ++i) {
+ for (uint i = next.loadRelaxed(); i < NumBits; ++i) {
if (allocateSpecific(i)) {
// remember next (possibly) free id:
- const uint oldNext = next.load();
+ const uint oldNext = next.loadRelaxed();
next.testAndSetRelaxed(oldNext, qMax(i + 1, oldNext));
return i;
}
@@ -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/qcoreglobaldata.cpp b/src/corelib/kernel/qcoreglobaldata.cpp
index 104be1b87b..7ff222f170 100644
--- a/src/corelib/kernel/qcoreglobaldata.cpp
+++ b/src/corelib/kernel/qcoreglobaldata.cpp
@@ -48,7 +48,7 @@ Q_GLOBAL_STATIC(QCoreGlobalData, globalInstance)
QCoreGlobalData::QCoreGlobalData()
#if QT_CONFIG(textcodec)
- : codecForLocale(0)
+ : codecForLocale(nullptr)
#endif
{
}
@@ -56,7 +56,7 @@ QCoreGlobalData::QCoreGlobalData()
QCoreGlobalData::~QCoreGlobalData()
{
#if QT_CONFIG(textcodec)
- codecForLocale = 0;
+ codecForLocale = nullptr;
QList<QTextCodec *> tmp = allCodecs;
allCodecs.clear();
codecCache.clear();
diff --git a/src/corelib/kernel/qdeadlinetimer.cpp b/src/corelib/kernel/qdeadlinetimer.cpp
index 49874b94b4..06b56bb09b 100644
--- a/src/corelib/kernel/qdeadlinetimer.cpp
+++ b/src/corelib/kernel/qdeadlinetimer.cpp
@@ -464,7 +464,7 @@ inline bool TimeReference::toNanoseconds(qint64 *result) const
\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);
@@ -536,7 +536,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);
@@ -562,7 +562,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);
@@ -619,7 +619,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;
@@ -666,7 +666,7 @@ void QDeadlineTimer::setTimerType(Qt::TimerType timerType)
\sa remainingTimeNSecs(), isForever(), hasExpired()
*/
-qint64 QDeadlineTimer::remainingTime() const Q_DECL_NOTHROW
+qint64 QDeadlineTimer::remainingTime() const noexcept
{
if (isForever())
return -1;
@@ -694,7 +694,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;
@@ -708,7 +708,7 @@ qint64 QDeadlineTimer::remainingTimeNSecs() const Q_DECL_NOTHROW
not deal with Forever. In case of underflow the result is saturated to
the minimum possible value, on overflow - the maximum possible value.
*/
-qint64 QDeadlineTimer::rawRemainingTimeNSecs() const Q_DECL_NOTHROW
+qint64 QDeadlineTimer::rawRemainingTimeNSecs() const noexcept
{
QDeadlineTimer now = current(timerType());
TimeReference ref(t1, t2);
@@ -744,7 +744,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 TimeReference::Max;
@@ -777,7 +777,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 TimeReference::Max;
@@ -802,7 +802,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 == TimeReference::Max) {
*this = QDeadlineTimer(Forever, timerType);
@@ -829,7 +829,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;
@@ -849,7 +849,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())
return dt;
diff --git a/src/corelib/kernel/qdeadlinetimer.h b/src/corelib/kernel/qdeadlinetimer.h
index f9ad4063e5..9dd92481d2 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 Q_CORE_EXPORT QDeadlineTimer operator+(QDeadlineTimer dt, qint64 msecs);
@@ -159,7 +159,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();
@@ -185,7 +185,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..57825583dd 100644
--- a/src/corelib/kernel/qelapsedtimer.cpp
+++ b/src/corelib/kernel/qelapsedtimer.cpp
@@ -65,7 +65,7 @@ QT_BEGIN_NAMESPACE
\snippet qelapsedtimer/main.cpp 0
In this example, the timer is started by a call to start() and the
- elapsed timer is calculated by the elapsed() function.
+ elapsed time is calculated by the elapsed() function.
The time elapsed can also be used to recalculate the time available for
another operation, after the first one is complete. This is useful when
@@ -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 3beb158b8a..8becb17461 100644
--- a/src/corelib/kernel/qelapsedtimer_win.cpp
+++ b/src/corelib/kernel/qelapsedtimer_win.cpp
@@ -101,25 +101,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();
@@ -127,40 +127,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_cf.mm b/src/corelib/kernel/qeventdispatcher_cf.mm
index b7b379e2c1..177551467c 100644
--- a/src/corelib/kernel/qeventdispatcher_cf.mm
+++ b/src/corelib/kernel/qeventdispatcher_cf.mm
@@ -56,6 +56,14 @@
# include <UIKit/UIApplication.h>
#endif
+QT_BEGIN_NAMESPACE
+namespace QtPrivate {
+Q_LOGGING_CATEGORY(lcEventDispatcher, "qt.eventdispatcher");
+Q_LOGGING_CATEGORY(lcEventDispatcherTimers, "qt.eventdispatcher.timers");
+}
+using namespace QtPrivate;
+QT_END_NAMESPACE
+
QT_USE_NAMESPACE
/*
@@ -148,9 +156,6 @@ static CFStringRef runLoopMode(NSDictionary *dictionary)
QT_BEGIN_NAMESPACE
-Q_LOGGING_CATEGORY(lcEventDispatcher, "qt.eventdispatcher");
-Q_LOGGING_CATEGORY(lcEventDispatcherTimers, "qt.eventdispatcher.timers");
-
class RunLoopDebugger : public QObject
{
Q_OBJECT
@@ -190,7 +195,7 @@ Q_ENUM_PRINTER(Result);
QDebug operator<<(QDebug s, timespec tv)
{
- s << tv.tv_sec << "." << qSetFieldWidth(9) << qSetPadChar(QChar(48)) << tv.tv_nsec << reset;
+ s << tv.tv_sec << "." << qSetFieldWidth(9) << qSetPadChar(QChar(48)) << tv.tv_nsec << Qt::reset;
return s;
}
@@ -423,7 +428,7 @@ bool QEventDispatcherCoreFoundation::processPostedEvents()
m_processEvents.processedPostedEvents = true;
qCDebug(lcEventDispatcher) << "Sending posted events for"
- << QEventLoop::ProcessEventsFlags(m_processEvents.flags.load());
+ << QEventLoop::ProcessEventsFlags(m_processEvents.flags.loadRelaxed());
QCoreApplication::sendPostedEvents();
return true;
diff --git a/src/corelib/kernel/qeventdispatcher_cf_p.h b/src/corelib/kernel/qeventdispatcher_cf_p.h
index 26191d520c..a2cecd9a93 100644
--- a/src/corelib/kernel/qeventdispatcher_cf_p.h
+++ b/src/corelib/kernel/qeventdispatcher_cf_p.h
@@ -98,8 +98,10 @@ Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(RunLoopModeTracker));
QT_BEGIN_NAMESPACE
-Q_DECLARE_LOGGING_CATEGORY(lcEventDispatcher);
-Q_DECLARE_LOGGING_CATEGORY(lcEventDispatcherTimers)
+namespace QtPrivate {
+Q_CORE_EXPORT Q_DECLARE_LOGGING_CATEGORY(lcEventDispatcher);
+Q_CORE_EXPORT Q_DECLARE_LOGGING_CATEGORY(lcEventDispatcherTimers)
+}
class QEventDispatcherCoreFoundation;
diff --git a/src/corelib/kernel/qeventdispatcher_glib.cpp b/src/corelib/kernel/qeventdispatcher_glib.cpp
index 34c2dde6a8..d9746ef6e2 100644
--- a/src/corelib/kernel/qeventdispatcher_glib.cpp
+++ b/src/corelib/kernel/qeventdispatcher_glib.cpp
@@ -261,7 +261,7 @@ static gboolean postEventSourcePrepare(GSource *s, gint *timeout)
*timeout = canWait ? -1 : 0;
GPostEventSource *source = reinterpret_cast<GPostEventSource *>(s);
- source->d->wakeUpCalled = source->serialNumber.load() != source->lastSerialNumber;
+ source->d->wakeUpCalled = source->serialNumber.loadRelaxed() != source->lastSerialNumber;
return !canWait || source->d->wakeUpCalled;
}
@@ -273,7 +273,7 @@ static gboolean postEventSourceCheck(GSource *source)
static gboolean postEventSourceDispatch(GSource *s, GSourceFunc, gpointer)
{
GPostEventSource *source = reinterpret_cast<GPostEventSource *>(s);
- source->lastSerialNumber = source->serialNumber.load();
+ source->lastSerialNumber = source->serialNumber.loadRelaxed();
QCoreApplication::sendPostedEvents();
source->d->runTimersOnceWithNormalPriority();
return true; // i dunno, george...
@@ -320,7 +320,7 @@ QEventDispatcherGlibPrivate::QEventDispatcherGlibPrivate(GMainContext *context)
// setup post event source
postEventSource = reinterpret_cast<GPostEventSource *>(g_source_new(&postEventSourceFuncs,
sizeof(GPostEventSource)));
- postEventSource->serialNumber.store(1);
+ postEventSource->serialNumber.storeRelaxed(1);
postEventSource->d = this;
g_source_set_can_recurse(&postEventSource->source, true);
g_source_attach(&postEventSource->source, mainContext);
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.cpp b/src/corelib/kernel/qeventdispatcher_unix.cpp
index df0cac0239..5bc65b7110 100644
--- a/src/corelib/kernel/qeventdispatcher_unix.cpp
+++ b/src/corelib/kernel/qeventdispatcher_unix.cpp
@@ -459,7 +459,7 @@ void QEventDispatcherUNIX::unregisterSocketNotifier(QSocketNotifier *notifier)
bool QEventDispatcherUNIX::processEvents(QEventLoop::ProcessEventsFlags flags)
{
Q_D(QEventDispatcherUNIX);
- d->interrupt.store(0);
+ d->interrupt.storeRelaxed(0);
// we are awake, broadcast it
emit awake();
@@ -470,13 +470,13 @@ bool QEventDispatcherUNIX::processEvents(QEventLoop::ProcessEventsFlags flags)
const bool wait_for_events = flags & QEventLoop::WaitForMoreEvents;
const bool canWait = (d->threadData->canWaitLocked()
- && !d->interrupt.load()
+ && !d->interrupt.loadRelaxed()
&& wait_for_events);
if (canWait)
emit aboutToBlock();
- if (d->interrupt.load())
+ if (d->interrupt.loadRelaxed())
return false;
timespec *tm = nullptr;
@@ -545,7 +545,7 @@ void QEventDispatcherUNIX::wakeUp()
void QEventDispatcherUNIX::interrupt()
{
Q_D(QEventDispatcherUNIX);
- d->interrupt.store(1);
+ d->interrupt.storeRelaxed(1);
wakeUp();
}
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 8ff7637b7e..87623f304a 100644
--- a/src/corelib/kernel/qeventdispatcher_win.cpp
+++ b/src/corelib/kernel/qeventdispatcher_win.cpp
@@ -52,7 +52,6 @@
#include "qelapsedtimer.h"
#include "qcoreapplication_p.h"
#include <private/qthread_p.h>
-#include <private/qmutexpool_p.h>
#include <private/qwineventnotifier_p.h>
QT_BEGIN_NAMESPACE
@@ -82,11 +81,13 @@ extern uint qGlobalPostedEventsCount();
enum {
WM_QT_SOCKETNOTIFIER = WM_USER,
WM_QT_SENDPOSTEDEVENTS = WM_USER + 1,
- WM_QT_ACTIVATENOTIFIERS = WM_USER + 2,
+ WM_QT_ACTIVATENOTIFIERS = WM_USER + 2
};
-enum : UINT_PTR {
- SendPostedEventsWindowsTimerId = ~UINT_PTR(1)
+// WM_QT_SENDPOSTEDEVENTS message parameter
+enum {
+ WMWP_QT_TOFOREIGNLOOP = 0,
+ WMWP_QT_FROMWAKEUP
};
class QEventDispatcherWin32Private;
@@ -99,8 +100,8 @@ LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPA
QEventDispatcherWin32Private::QEventDispatcherWin32Private()
: threadId(GetCurrentThreadId()), interrupt(false), internalHwnd(0),
- getMessageHook(0), serialNumber(0), lastSerialNumber(0), sendPostedEventsWindowsTimerId(0),
- wakeUps(0), activateNotifiersPosted(false), winEventNotifierActivatedEvent(NULL)
+ getMessageHook(0), wakeUps(0), activateNotifiersPosted(false),
+ winEventNotifierActivatedEvent(NULL)
{
}
@@ -139,7 +140,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);
@@ -233,30 +238,25 @@ LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPA
return 0;
}
case WM_TIMER:
- if (d->sendPostedEventsWindowsTimerId == 0
- || wp != uint(d->sendPostedEventsWindowsTimerId)) {
- Q_ASSERT(d != 0);
- d->sendTimerEvent(wp);
- return 0;
- }
- // we also use a Windows timer to send posted events when the message queue is full
- Q_FALLTHROUGH();
- case WM_QT_SENDPOSTEDEVENTS: {
- const int localSerialNumber = d->serialNumber.load();
- if (localSerialNumber != d->lastSerialNumber) {
- d->lastSerialNumber = localSerialNumber;
- q->sendPostedEvents();
- }
+ Q_ASSERT(d != 0);
+
+ d->sendTimerEvent(wp);
+ return 0;
+ case WM_QT_SENDPOSTEDEVENTS:
+ Q_ASSERT(d != 0);
+
+ // We send posted events manually, if the window procedure was invoked
+ // by the foreign event loop (e.g. from the native modal dialog).
+ q->sendPostedEvents();
return 0;
- }
} // switch (message)
return DefWindowProc(hwnd, message, wp, lp);
}
-static inline UINT inputTimerMask()
+static inline UINT inputQueueMask()
{
- UINT result = QS_TIMER | QS_INPUT | QS_RAWINPUT;
+ UINT result = QS_ALLEVENTS;
// QTBUG 28513, QTBUG-29097, QTBUG-29435: QS_TOUCH, QS_POINTER became part of
// QS_INPUT in Windows Kit 8. They should not be used when running on pre-Windows 8.
#if WINVER > 0x0601
@@ -270,41 +270,19 @@ LRESULT QT_WIN_CALLBACK qt_GetMessageHook(int code, WPARAM wp, LPARAM lp)
{
QEventDispatcherWin32 *q = qobject_cast<QEventDispatcherWin32 *>(QAbstractEventDispatcher::instance());
Q_ASSERT(q != 0);
-
- if (wp == PM_REMOVE) {
- if (q) {
- MSG *msg = (MSG *) lp;
- QEventDispatcherWin32Private *d = q->d_func();
- const int localSerialNumber = d->serialNumber.load();
- static const UINT mask = inputTimerMask();
- if (HIWORD(GetQueueStatus(mask)) == 0) {
- // no more input or timer events in the message queue, we can allow posted events to be sent normally now
- if (d->sendPostedEventsWindowsTimerId != 0) {
- // stop the timer to send posted events, since we now allow the WM_QT_SENDPOSTEDEVENTS message
- KillTimer(d->internalHwnd, SendPostedEventsWindowsTimerId);
- d->sendPostedEventsWindowsTimerId = 0;
- }
- (void) d->wakeUps.fetchAndStoreRelease(0);
- if (localSerialNumber != d->lastSerialNumber
- // if this message IS the one that triggers sendPostedEvents(), no need to post it again
- && (msg->hwnd != d->internalHwnd
- || msg->message != WM_QT_SENDPOSTEDEVENTS)) {
- PostMessage(d->internalHwnd, WM_QT_SENDPOSTEDEVENTS, 0, 0);
- }
- } else if (d->sendPostedEventsWindowsTimerId == 0
- && localSerialNumber != d->lastSerialNumber) {
- // start a special timer to continue delivering posted events while
- // there are still input and timer messages in the message queue
- d->sendPostedEventsWindowsTimerId = SetTimer(d->internalHwnd,
- SendPostedEventsWindowsTimerId,
- 0, // we specify zero, but Windows uses USER_TIMER_MINIMUM
- NULL);
- // we don't check the return value of SetTimer()... if creating the timer failed, there's little
- // we can do. we just have to accept that posted events will be starved
- }
+ QEventDispatcherWin32Private *d = q->d_func();
+ MSG *msg = reinterpret_cast<MSG *>(lp);
+ static const UINT mask = inputQueueMask();
+
+ if (HIWORD(GetQueueStatus(mask)) == 0 && wp == PM_REMOVE) {
+ // Allow posting WM_QT_SENDPOSTEDEVENTS message.
+ d->wakeUps.storeRelaxed(0);
+ if (!(msg->hwnd == d->internalHwnd && msg->message == WM_QT_SENDPOSTEDEVENTS)) {
+ PostMessage(d->internalHwnd, WM_QT_SENDPOSTEDEVENTS,
+ WMWP_QT_TOFOREIGNLOOP, 0);
}
}
- return q->d_func()->getMessageHook ? CallNextHookEx(0, code, wp, lp) : 0;
+ return d->getMessageHook ? CallNextHookEx(0, code, wp, lp) : 0;
}
// Provide class name and atom for the message window used by
@@ -341,7 +319,7 @@ QWindowsMessageWindowClassContext::QWindowsMessageWindowClassContext()
wc.lpszClassName = className;
atom = RegisterClass(&wc);
if (!atom) {
- qErrnoWarning("%s RegisterClass() failed", qPrintable(qClassName));
+ qErrnoWarning("%ls RegisterClass() failed", qUtf16Printable(qClassName));
delete [] className;
className = 0;
}
@@ -485,36 +463,17 @@ void QEventDispatcherWin32::createInternalHwnd()
return;
d->internalHwnd = qt_create_internal_window(this);
- installMessageHook();
-
- // start all normal timers
- for (int i = 0; i < d->timerVec.count(); ++i)
- d->registerTimer(d->timerVec.at(i));
-}
-
-void QEventDispatcherWin32::installMessageHook()
-{
- Q_D(QEventDispatcherWin32);
-
- if (d->getMessageHook)
- return;
-
// setup GetMessage hook needed to drive our posted events
d->getMessageHook = SetWindowsHookEx(WH_GETMESSAGE, (HOOKPROC) qt_GetMessageHook, NULL, GetCurrentThreadId());
if (Q_UNLIKELY(!d->getMessageHook)) {
int errorCode = GetLastError();
- qFatal("Qt: INTERNAL ERROR: failed to install GetMessage hook: %d, %s",
- errorCode, qPrintable(qt_error_string(errorCode)));
+ qFatal("Qt: INTERNAL ERROR: failed to install GetMessage hook: %d, %ls",
+ errorCode, qUtf16Printable(qt_error_string(errorCode)));
}
-}
-
-void QEventDispatcherWin32::uninstallMessageHook()
-{
- Q_D(QEventDispatcherWin32);
- if (d->getMessageHook)
- UnhookWindowsHookEx(d->getMessageHook);
- d->getMessageHook = 0;
+ // start all normal timers
+ for (int i = 0; i < d->timerVec.count(); ++i)
+ d->registerTimer(d->timerVec.at(i));
}
QEventDispatcherWin32::QEventDispatcherWin32(QObject *parent)
@@ -555,13 +514,15 @@ bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags)
wakeUp(); // trigger a call to sendPostedEvents()
}
- d->interrupt.store(false);
+ d->interrupt.storeRelaxed(false);
emit awake();
+ // To prevent livelocks, send posted events once per iteration.
+ // QCoreApplication::sendPostedEvents() takes care about recursions.
+ sendPostedEvents();
+
bool canWait;
bool retVal = false;
- bool seenWM_QT_SENDPOSTEDEVENTS = false;
- bool needWM_QT_SENDPOSTEDEVENTS = false;
do {
DWORD waitRet = 0;
DWORD nCount = 0;
@@ -571,7 +532,7 @@ bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags)
pHandles = &d->winEventNotifierActivatedEvent;
}
QVarLengthArray<MSG> processedTimers;
- while (!d->interrupt.load()) {
+ while (!d->interrupt.loadRelaxed()) {
MSG msg;
bool haveMessage;
@@ -609,19 +570,13 @@ bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags)
}
}
if (haveMessage) {
- // WinCE doesn't support hooks at all, so we have to call this by hand :(
- if (!d->getMessageHook)
- (void) qt_GetMessageHook(0, PM_REMOVE, reinterpret_cast<LPARAM>(&msg));
-
if (d->internalHwnd == msg.hwnd && msg.message == WM_QT_SENDPOSTEDEVENTS) {
- if (seenWM_QT_SENDPOSTEDEVENTS) {
- // when calling processEvents() "manually", we only want to send posted
- // events once
- needWM_QT_SENDPOSTEDEVENTS = true;
- continue;
- }
- seenWM_QT_SENDPOSTEDEVENTS = true;
- } else if (msg.message == WM_TIMER) {
+ // Set result to 'true', if the message was sent by wakeUp().
+ if (msg.wParam == WMWP_QT_FROMWAKEUP)
+ retVal = true;
+ continue;
+ }
+ if (msg.message == WM_TIMER) {
// avoid live-lock by keeping track of the timers we've already sent
bool found = false;
for (int i = 0; !found && i < processedTimers.count(); ++i) {
@@ -652,7 +607,7 @@ bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags)
// still nothing - wait for message or signalled objects
canWait = (!retVal
- && !d->interrupt.load()
+ && !d->interrupt.loadRelaxed()
&& (flags & QEventLoop::WaitForMoreEvents));
if (canWait) {
emit aboutToBlock();
@@ -665,14 +620,6 @@ bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags)
}
} while (canWait);
- if (!seenWM_QT_SENDPOSTEDEVENTS && (flags & QEventLoop::EventLoopExec) == 0) {
- // when called "manually", always send posted events
- sendPostedEvents();
- }
-
- if (needWM_QT_SENDPOSTEDEVENTS)
- PostMessage(d->internalHwnd, WM_QT_SENDPOSTEDEVENTS, 0, 0);
-
return retVal;
}
@@ -961,7 +908,7 @@ void QEventDispatcherWin32::activateEventNotifiers()
for (int i = 0; i < d->winEventNotifierList.count(); ++i) {
QWinEventNotifier *notifier = d->winEventNotifierList.at(i);
QWinEventNotifierPrivate *nd = QWinEventNotifierPrivate::get(notifier);
- if (nd->signaledCount.load() != 0) {
+ if (nd->signaledCount.loadRelaxed() != 0) {
--nd->signaledCount;
nd->unregisterWaitObject();
d->activateEventNotifier(notifier);
@@ -1015,17 +962,18 @@ int QEventDispatcherWin32::remainingTime(int timerId)
void QEventDispatcherWin32::wakeUp()
{
Q_D(QEventDispatcherWin32);
- d->serialNumber.ref();
if (d->internalHwnd && d->wakeUps.testAndSetAcquire(0, 1)) {
// post a WM_QT_SENDPOSTEDEVENTS to this thread if there isn't one already pending
- PostMessage(d->internalHwnd, WM_QT_SENDPOSTEDEVENTS, 0, 0);
+ if (!PostMessage(d->internalHwnd, WM_QT_SENDPOSTEDEVENTS,
+ WMWP_QT_FROMWAKEUP, 0))
+ qErrnoWarning("QEventDispatcherWin32::wakeUp: Failed to post a message");
}
}
void QEventDispatcherWin32::interrupt()
{
Q_D(QEventDispatcherWin32);
- d->interrupt.store(true);
+ d->interrupt.storeRelaxed(true);
wakeUp();
}
@@ -1056,7 +1004,9 @@ void QEventDispatcherWin32::closingDown()
d->closingDown = true;
- uninstallMessageHook();
+ if (d->getMessageHook)
+ UnhookWindowsHookEx(d->getMessageHook);
+ d->getMessageHook = 0;
}
bool QEventDispatcherWin32::event(QEvent *e)
diff --git a/src/corelib/kernel/qeventdispatcher_win_p.h b/src/corelib/kernel/qeventdispatcher_win_p.h
index a3a0cd1c2f..e6620178d8 100644
--- a/src/corelib/kernel/qeventdispatcher_win_p.h
+++ b/src/corelib/kernel/qeventdispatcher_win_p.h
@@ -73,8 +73,6 @@ class Q_CORE_EXPORT QEventDispatcherWin32 : public QAbstractEventDispatcher
protected:
void createInternalHwnd();
- void installMessageHook();
- void uninstallMessageHook();
public:
explicit QEventDispatcherWin32(QObject *parent = 0);
@@ -172,9 +170,6 @@ public:
HHOOK getMessageHook;
// for controlling when to send posted events
- QAtomicInt serialNumber;
- int lastSerialNumber;
- UINT_PTR sendPostedEventsWindowsTimerId;
QAtomicInt wakeUps;
// timers
diff --git a/src/corelib/kernel/qeventdispatcher_winrt.cpp b/src/corelib/kernel/qeventdispatcher_winrt.cpp
index 600c6c38fd..f7a1f969a8 100644
--- a/src/corelib/kernel/qeventdispatcher_winrt.cpp
+++ b/src/corelib/kernel/qeventdispatcher_winrt.cpp
@@ -44,12 +44,13 @@
#include <QtCore/QHash>
#include <QtCore/QMutex>
#include <QtCore/QSemaphore>
-#include <QtCore/QSharedPointer>
#include <QtCore/qfunctions_winrt.h>
#include <private/qabstracteventdispatcher_p.h>
#include <private/qcoreapplication_p.h>
#include <functional>
+#include <memory>
+
#include <wrl.h>
#include <windows.foundation.h>
#include <windows.system.threading.h>
@@ -300,19 +301,19 @@ HRESULT QEventDispatcherWinRT::runOnMainThread(const std::function<HRESULT()> &d
if (QThread::currentThread() == QCoreApplication::instance()->thread())
return delegate();
- auto semaphore = QSharedPointer<QSemaphore>(new QSemaphore);
- auto ptrSemaphore = new QSharedPointer<QSemaphore>(semaphore);
- auto result = QSharedPointer<HRESULT>(new HRESULT);
- auto ptrResult = new QSharedPointer<HRESULT>(result);
+ struct State {
+ QSemaphore semaphore;
+ HRESULT result;
+ };
+
+ const auto state = std::make_shared<State>();
- QMetaObject::invokeMethod(QCoreApplication::instance(), [delegate, ptrSemaphore, ptrResult]() {
- **ptrResult = delegate();
- delete ptrResult;
- (*ptrSemaphore)->release();
- delete ptrSemaphore;
+ QMetaObject::invokeMethod(QCoreApplication::instance(), [delegate, state]() {
+ const QSemaphoreReleaser releaser{state->semaphore};
+ state->result = delegate();
}, nullptr);
- return semaphore->tryAcquire(1, timeout) ? *result : E_FAIL;
+ return state->semaphore.tryAcquire(1, timeout) ? state->result : E_FAIL;
}
bool QEventDispatcherWinRT::processEvents(QEventLoop::ProcessEventsFlags flags)
diff --git a/src/corelib/kernel/qeventdispatcher_winrt_p.h b/src/corelib/kernel/qeventdispatcher_winrt_p.h
index 8b998a7958..2672f11123 100644
--- a/src/corelib/kernel/qeventdispatcher_winrt_p.h
+++ b/src/corelib/kernel/qeventdispatcher_winrt_p.h
@@ -57,7 +57,7 @@
#include <qt_windows.h>
-namespace std { template <typename T> class function; }
+#include <functional>
QT_BEGIN_NAMESPACE
diff --git a/src/corelib/kernel/qeventloop.cpp b/src/corelib/kernel/qeventloop.cpp
index a6cc51621a..eacd0c4e73 100644
--- a/src/corelib/kernel/qeventloop.cpp
+++ b/src/corelib/kernel/qeventloop.cpp
@@ -135,7 +135,7 @@ bool QEventLoop::processEvents(ProcessEventsFlags flags)
Q_D(QEventLoop);
if (!d->threadData->hasEventDispatcher())
return false;
- return d->threadData->eventDispatcher.load()->processEvents(flags);
+ return d->threadData->eventDispatcher.loadRelaxed()->processEvents(flags);
}
/*!
@@ -165,7 +165,7 @@ int QEventLoop::exec(ProcessEventsFlags flags)
{
Q_D(QEventLoop);
//we need to protect from race condition with QThread::exit
- QMutexLocker locker(&static_cast<QThreadPrivate *>(QObjectPrivate::get(d->threadData->thread))->mutex);
+ QMutexLocker locker(&static_cast<QThreadPrivate *>(QObjectPrivate::get(d->threadData->thread.loadAcquire()))->mutex);
if (d->threadData->quitNow)
return -1;
@@ -225,7 +225,7 @@ int QEventLoop::exec(ProcessEventsFlags flags)
processEvents(flags | WaitForMoreEvents | EventLoopExec);
ref.exceptionCaught = false;
- return d->returnCode.load();
+ return d->returnCode.loadRelaxed();
}
/*!
@@ -279,9 +279,9 @@ void QEventLoop::exit(int returnCode)
if (!d->threadData->hasEventDispatcher())
return;
- d->returnCode.store(returnCode);
+ d->returnCode.storeRelaxed(returnCode);
d->exit.storeRelease(true);
- d->threadData->eventDispatcher.load()->interrupt();
+ d->threadData->eventDispatcher.loadRelaxed()->interrupt();
#ifdef Q_OS_WASM
// QEventLoop::exec() never returns in emscripten. We implement approximate behavior here.
@@ -318,7 +318,7 @@ void QEventLoop::wakeUp()
Q_D(QEventLoop);
if (!d->threadData->hasEventDispatcher())
return;
- d->threadData->eventDispatcher.load()->wakeUp();
+ d->threadData->eventDispatcher.loadRelaxed()->wakeUp();
}
diff --git a/src/corelib/kernel/qeventloop_p.h b/src/corelib/kernel/qeventloop_p.h
index dcbb5c63c6..4ad6d92007 100644
--- a/src/corelib/kernel/qeventloop_p.h
+++ b/src/corelib/kernel/qeventloop_p.h
@@ -63,8 +63,8 @@ public:
inline QEventLoopPrivate()
: inExec(false)
{
- returnCode.store(-1);
- exit.store(true);
+ returnCode.storeRelaxed(-1);
+ exit.storeRelaxed(true);
}
QAtomicInt quitLockRef;
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/qjni.cpp b/src/corelib/kernel/qjni.cpp
index 75a2436d9d..5f652d70e3 100644
--- a/src/corelib/kernel/qjni.cpp
+++ b/src/corelib/kernel/qjni.cpp
@@ -47,9 +47,9 @@
QT_BEGIN_NAMESPACE
-static inline QString keyBase()
+static inline QLatin1String keyBase()
{
- return QStringLiteral("%1%2:%3");
+ return QLatin1String("%1%2:%3");
}
static QString qt_convertJString(jstring string)
@@ -154,7 +154,7 @@ static jmethodID getCachedMethodID(JNIEnv *env,
if (className.isEmpty())
return getMethodID(env, clazz, name, sig, isStatic);
- const QString key = keyBase().arg(QLatin1String(className)).arg(QLatin1String(name)).arg(QLatin1String(sig));
+ const QString key = keyBase().arg(QLatin1String(className), QLatin1String(name), QLatin1String(sig));
QHash<QString, jmethodID>::const_iterator it;
{
@@ -206,7 +206,7 @@ static jfieldID getCachedFieldID(JNIEnv *env,
if (className.isNull())
return getFieldID(env, clazz, name, sig, isStatic);
- const QString key = keyBase().arg(QLatin1String(className)).arg(QLatin1String(name)).arg(QLatin1String(sig));
+ const QString key = keyBase().arg(QLatin1String(className), QLatin1String(name), QLatin1String(sig));
QHash<QString, jfieldID>::const_iterator it;
{
diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp
index 51866a1867..5cb30a74ac 100644
--- a/src/corelib/kernel/qmetaobject.cpp
+++ b/src/corelib/kernel/qmetaobject.cpp
@@ -348,7 +348,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 {
@@ -821,6 +821,7 @@ int QMetaObjectPrivate::indexOfConstructor(const QMetaObject *m, const QByteArra
}
/*!
+ \fn int QMetaObjectPrivate::signalOffset(const QMetaObject *m)
\internal
\since 5.0
@@ -830,14 +831,6 @@ int QMetaObjectPrivate::indexOfConstructor(const QMetaObject *m, const QByteArra
Similar to QMetaObject::methodOffset(), but non-signal methods are
excluded.
*/
-int QMetaObjectPrivate::signalOffset(const QMetaObject *m)
-{
- Q_ASSERT(m != 0);
- int offset = 0;
- for (m = m->d.superdata; m; m = m->d.superdata)
- offset += priv(m->d.data)->signalCount;
- return offset;
-}
/*!
\internal
@@ -960,7 +953,7 @@ static const QMetaObject *QMetaObject_findMetaObject(const QMetaObject *self, co
return self;
if (self->d.relatedMetaObjects) {
Q_ASSERT(priv(self->d.data)->revision >= 2);
- const QMetaObject * const *e = self->d.relatedMetaObjects;
+ const auto *e = self->d.relatedMetaObjects;
if (e) {
while (*e) {
if (const QMetaObject *m =QMetaObject_findMetaObject((*e), name))
@@ -1549,21 +1542,14 @@ bool QMetaObject::invokeMethodImpl(QObject *object, QtPrivate::QSlotObjectBase *
return false;
}
- // args and typesCopy will be deallocated by ~QMetaCallEvent() using free()
- void **args = static_cast<void **>(calloc(1, sizeof(void *)));
- Q_CHECK_PTR(args);
-
- int *types = static_cast<int *>(calloc(1, sizeof(int)));
- Q_CHECK_PTR(types);
-
- QCoreApplication::postEvent(object, new QMetaCallEvent(slot, 0, -1, 1, types, args));
+ QCoreApplication::postEvent(object, new QMetaCallEvent(slot, 0, -1, 1));
} else if (type == Qt::BlockingQueuedConnection) {
#if QT_CONFIG(thread)
if (currentThread == objectThread)
qWarning("QMetaObject::invokeMethod: Dead lock detected");
QSemaphore semaphore;
- QCoreApplication::postEvent(object, new QMetaCallEvent(slot, 0, -1, 0, 0, argv, &semaphore));
+ QCoreApplication::postEvent(object, new QMetaCallEvent(slot, 0, -1, argv, &semaphore));
semaphore.acquire();
#endif // QT_CONFIG(thread)
} else {
@@ -2317,42 +2303,31 @@ bool QMetaMethod::invoke(QObject *object,
return false;
}
- int nargs = 1; // include return type
- void **args = (void **) malloc(paramCount * sizeof(void *));
- Q_CHECK_PTR(args);
- int *types = (int *) malloc(paramCount * sizeof(int));
- Q_CHECK_PTR(types);
- types[0] = 0; // return type
- args[0] = 0;
+ QScopedPointer<QMetaCallEvent> event(new QMetaCallEvent(idx_offset, idx_relative, callFunction, 0, -1, paramCount));
+ int *types = event->types();
+ void **args = event->args();
+ int argIndex = 0;
for (int i = 1; i < paramCount; ++i) {
types[i] = QMetaType::type(typeNames[i]);
if (types[i] == QMetaType::UnknownType && param[i]) {
// Try to register the type and try again before reporting an error.
- int index = nargs - 1;
- void *argv[] = { &types[i], &index };
+ void *argv[] = { &types[i], &argIndex };
QMetaObject::metacall(object, QMetaObject::RegisterMethodArgumentMetaType,
idx_relative + idx_offset, argv);
if (types[i] == -1) {
qWarning("QMetaMethod::invoke: Unable to handle unregistered datatype '%s'",
typeNames[i]);
- for (int x = 1; x < i; ++x) {
- if (types[x] && args[x])
- QMetaType::destroy(types[x], args[x]);
- }
- free(types);
- free(args);
return false;
}
}
if (types[i] != QMetaType::UnknownType) {
args[i] = QMetaType::create(types[i], param[i]);
- ++nargs;
+ ++argIndex;
}
}
- QCoreApplication::postEvent(object, new QMetaCallEvent(idx_offset, idx_relative, callFunction,
- 0, -1, nargs, types, args));
+ QCoreApplication::postEvent(object, event.take());
} else { // blocking queued connection
#if QT_CONFIG(thread)
QThread *currentThread = QThread::currentThread();
@@ -2365,7 +2340,7 @@ bool QMetaMethod::invoke(QObject *object,
QSemaphore semaphore;
QCoreApplication::postEvent(object, new QMetaCallEvent(idx_offset, idx_relative, callFunction,
- 0, -1, 0, 0, param, &semaphore));
+ 0, -1, param, &semaphore));
semaphore.acquire();
#endif // QT_CONFIG(thread)
}
@@ -3030,6 +3005,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 1efb49017f..fcd92afd89 100644
--- a/src/corelib/kernel/qmetaobject.h
+++ b/src/corelib/kernel/qmetaobject.h
@@ -183,7 +183,7 @@ private:
// signature() has been renamed to methodSignature() in Qt 5.
// Warning, that function returns a QByteArray; check the life time if
// you convert to char*.
- char *signature(struct renamedInQt5_warning_checkTheLifeTime * = nullptr) Q_DECL_EQ_DELETE;
+ char *signature(struct renamedInQt5_warning_checkTheLifeTime * = nullptr) = delete;
#endif
static QMetaMethod fromSignalImpl(const QMetaObject *, void **);
@@ -254,6 +254,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..56e3d6cb44 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
{
@@ -208,7 +208,13 @@ struct QMetaObjectPrivate
static int indexOfConstructor(const QMetaObject *m, const QByteArray &name,
int argc, const QArgumentType *types);
Q_CORE_EXPORT static QMetaMethod signal(const QMetaObject *m, int signal_index);
- Q_CORE_EXPORT static int signalOffset(const QMetaObject *m);
+ static inline int signalOffset(const QMetaObject *m) {
+ Q_ASSERT(m != nullptr);
+ int offset = 0;
+ for (m = m->d.superdata; m; m = m->d.superdata)
+ offset += reinterpret_cast<const QMetaObjectPrivate*>(m->d.data)->signalCount;
+ return offset;
+ }
Q_CORE_EXPORT static int absoluteSignalCount(const QMetaObject *m);
Q_CORE_EXPORT static int signalIndex(const QMetaMethod &m);
static bool checkConnectArgs(int signalArgc, const QArgumentType *signalTypes,
@@ -226,15 +232,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.cpp b/src/corelib/kernel/qmetaobjectbuilder.cpp
index d2030f0275..f77c4ce32f 100644
--- a/src/corelib/kernel/qmetaobjectbuilder.cpp
+++ b/src/corelib/kernel/qmetaobjectbuilder.cpp
@@ -747,7 +747,7 @@ void QMetaObjectBuilder::addMetaObject
if ((members & RelatedMetaObjects) != 0) {
Q_ASSERT(priv(prototype->d.data)->revision >= 2);
- const QMetaObject * const *objects = prototype->d.relatedMetaObjects;
+ const auto *objects = prototype->d.relatedMetaObjects;
if (objects) {
while (*objects != 0) {
addRelatedMetaObject(*objects);
@@ -1464,16 +1464,16 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
// Create the relatedMetaObjects block if we need one.
if (d->relatedMetaObjects.size() > 0) {
- ALIGN(size, QMetaObject *);
- const QMetaObject **objects =
- reinterpret_cast<const QMetaObject **>(buf + size);
+ using SuperData = QMetaObject::SuperData;
+ ALIGN(size, SuperData);
+ auto objects = reinterpret_cast<SuperData *>(buf + size);
if (buf) {
meta->d.relatedMetaObjects = objects;
for (index = 0; index < d->relatedMetaObjects.size(); ++index)
objects[index] = d->relatedMetaObjects[index];
- objects[index] = 0;
+ objects[index] = nullptr;
}
- size += sizeof(QMetaObject *) * (d->relatedMetaObjects.size() + 1);
+ size += sizeof(SuperData) * (d->relatedMetaObjects.size() + 1);
}
// Align the final size and return it.
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..356a675517 100644
--- a/src/corelib/kernel/qmetatype.cpp
+++ b/src/corelib/kernel/qmetatype.cpp
@@ -47,10 +47,13 @@
#include "qstringlist.h"
#include "qvector.h"
#include "qlocale.h"
+#if QT_CONFIG(easingcurve)
#include "qeasingcurve.h"
+#endif
#include "quuid.h"
#include "qvariant.h"
#include "qdatastream.h"
+#include "qregexp.h"
#include "qmetatypeswitcher_p.h"
#if QT_CONFIG(regularexpression)
@@ -516,12 +519,12 @@ static const struct { const char * typeName; int typeNameLength; int type; } typ
QT_FOR_EACH_STATIC_TYPE(QT_ADD_STATIC_METATYPE)
QT_FOR_EACH_STATIC_ALIAS_TYPE(QT_ADD_STATIC_METATYPE_ALIASES_ITER)
QT_FOR_EACH_STATIC_HACKS_TYPE(QT_ADD_STATIC_METATYPE_HACKS_ITER)
- {0, 0, QMetaType::UnknownType}
+ {nullptr, 0, QMetaType::UnknownType}
};
-Q_CORE_EXPORT const QMetaTypeInterface *qMetaTypeGuiHelper = 0;
-Q_CORE_EXPORT const QMetaTypeInterface *qMetaTypeWidgetsHelper = 0;
-Q_CORE_EXPORT const QMetaObject *qMetaObjectWidgetsHelper = 0;
+Q_CORE_EXPORT const QMetaTypeInterface *qMetaTypeGuiHelper = nullptr;
+Q_CORE_EXPORT const QMetaTypeInterface *qMetaTypeWidgetsHelper = nullptr;
+Q_CORE_EXPORT const QMetaObject *qMetaObjectWidgetsHelper = nullptr;
class QCustomTypeInfo : public QMetaTypeInterface
{
@@ -556,7 +559,7 @@ public:
{
const QWriteLocker locker(&lock);
const T* &fun = map[k];
- if (fun != 0)
+ if (fun)
return false;
fun = f;
return true;
@@ -565,7 +568,7 @@ public:
const T *function(Key k) const
{
const QReadLocker locker(&lock);
- return map.value(k, 0);
+ return map.value(k, nullptr);
}
void remove(int from, int to)
@@ -586,13 +589,7 @@ QMetaTypeComparatorRegistry;
typedef QMetaTypeFunctionRegistry<QtPrivate::AbstractDebugStreamFunction,int>
QMetaTypeDebugStreamRegistry;
-namespace
-{
-union CheckThatItIsPod
-{ // This should break if QMetaTypeInterface is not a POD type
- QMetaTypeInterface iface;
-};
-}
+Q_STATIC_ASSERT(std::is_pod<QMetaTypeInterface>::value);
Q_DECLARE_TYPEINFO(QCustomTypeInfo, Q_MOVABLE_TYPE);
Q_GLOBAL_STATIC(QVector<QCustomTypeInfo>, customTypes)
@@ -915,7 +912,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;
@@ -972,7 +969,7 @@ static inline int qMetaTypeStaticType(const char *typeName, int length)
The extra \a firstInvalidIndex parameter is an easy way to avoid
iterating over customTypes() a second time in registerNormalizedType().
*/
-static int qMetaTypeCustomType_unlocked(const char *typeName, int length, int *firstInvalidIndex = 0)
+static int qMetaTypeCustomType_unlocked(const char *typeName, int length, int *firstInvalidIndex = nullptr)
{
const QVector<QCustomTypeInfo> * const ct = customTypes();
if (!ct)
@@ -1005,7 +1002,7 @@ int QMetaType::registerType(const char *typeName, Deleter deleter,
{
return registerType(typeName, deleter, creator,
QtMetaTypePrivate::QMetaTypeFunctionHelper<void>::Destruct,
- QtMetaTypePrivate::QMetaTypeFunctionHelper<void>::Construct, 0, TypeFlags(), 0);
+ QtMetaTypePrivate::QMetaTypeFunctionHelper<void>::Construct, 0, TypeFlags(), nullptr);
}
/*!
@@ -1612,7 +1609,7 @@ void *QMetaType::create(int type, const void *copy)
QMetaType info(type);
if (int size = info.sizeOf())
return info.construct(operator new(size), copy);
- return 0;
+ return nullptr;
}
/*!
@@ -1638,14 +1635,18 @@ class TypeConstructor {
static void *Construct(const int type, void *where, const void *copy)
{
if (QModulesPrivate::QTypeModuleInfo<T>::IsGui)
- return Q_LIKELY(qMetaTypeGuiHelper) ? qMetaTypeGuiHelper[type - QMetaType::FirstGuiType].constructor(where, copy) : 0;
+ return Q_LIKELY(qMetaTypeGuiHelper)
+ ? qMetaTypeGuiHelper[type - QMetaType::FirstGuiType].constructor(where, copy)
+ : nullptr;
if (QModulesPrivate::QTypeModuleInfo<T>::IsWidget)
- return Q_LIKELY(qMetaTypeWidgetsHelper) ? qMetaTypeWidgetsHelper[type - QMetaType::FirstWidgetsType].constructor(where, copy) : 0;
+ return Q_LIKELY(qMetaTypeWidgetsHelper)
+ ? qMetaTypeWidgetsHelper[type - QMetaType::FirstWidgetsType].constructor(where, copy)
+ : nullptr;
// This point can be reached only for known types that definition is not available, for example
// in bootstrap mode. We have no other choice then ignore it.
- return 0;
+ return nullptr;
}
};
public:
@@ -1669,7 +1670,7 @@ private:
{
QReadLocker locker(customTypesLock());
if (Q_UNLIKELY(type < QMetaType::User || !ct || ct->count() <= type - QMetaType::User))
- return 0;
+ return nullptr;
const auto &typeInfo = ct->at(type - QMetaType::User);
ctor = typeInfo.constructor;
tctor = typeInfo.typedConstructor;
@@ -1714,7 +1715,7 @@ private:
void *QMetaType::construct(int type, void *where, const void *copy)
{
if (!where)
- return 0;
+ return nullptr;
TypeConstructor constructor(type, where);
return QMetaTypeSwitcher::switcher<void*>(constructor, type, copy);
}
@@ -1860,7 +1861,7 @@ private:
int QMetaType::sizeOf(int type)
{
SizeOf sizeOf(type);
- return QMetaTypeSwitcher::switcher<int>(sizeOf, type, 0);
+ return QMetaTypeSwitcher::switcher<int>(sizeOf, type);
}
namespace {
@@ -1924,7 +1925,7 @@ private:
QMetaType::TypeFlags QMetaType::typeFlags(int type)
{
Flags flags(type);
- return static_cast<QMetaType::TypeFlags>(QMetaTypeSwitcher::switcher<quint32>(flags, type, 0));
+ return static_cast<QMetaType::TypeFlags>(QMetaTypeSwitcher::switcher<quint32>(flags, type));
}
#ifndef QT_BOOTSTRAPPED
@@ -1947,17 +1948,21 @@ public:
{
static const QMetaObject *MetaObject(int type) {
if (QModulesPrivate::QTypeModuleInfo<T>::IsGui)
- return Q_LIKELY(qMetaTypeGuiHelper) ? qMetaTypeGuiHelper[type - QMetaType::FirstGuiType].metaObject : 0;
+ return Q_LIKELY(qMetaTypeGuiHelper)
+ ? qMetaTypeGuiHelper[type - QMetaType::FirstGuiType].metaObject
+ : nullptr;
if (QModulesPrivate::QTypeModuleInfo<T>::IsWidget)
- return Q_LIKELY(qMetaTypeWidgetsHelper) ? qMetaTypeWidgetsHelper[type - QMetaType::FirstWidgetsType].metaObject : 0;
+ return Q_LIKELY(qMetaTypeWidgetsHelper)
+ ? qMetaTypeWidgetsHelper[type - QMetaType::FirstWidgetsType].metaObject
+ : nullptr;
return 0;
}
};
template <typename T>
const QMetaObject *delegate(const T *) { return MetaObjectImpl<T>::MetaObject(m_type); }
- const QMetaObject *delegate(const void*) { return 0; }
- const QMetaObject *delegate(const QMetaTypeSwitcher::UnknownType*) { return 0; }
+ const QMetaObject *delegate(const void*) { return nullptr; }
+ const QMetaObject *delegate(const QMetaTypeSwitcher::UnknownType*) { return nullptr; }
const QMetaObject *delegate(const QMetaTypeSwitcher::NotBuiltinType*) { return customMetaObject(m_type); }
private:
const int m_type;
@@ -1965,10 +1970,10 @@ private:
{
const QVector<QCustomTypeInfo> * const ct = customTypes();
if (Q_UNLIKELY(!ct || type < QMetaType::User))
- return 0;
+ return nullptr;
QReadLocker locker(customTypesLock());
if (Q_UNLIKELY(ct->count() <= type - QMetaType::User))
- return 0;
+ return nullptr;
return ct->at(type - QMetaType::User).metaObject;
}
};
@@ -1986,10 +1991,10 @@ const QMetaObject *QMetaType::metaObjectForType(int type)
{
#ifndef QT_BOOTSTRAPPED
MetaObject mo(type);
- return QMetaTypeSwitcher::switcher<const QMetaObject*>(mo, type, 0);
+ return QMetaTypeSwitcher::switcher<const QMetaObject*>(mo, type);
#else
Q_UNUSED(type);
- return 0;
+ return nullptr;
#endif
}
@@ -2186,7 +2191,7 @@ private:
QMetaType QMetaType::typeInfo(const int type)
{
TypeInfo typeInfo(type);
- QMetaTypeSwitcher::switcher<void>(typeInfo, type, 0);
+ QMetaTypeSwitcher::switcher<void>(typeInfo, type);
return (typeInfo.info.constructor || typeInfo.info.typedConstructor)
? QMetaType(static_cast<ExtensionFlag>(QMetaType::CreateEx | QMetaType::DestroyEx |
(typeInfo.info.typedConstructor ? QMetaType::ConstructEx | QMetaType::DestructEx : 0))
@@ -2306,7 +2311,7 @@ void QMetaType::dtor()
void *QMetaType::createExtended(const void *copy) const
{
if (m_typeId == QMetaType::UnknownType)
- return 0;
+ return nullptr;
if (Q_UNLIKELY(m_typedConstructor && !m_constructor))
return m_typedConstructor(m_typeId, operator new(m_size), copy);
return m_constructor(operator new(m_size), copy);
@@ -2386,7 +2391,7 @@ uint QMetaType::sizeExtended() const
*/
QMetaType::TypeFlags QMetaType::flagsExtended() const
{
- return 0;
+ return { };
}
/*!
@@ -2399,7 +2404,7 @@ QMetaType::TypeFlags QMetaType::flagsExtended() const
*/
const QMetaObject *QMetaType::metaObjectExtended() const
{
- return 0;
+ return nullptr;
}
@@ -2408,7 +2413,7 @@ namespace QtPrivate
const QMetaObject *metaObjectForQWidget()
{
if (!qMetaTypeWidgetsHelper)
- return 0;
+ return nullptr;
return qMetaObjectWidgetsHelper;
}
}
diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h
index a47fbfe28d..d41f7ee80e 100644
--- a/src/corelib/kernel/qmetatype.h
+++ b/src/corelib/kernel/qmetatype.h
@@ -94,6 +94,13 @@ inline Q_DECL_CONSTEXPR int qMetaTypeId();
#define QT_FOR_EACH_STATIC_PRIMITIVE_POINTER(F)\
F(VoidStar, 31, void*) \
+#if QT_CONFIG(easingcurve)
+#define QT_FOR_EACH_STATIC_EASINGCURVE(F)\
+ F(QEasingCurve, 29, QEasingCurve)
+#else
+#define QT_FOR_EACH_STATIC_EASINGCURVE(F)
+#endif
+
#if QT_CONFIG(itemmodel)
#define QT_FOR_EACH_STATIC_ITEMMODEL_CLASS(F)\
F(QModelIndex, 42, QModelIndex) \
@@ -122,7 +129,7 @@ inline Q_DECL_CONSTEXPR int qMetaTypeId();
F(QPoint, 25, QPoint) \
F(QPointF, 26, QPointF) \
F(QRegExp, 27, QRegExp) \
- F(QEasingCurve, 29, QEasingCurve) \
+ QT_FOR_EACH_STATIC_EASINGCURVE(F) \
F(QUuid, 30, QUuid) \
F(QVariant, 41, QVariant) \
F(QRegularExpression, 44, QRegularExpression) \
@@ -216,7 +223,7 @@ inline Q_DECL_CONSTEXPR int qMetaTypeId();
F(QQueue) \
F(QStack) \
F(QSet) \
- F(QLinkedList)
+ /*end*/
#define QT_FOR_EACH_AUTOMATIC_TEMPLATE_2ARG(F) \
F(QHash, class) \
@@ -849,7 +856,7 @@ struct VariantData
const uint flags;
private:
// copy constructor allowed to be implicit to silence level 4 warning from MSVC
- VariantData &operator=(const VariantData &) Q_DECL_EQ_DELETE;
+ VariantData &operator=(const VariantData &) = delete;
};
template<typename const_iterator>
@@ -1715,12 +1722,17 @@ namespace QtPrivate {
}
};
+ // hack to delay name lookup to instantiation time by making
+ // EnableInternalData a dependent name:
+ template <typename T>
+ struct EnableInternalDataWrap;
+
template<typename T>
struct QSmartPointerConvertFunctor<QWeakPointer<T> >
{
QObject* operator()(const QWeakPointer<T> &p) const
{
- return p.data();
+ return QtPrivate::EnableInternalDataWrap<T>::internalData(p);
}
};
}
@@ -1994,7 +2006,7 @@ struct QMetaTypeId< SINGLE_ARG_TEMPLATE<T> > \
static int qt_metatype_id() \
{ \
static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0); \
- if (const int id = metatype_id.load()) \
+ if (const int id = metatype_id.loadRelaxed()) \
return id; \
const char *tName = QMetaType::typeName(qMetaTypeId<T>()); \
Q_ASSERT(tName); \
diff --git a/src/corelib/kernel/qmetatype_p.h b/src/corelib/kernel/qmetatype_p.h
index eba0207ea7..d743d5a5c7 100644
--- a/src/corelib/kernel/qmetatype_p.h
+++ b/src/corelib/kernel/qmetatype_p.h
@@ -140,12 +140,12 @@ public:
/*saveOp*/(QtMetaTypePrivate::QMetaTypeFunctionHelper<Type, QtMetaTypePrivate::TypeDefinition<Type>::IsAvailable>::Save), \
/*loadOp*/(QtMetaTypePrivate::QMetaTypeFunctionHelper<Type, QtMetaTypePrivate::TypeDefinition<Type>::IsAvailable>::Load),
# define QT_METATYPE_INTERFACE_INIT_EMPTY_DATASTREAM_IMPL(Type) \
- /*saveOp*/ 0, \
- /*loadOp*/ 0,
+ /*saveOp*/ nullptr, \
+ /*loadOp*/ nullptr,
#else
# define QT_METATYPE_INTERFACE_INIT_EMPTY_DATASTREAM_IMPL(Type) \
- /*saveOp*/ 0, \
- /*loadOp*/ 0,
+ /*saveOp*/ nullptr, \
+ /*loadOp*/ nullptr,
# define QT_METATYPE_INTERFACE_INIT_DATASTREAM_IMPL(Type) \
QT_METATYPE_INTERFACE_INIT_EMPTY_DATASTREAM_IMPL(Type)
#endif
@@ -153,7 +153,7 @@ public:
#ifndef QT_BOOTSTRAPPED
#define METAOBJECT_DELEGATE(Type) (QtPrivate::MetaObjectForType<Type>::value())
#else
-#define METAOBJECT_DELEGATE(Type) 0
+#define METAOBJECT_DELEGATE(Type) nullptr
#endif
#define QT_METATYPE_INTERFACE_INIT_IMPL(Type, DATASTREAM_DELEGATE) \
@@ -184,11 +184,11 @@ public:
#define QT_METATYPE_INTERFACE_INIT_EMPTY() \
{ \
QT_METATYPE_INTERFACE_INIT_EMPTY_DATASTREAM_IMPL(void) \
- /*constructor*/ 0, \
- /*destructor*/ 0, \
+ /*constructor*/ nullptr, \
+ /*destructor*/ nullptr, \
/*size*/ 0, \
/*flags*/ 0, \
- /*metaObject*/ 0 , \
+ /*metaObject*/ nullptr , \
/*typedConstructor*/ nullptr, \
/*typedDestructor*/ nullptr \
}
@@ -206,7 +206,9 @@ template<> struct TypeDefinition<QCborArray> { static const bool IsAvailable = f
template<> struct TypeDefinition<QCborMap> { static const bool IsAvailable = false; };
template<> struct TypeDefinition<QCborSimpleType> { static const bool IsAvailable = false; };
template<> struct TypeDefinition<QCborValue> { static const bool IsAvailable = false; };
+#if QT_CONFIG(easingcurve)
template<> struct TypeDefinition<QEasingCurve> { static const bool IsAvailable = false; };
+#endif
template<> struct TypeDefinition<QJsonArray> { static const bool IsAvailable = false; };
template<> struct TypeDefinition<QJsonDocument> { static const bool IsAvailable = false; };
template<> struct TypeDefinition<QJsonObject> { static const bool IsAvailable = false; };
diff --git a/src/corelib/kernel/qmetatypeswitcher_p.h b/src/corelib/kernel/qmetatypeswitcher_p.h
index 154fb8ab7f..dabc70f4b0 100644
--- a/src/corelib/kernel/qmetatypeswitcher_p.h
+++ b/src/corelib/kernel/qmetatypeswitcher_p.h
@@ -60,7 +60,7 @@ public:
class NotBuiltinType; // type is not a built-in type, but it may be a custom type or an unknown type
class UnknownType; // type not known to QMetaType system
template<class ReturnType, class DelegateObject>
- static ReturnType switcher(DelegateObject &logic, int type, const void *data);
+ static ReturnType switcher(DelegateObject &logic, int type, const void *data = nullptr);
};
diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp
index 598ce75bd4..cf107498dd 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/
@@ -58,6 +58,7 @@
#include <qdebug.h>
#include <qpair.h>
#include <qvarlengtharray.h>
+#include <qscopeguard.h>
#include <qset.h>
#if QT_CONFIG(thread)
#include <qsemaphore.h>
@@ -77,6 +78,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.storeRelease(callback_set);
+}
QDynamicMetaObjectData::~QDynamicMetaObjectData()
{
@@ -86,12 +93,6 @@ QAbstractDynamicMetaObject::~QAbstractDynamicMetaObject()
{
}
-
-struct QSlotObjectBaseDeleter { // for use with QScopedPointer<QSlotObjectBase,...>
- static void cleanup(QtPrivate::QSlotObjectBase *slot) {
- if (slot) slot->destroyIfLastRef();
- }
-};
static int *queuedConnectionTypes(const QList<QByteArray> &typeNames)
{
int *types = new int [typeNames.count() + 1];
@@ -146,10 +147,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 +160,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, &currentSender);
- switched = true;
- }
-
- inline ~QConnectionSenderSwitcher()
- {
- if (switched)
- QObjectPrivate::resetCurrentSender(receiver, &currentSender, 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;
@@ -201,6 +168,12 @@ int (*QAbstractDeclarativeData::receivers)(QAbstractDeclarativeData *, const QO
bool (*QAbstractDeclarativeData::isSignalConnected)(QAbstractDeclarativeData *, const QObject *, int) = 0;
void (*QAbstractDeclarativeData::setWidgetParent)(QObject *, QObject *) = 0;
+/*!
+ \fn QObjectData::QObjectData()
+ \internal
+ */
+
+
QObjectData::~QObjectData() {}
QMetaObject *QObjectData::dynamicMetaObject() const
@@ -209,7 +182,7 @@ QMetaObject *QObjectData::dynamicMetaObject() const
}
QObjectPrivate::QObjectPrivate(int version)
- : threadData(0), connectionLists(0), senders(0), currentSender(0), currentChildBeingDeleted(0)
+ : threadData(0), currentChildBeingDeleted(0)
{
#ifdef QT_BUILD_INTERNAL
// Don't check the version parameter in internal builds.
@@ -232,7 +205,6 @@ QObjectPrivate::QObjectPrivate(int version)
receiveChildEvents = true;
postedEvents = 0;
extraData = 0;
- connectedSignals[0] = connectedSignals[1] = 0;
metaObject = 0;
isWindow = false;
deleteLaterCalled = false;
@@ -241,10 +213,10 @@ QObjectPrivate::QObjectPrivate(int version)
QObjectPrivate::~QObjectPrivate()
{
if (extraData && !extraData->runningTimers.isEmpty()) {
- if (Q_LIKELY(threadData->thread == QThread::currentThread())) {
+ if (Q_LIKELY(threadData->thread.loadAcquire() == QThread::currentThread())) {
// unregister pending timers
if (threadData->hasEventDispatcher())
- threadData->eventDispatcher.load()->unregisterTimers(q_ptr);
+ threadData->eventDispatcher.loadRelaxed()->unregisterTimers(q_ptr);
// release the timer ids back to the pool
for (int i = 0; i < extraData->runningTimers.size(); ++i)
@@ -285,59 +257,22 @@ static void computeOffsets(const QMetaObject *metaobject, int *signalOffset, int
}
}
-/*
- This vector contains the all connections from an object.
-
- Each object may have one vector containing the lists of
- connections for a given signal. The index in the vector correspond
- to the signal index. The signal index is the one returned by
- QObjectPrivate::signalIndex (not QMetaObject::indexOfSignal).
- Negative index means connections to all signals.
-
- This vector is protected by the object mutex (signalSlotMutexes())
-
- Each Connection is also part of a 'senders' linked list. The mutex
- of the receiver must be locked when touching the pointers of this
- linked list.
-*/
-class QObjectConnectionListVector : public QVector<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.loadRelaxed();
+ 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.loadRelaxed()->at(signal_index).first.loadRelaxed();
+
+ while (c) {
+ if (c->receiver.loadRelaxed() == receiver)
+ return true;
+ c = c->nextConnectionList.loadRelaxed();
}
}
return false;
@@ -346,21 +281,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.loadRelaxed();
+ 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.loadRelaxed()->at(signal_index).first.loadRelaxed();
+
+ while (c) {
+ QObject *r = c->receiver.loadRelaxed();
+ if (r)
+ returnValue << r;
+ c = c->nextConnectionList.loadRelaxed();
}
}
return returnValue;
@@ -370,9 +303,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.loadRelaxed();
+ if (cd) {
+ QBasicMutexLocker locker(signalSlotLock(q_func()));
+ for (Connection *c = cd->senders; c; c = c->next)
+ returnValue << c->sender;
+ }
return returnValue;
}
@@ -389,103 +325,271 @@ 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.loadRelaxed();
+ cd->resizeSignalVector(signal + 1);
+
+ ConnectionList &connectionList = cd->connectionsForSignal(signal);
+ if (connectionList.last.loadRelaxed()) {
+ Q_ASSERT(connectionList.last.loadRelaxed()->receiver.loadRelaxed());
+ connectionList.last.loadRelaxed()->nextConnectionList.storeRelaxed(c);
} else {
- connectionList.first = c;
+ connectionList.first.storeRelaxed(c);
}
- connectionList.last = c;
+ c->id = ++cd->currentConnectionId;
+ c->prevConnectionList = connectionList.last.loadRelaxed();
+ connectionList.last.storeRelaxed(c);
- cleanConnectionLists();
+ QObjectPrivate *rd = QObjectPrivate::get(c->receiver.loadRelaxed());
+ rd->ensureConnectionData();
- c->prev = &(QObjectPrivate::get(c->receiver)->senders);
+ c->prev = &(rd->connections.loadRelaxed()->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.loadRelaxed());
+ ConnectionList &connections = signalVector.loadRelaxed()->at(c->signal_index);
+ c->receiver.storeRelaxed(nullptr);
+ QThreadData *td = c->receiverThreadData.loadRelaxed();
+ if (td)
+ td->deref();
+ c->receiverThreadData.storeRelaxed(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.loadRelaxed(); cc; cc = cc->nextConnectionList.loadRelaxed()) {
+ 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.loadRelaxed() == c)
+ connections.first.storeRelaxed(c->nextConnectionList.loadRelaxed());
+ if (connections.last.loadRelaxed() == c)
+ connections.last.storeRelaxed(c->prevConnectionList);
+ Q_ASSERT(signalVector.loadRelaxed()->at(c->signal_index).first.loadRelaxed() != c);
+ Q_ASSERT(signalVector.loadRelaxed()->at(c->signal_index).last.loadRelaxed() != c);
+
+ // keep c->nextConnectionList intact, as it might still get accessed by activate
+ Connection *n = c->nextConnectionList.loadRelaxed();
+ if (n)
+ n->prevConnectionList = c->prevConnectionList;
+ if (c->prevConnectionList)
+ c->prevConnectionList->nextConnectionList.storeRelaxed(n);
+ c->prevConnectionList = nullptr;
+
+ Q_ASSERT(c != orphaned.loadRelaxed());
+ // add c to orphanedConnections
+ c->nextInOrphanList = orphaned.loadRelaxed();
+ orphaned.storeRelaxed(c);
+
+#ifndef QT_NO_DEBUG
+ found = false;
+ for (Connection *cc = connections.first.loadRelaxed(); cc; cc = cc->nextConnectionList.loadRelaxed()) {
+ 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.loadAcquire() > 1)
+ return;
+
+ // 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.loadRelaxed();
+ orphaned.storeRelaxed(nullptr);
+ }
+ deleteOrphaned(c);
+}
- // Correct the connection list's last pointer.
- // As conectionList.last could equal last, this could be a noop
- connectionList.last = last;
+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.loadRelaxed());
+ Q_ASSERT(!c->prev);
+ c->freeSlotObject();
+ c->deref();
+ }
+ o = next;
+ }
+}
- 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;
- }
+/*! \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.loadRelaxed();
+ if (!cd)
+ return false;
+ SignalVector *signalVector = cd->signalVector.loadRelaxed();
+ if (!signalVector)
+ return false;
+
+ if (signalVector->at(-1).first.loadRelaxed())
+ return true;
+
+ if (signalIndex < uint(cd->signalVectorCount())) {
+ const QObjectPrivate::Connection *c = signalVector->at(signalIndex).first.loadRelaxed();
+ while (c) {
+ if (c->receiver.loadRelaxed())
+ return true;
+ c = c->nextConnectionList.loadRelaxed();
}
- connectionLists->dirty = false;
}
+ return false;
+}
+
+bool QObjectPrivate::maybeSignalConnected(uint signalIndex) const
+{
+ ConnectionData *cd = connections.loadRelaxed();
+ if (!cd)
+ return false;
+ SignalVector *signalVector = cd->signalVector.loadRelaxed();
+ if (!signalVector)
+ return false;
+
+ if (signalVector->at(-1).first.loadAcquire())
+ return true;
+
+ if (signalIndex < uint(cd->signalVectorCount())) {
+ const QObjectPrivate::Connection *c = signalVector->at(signalIndex).first.loadAcquire();
+ return c != nullptr;
+ }
+ return false;
+}
+
+/*!
+ \internal
+ */
+QAbstractMetaCallEvent::~QAbstractMetaCallEvent()
+{
+#if QT_CONFIG(thread)
+ if (semaphore_)
+ semaphore_->release();
+#endif
}
/*!
\internal
*/
-QMetaCallEvent::QMetaCallEvent(ushort method_offset, ushort method_relative, QObjectPrivate::StaticMetaCallFunction callFunction,
+inline void QMetaCallEvent::allocArgs()
+{
+ if (!d.nargs_)
+ return;
+
+ constexpr size_t each = sizeof(void*) + sizeof(int);
+ void *const memory = d.nargs_ * each > sizeof(prealloc_) ?
+ calloc(d.nargs_, each) : prealloc_;
+
+ Q_CHECK_PTR(memory);
+ d.args_ = static_cast<void **>(memory);
+}
+
+/*!
+ \internal
+
+ Used for blocking queued connections, just passes \a args through without
+ allocating any memory.
+ */
+QMetaCallEvent::QMetaCallEvent(ushort method_offset, ushort method_relative,
+ QObjectPrivate::StaticMetaCallFunction callFunction,
const QObject *sender, int signalId,
- int nargs, int *types, void **args, QSemaphore *semaphore)
- : QEvent(MetaCall), slotObj_(0), sender_(sender), signalId_(signalId),
- nargs_(nargs), types_(types), args_(args), semaphore_(semaphore),
- callFunction_(callFunction), method_offset_(method_offset), method_relative_(method_relative)
-{ }
+ void **args, QSemaphore *semaphore)
+ : QAbstractMetaCallEvent(sender, signalId, semaphore),
+ d({nullptr, args, callFunction, 0, method_offset, method_relative}),
+ prealloc_()
+{
+}
+
+/*!
+ \internal
+
+ Used for blocking queued connections, just passes \a args through without
+ allocating any memory.
+ */
+QMetaCallEvent::QMetaCallEvent(QtPrivate::QSlotObjectBase *slotO,
+ const QObject *sender, int signalId,
+ void **args, QSemaphore *semaphore)
+ : QAbstractMetaCallEvent(sender, signalId, semaphore),
+ d({slotO, args, nullptr, 0, 0, ushort(-1)}),
+ prealloc_()
+{
+ if (d.slotObj_)
+ d.slotObj_->ref();
+}
/*!
\internal
+
+ Allocates memory for \a nargs; code creating an event needs to initialize
+ the void* and int arrays by accessing \a args() and \a types(), respectively.
*/
-QMetaCallEvent::QMetaCallEvent(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))
+QMetaCallEvent::QMetaCallEvent(ushort method_offset, ushort method_relative,
+ QObjectPrivate::StaticMetaCallFunction callFunction,
+ const QObject *sender, int signalId,
+ int nargs)
+ : QAbstractMetaCallEvent(sender, signalId),
+ d({nullptr, nullptr, callFunction, nargs, method_offset, method_relative}),
+ prealloc_()
+{
+ allocArgs();
+}
+
+/*!
+ \internal
+
+ Allocates memory for \a nargs; code creating an event needs to initialize
+ the void* and int arrays by accessing \a args() and \a types(), respectively.
+ */
+QMetaCallEvent::QMetaCallEvent(QtPrivate::QSlotObjectBase *slotO,
+ const QObject *sender, int signalId,
+ int nargs)
+ : QAbstractMetaCallEvent(sender, signalId),
+ d({slotO, nullptr, nullptr, nargs, 0, ushort(-1)}),
+ prealloc_()
{
- if (slotObj_)
- slotObj_->ref();
+ if (d.slotObj_)
+ d.slotObj_->ref();
+ allocArgs();
}
/*!
@@ -493,20 +597,17 @@ QMetaCallEvent::QMetaCallEvent(QtPrivate::QSlotObjectBase *slotO, const QObject
*/
QMetaCallEvent::~QMetaCallEvent()
{
- if (types_) {
- for (int i = 0; i < nargs_; ++i) {
- if (types_[i] && args_[i])
- QMetaType::destroy(types_[i], args_[i]);
+ if (d.nargs_) {
+ int *typeIDs = types();
+ for (int i = 0; i < d.nargs_; ++i) {
+ if (typeIDs[i] && d.args_[i])
+ QMetaType::destroy(typeIDs[i], d.args_[i]);
}
- free(types_);
- free(args_);
+ if (reinterpret_cast<void*>(d.args_) != reinterpret_cast<void*>(prealloc_))
+ free(d.args_);
}
-#if QT_CONFIG(thread)
- if (semaphore_)
- semaphore_->release();
-#endif
- if (slotObj_)
- slotObj_->destroyIfLastRef();
+ if (d.slotObj_)
+ d.slotObj_->destroyIfLastRef();
}
/*!
@@ -514,12 +615,13 @@ QMetaCallEvent::~QMetaCallEvent()
*/
void QMetaCallEvent::placeMetaCall(QObject *object)
{
- if (slotObj_) {
- slotObj_->call(object, args_);
- } else if (callFunction_ && method_offset_ <= object->metaObject()->methodOffset()) {
- callFunction_(object, QMetaObject::InvokeMetaMethod, method_relative_, args_);
+ if (d.slotObj_) {
+ d.slotObj_->call(object, d.args_);
+ } else if (d.callFunction_ && d.method_offset_ <= object->metaObject()->methodOffset()) {
+ d.callFunction_(object, QMetaObject::InvokeMetaMethod, d.method_relative_, d.args_);
} else {
- QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, method_offset_ + method_relative_, args_);
+ QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod,
+ d.method_offset_ + d.method_relative_, d.args_);
}
}
@@ -773,8 +875,8 @@ static bool check_parent_thread(QObject *parent,
QThreadData *currentThreadData)
{
if (parent && parentThreadData != currentThreadData) {
- QThread *parentThread = parentThreadData->thread;
- QThread *currentThread = currentThreadData->thread;
+ QThread *parentThread = parentThreadData->thread.loadAcquire();
+ QThread *currentThread = currentThreadData->thread.loadAcquire();
qWarning("QObject: Cannot create children for a parent that is in a different thread.\n"
"(Parent is %s(%p), parent's thread is %s(%p), current thread is %s(%p)",
parent->metaObject()->className(),
@@ -806,6 +908,8 @@ static bool check_parent_thread(QObject *parent,
QObject::QObject(QObject *parent)
: d_ptr(new QObjectPrivate)
{
+ Q_ASSERT_X(this != parent, Q_FUNC_INFO, "Cannot parent a QObject to itself");
+
Q_D(QObject);
d_ptr->q_ptr = this;
d->threadData = (parent && !parent->thread()) ? parent->d_func()->threadData : QThreadData::current();
@@ -834,6 +938,8 @@ QObject::QObject(QObject *parent)
QObject::QObject(QObjectPrivate &dd, QObject *parent)
: d_ptr(&dd)
{
+ Q_ASSERT_X(this != parent, Q_FUNC_INFO, "Cannot parent a QObject to itself");
+
Q_D(QObject);
d_ptr->q_ptr = this;
d->threadData = (parent && !parent->thread()) ? parent->d_func()->threadData : QThreadData::current();
@@ -894,15 +1000,15 @@ QObject::~QObject()
d->wasDeleted = true;
d->blockSig = 0; // unblock signals so we always emit destroyed()
- QtSharedPointer::ExternalRefCountData *sharedRefcount = d->sharedRefcount.load();
+ QtSharedPointer::ExternalRefCountData *sharedRefcount = d->sharedRefcount.loadRelaxed();
if (sharedRefcount) {
- if (sharedRefcount->strongref.load() > 0) {
+ if (sharedRefcount->strongref.loadRelaxed() > 0) {
qWarning("QObject: shared QObject was deleted directly. The program is malformed and may crash.");
// but continue deleting, it's too late to stop anyway
}
// indicate to all QWeakPointers that this QObject has now been deleted
- sharedRefcount->strongref.store(0);
+ sharedRefcount->strongref.storeRelaxed(0);
if (!sharedRefcount->weakref.deref())
delete sharedRefcount;
}
@@ -921,92 +1027,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.loadRelaxed();
+ 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;
- }
-
- QMutex *m = signalSlotLock(c->receiver);
- bool needToUnlock = QOrderedMutexLocker::relock(signalSlotMutex, m);
-
- if (c->receiver) {
- *c->prev = c->next;
- if (c->next) c->next->prev = c->prev;
- }
- c->receiver = 0;
- if (needToUnlock)
- m->unlock();
-
- connectionList.first = c->nextConnectionList;
-
- // The destroy operation must happen outside the lock
- if (c->isSlotObject) {
- c->isSlotObject = false;
- locker.unlock();
- c->slotObj->destroyIfLastRef();
- locker.relock();
- }
- c->deref();
+ int receiverCount = cd->signalVectorCount();
+ for (int signal = -1; signal < receiverCount; ++signal) {
+ QObjectPrivate::ConnectionList &connectionList = cd->connectionsForSignal(signal);
+
+ while (QObjectPrivate::Connection *c = connectionList.first.loadRelaxed()) {
+ Q_ASSERT(c->receiver.loadAcquire());
+
+ QBasicMutex *m = signalSlotLock(c->receiver.loadRelaxed());
+ bool needToUnlock = QOrderedMutexLocker::relock(signalSlotMutex, m);
+ if (c->receiver.loadAcquire()) {
+ cd->removeConnection(c);
+ Q_ASSERT(connectionList.first.loadRelaxed() != 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.loadAcquire());
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.loadRelaxed();
+ Q_ASSERT(senderData);
QtPrivate::QSlotObjectBase *slotObj = nullptr;
if (node->isSlotObject) {
@@ -1014,19 +1084,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.storeRelaxed(0);
}
+ if (cd && !cd->ref.deref())
+ delete cd;
+ d->connections.storeRelaxed(nullptr);
if (!d->children.isEmpty())
d->deleteChildren();
@@ -1046,7 +1121,7 @@ QObject::~QObject()
QObjectPrivate::Connection::~Connection()
{
if (ownArgumentTypes) {
- const int *v = argumentTypes.load();
+ const int *v = argumentTypes.loadRelaxed();
if (v != &DIRECT_CONNECTION_ONLY)
delete [] v;
}
@@ -1253,9 +1328,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.loadRelaxed()) {
+ QBasicMutexLocker locker(signalSlotLock(this));
+ d_func()->ensureConnectionData();
+ }
+ QObjectPrivate::Sender sender(this, const_cast<QObject*>(mce->sender()), mce->signalId());
mce->placeMetaCall(this);
break;
@@ -1264,7 +1343,7 @@ bool QObject::event(QEvent *e)
case QEvent::ThreadChange: {
Q_D(QObject);
QThreadData *threadData = d->threadData;
- QAbstractEventDispatcher *eventDispatcher = threadData->eventDispatcher.load();
+ QAbstractEventDispatcher *eventDispatcher = threadData->eventDispatcher.loadRelaxed();
if (eventDispatcher) {
QList<QAbstractEventDispatcher::TimerInfo> timers = eventDispatcher->registeredTimers(this);
if (!timers.isEmpty()) {
@@ -1415,7 +1494,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;
@@ -1430,7 +1509,7 @@ bool QObject::blockSignals(bool block) Q_DECL_NOTHROW
*/
QThread *QObject::thread() const
{
- return d_func()->threadData->thread;
+ return d_func()->threadData->thread.loadAcquire();
}
/*!
@@ -1477,7 +1556,7 @@ void QObject::moveToThread(QThread *targetThread)
{
Q_D(QObject);
- if (d->threadData->thread == targetThread) {
+ if (d->threadData->thread.loadAcquire() == targetThread) {
// object is already in this thread
return;
}
@@ -1493,13 +1572,13 @@ void QObject::moveToThread(QThread *targetThread)
QThreadData *currentData = QThreadData::current();
QThreadData *targetData = targetThread ? QThreadData::get2(targetThread) : nullptr;
- if (d->threadData->thread == 0 && currentData == targetData) {
+ if (d->threadData->thread.loadAcquire() == 0 && currentData == targetData) {
// one exception to the rule: we allow moving objects with no thread affinity to the current thread
currentData = d->threadData;
} else if (d->threadData != currentData) {
qWarning("QObject::moveToThread: Current thread (%p) is not the object's thread (%p).\n"
"Cannot move to target thread (%p)\n",
- currentData->thread.load(), d->threadData->thread.load(), targetData ? targetData->thread.load() : nullptr);
+ currentData->thread.loadRelaxed(), d->threadData->thread.loadRelaxed(), targetData ? targetData->thread.loadRelaxed() : nullptr);
#ifdef Q_OS_MAC
qWarning("You might be loading two sets of Qt binaries into the same process. "
@@ -1516,6 +1595,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);
@@ -1561,13 +1643,35 @@ void QObjectPrivate::setThreadData_helper(QThreadData *currentData, QThreadData
}
if (eventsMoved > 0 && targetData->hasEventDispatcher()) {
targetData->canWait = false;
- targetData->eventDispatcher.load()->wakeUp();
+ targetData->eventDispatcher.loadRelaxed()->wakeUp();
}
// the current emitting thread shouldn't restore currentSender after calling moveToThread()
- if (currentSender)
- currentSender->ref = 0;
- currentSender = 0;
+ ConnectionData *cd = connections.loadRelaxed();
+ 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.loadRelaxed();
+ if (r) {
+ Q_ASSERT(r == q);
+ targetData->ref();
+ QThreadData *old = c->receiverThreadData.loadRelaxed();
+ if (old)
+ old->deref();
+ c->receiverThreadData.storeRelaxed(targetData);
+ }
+ c = c->next;
+ }
+ }
+
+ }
// set new thread data
targetData->ref();
@@ -1584,7 +1688,7 @@ void QObjectPrivate::_q_reregisterTimers(void *pointer)
{
Q_Q(QObject);
QList<QAbstractEventDispatcher::TimerInfo> *timerList = reinterpret_cast<QList<QAbstractEventDispatcher::TimerInfo> *>(pointer);
- QAbstractEventDispatcher *eventDispatcher = threadData->eventDispatcher.load();
+ QAbstractEventDispatcher *eventDispatcher = threadData->eventDispatcher.loadRelaxed();
for (int i = 0; i < timerList->size(); ++i) {
const QAbstractEventDispatcher::TimerInfo &ti = timerList->at(i);
eventDispatcher->registerTimer(ti.timerId, ti.interval, ti.timerType, q);
@@ -1650,7 +1754,7 @@ int QObject::startTimer(int interval, Qt::TimerType timerType)
qWarning("QObject::startTimer: Timers cannot be started from another thread");
return 0;
}
- int timerId = d->threadData->eventDispatcher.load()->registerTimer(interval, timerType, this);
+ int timerId = d->threadData->eventDispatcher.loadRelaxed()->registerTimer(interval, timerType, this);
if (!d->extraData)
d->extraData = new QObjectPrivate::ExtraData;
d->extraData->runningTimers.append(timerId);
@@ -1716,16 +1820,16 @@ void QObject::killTimer(int id)
int at = d->extraData ? d->extraData->runningTimers.indexOf(id) : -1;
if (at == -1) {
// timer isn't owned by this object
- qWarning("QObject::killTimer(): Error: timer id %d is not valid for object %p (%s, %s), timer has not been killed",
+ qWarning("QObject::killTimer(): Error: timer id %d is not valid for object %p (%s, %ls), timer has not been killed",
id,
this,
metaObject()->className(),
- qPrintable(objectName()));
+ qUtf16Printable(objectName()));
return;
}
if (d->threadData->hasEventDispatcher())
- d->threadData->eventDispatcher.load()->unregisterTimer(id);
+ d->threadData->eventDispatcher.loadRelaxed()->unregisterTimer(id);
d->extraData->runningTimers.remove(at);
QAbstractEventDispatcherPrivate::releaseTimerId(id);
@@ -2026,8 +2130,25 @@ void QObjectPrivate::deleteChildren()
void QObjectPrivate::setParent_helper(QObject *o)
{
Q_Q(QObject);
+ Q_ASSERT_X(q != o, Q_FUNC_INFO, "Cannot parent a QObject to itself");
+#ifdef QT_DEBUG
+ const auto checkForParentChildLoops = qScopeGuard([&](){
+ int depth = 0;
+ auto p = parent;
+ while (p) {
+ if (++depth == CheckForParentChildLoopsWarnDepth) {
+ qWarning("QObject %p (class: '%s', object name: '%s') may have a loop in its parent-child chain; "
+ "this is undefined behavior",
+ q, q->metaObject()->className(), qPrintable(q->objectName()));
+ }
+ p = p->parent();
+ }
+ });
+#endif
+
if (o == parent)
return;
+
if (parent) {
QObjectPrivate *parentD = parent->d_func();
if (parentD->isDeletingChildren && wasDeleted
@@ -2378,13 +2499,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.loadRelaxed();
+ 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;
@@ -2419,14 +2541,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.loadRelaxed();
+ 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();
}
}
@@ -2482,15 +2605,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.loadRelaxed();
+ QBasicMutexLocker locker(signalSlotLock(this));
+ if (cd && signal_index < cd->signalVectorCount()) {
+ const QObjectPrivate::Connection *c = cd->signalVector.loadRelaxed()->at(signal_index).first.loadRelaxed();
+ while (c) {
+ receivers += c->receiver.loadRelaxed() ? 1 : 0;
+ c = c->nextConnectionList.loadRelaxed();
}
}
}
@@ -2530,22 +2651,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);
}
/*!
@@ -3308,49 +3415,49 @@ 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.loadRelaxed();
+ if (type & Qt::UniqueConnection && scd) {
+ if (scd->signalVectorCount() > signal_index) {
+ const QObjectPrivate::Connection *c2 = scd->signalVector.loadRelaxed()->at(signal_index).first.loadRelaxed();
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.loadRelaxed() == receiver && c2->method() == method_index_absolute)
+ return nullptr;
+ c2 = c2->nextConnectionList.loadRelaxed();
}
}
type &= Qt::UniqueConnection - 1;
}
- QScopedPointer<QObjectPrivate::Connection> c(new QObjectPrivate::Connection);
+ std::unique_ptr<QObjectPrivate::Connection> c{new QObjectPrivate::Connection};
c->sender = s;
c->signal_index = signal_index;
- c->receiver = r;
+ c->receiver.storeRelaxed(r);
+ QThreadData *td = r->d_func()->threadData;
+ td->ref();
+ c->receiverThreadData.storeRelaxed(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->argumentTypes.storeRelaxed(types);
c->callFunction = callFunction;
- QObjectPrivate::get(s)->addConnection(signal_index, c.data());
+ QObjectPrivate::get(s)->addConnection(signal_index, c.get());
locker.unlock();
QMetaMethod smethod = QMetaObjectPrivate::signal(smeta, signal_index);
if (smethod.isValid())
s->connectNotify(smethod);
- return c.take();
+ return c.release();
}
/*!
@@ -3386,47 +3493,38 @@ bool QMetaObject::disconnectOne(const QObject *sender, int signal_index,
\internal
Helper function to remove the connection from the senders list and set the receivers to \nullptr
*/
-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.loadRelaxed();
while (c) {
- if (c->receiver
- && (receiver == 0 || (c->receiver == receiver
+ QObject *r = c->receiver.loadRelaxed();
+ 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.loadRelaxed())
+ 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.loadRelaxed();
}
return success;
}
@@ -3445,43 +3543,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.loadRelaxed();
+ 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);
@@ -3597,10 +3686,9 @@ 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();
+ const int *argumentTypes = c->argumentTypes.loadRelaxed();
if (!argumentTypes) {
QMetaMethod m = QMetaObjectPrivate::signal(sender->metaObject(), signal);
argumentTypes = queuedConnectionTypes(m.parameterTypes());
@@ -3609,7 +3697,7 @@ static void queued_activate(QObject *sender, int signal, QObjectPrivate::Connect
if (!c->argumentTypes.testAndSetOrdered(0, argumentTypes)) {
if (argumentTypes != &DIRECT_CONNECTION_ONLY)
delete [] argumentTypes;
- argumentTypes = c->argumentTypes.load();
+ argumentTypes = c->argumentTypes.loadRelaxed();
}
}
if (argumentTypes == &DIRECT_CONNECTION_ONLY) // cannot activate
@@ -3617,142 +3705,129 @@ static void queued_activate(QObject *sender, int signal, QObjectPrivate::Connect
int nargs = 1; // include return type
while (argumentTypes[nargs-1])
++nargs;
- int *types = (int *) malloc(nargs*sizeof(int));
- Q_CHECK_PTR(types);
- void **args = (void **) malloc(nargs*sizeof(void *));
- Q_CHECK_PTR(args);
+
+ QBasicMutexLocker locker(signalSlotLock(c->receiver.loadRelaxed()));
+ if (!c->receiver.loadRelaxed()) {
+ // the connection has been disconnected before we got the lock
+ return;
+ }
+ if (c->isSlotObject)
+ c->slotObj->ref();
+ locker.unlock();
+
+ QMetaCallEvent *ev = c->isSlotObject ?
+ new QMetaCallEvent(c->slotObj, sender, signal, nargs) :
+ new QMetaCallEvent(c->method_offset, c->method_relative, c->callFunction, sender, signal, nargs);
+
+ void **args = ev->args();
+ int *types = ev->types();
+
types[0] = 0; // return type
- args[0] = 0; // return value
+ args[0] = nullptr; // return value
if (nargs > 1) {
for (int n = 1; n < nargs; ++n)
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;
- }
}
- 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);
-}
+ locker.relock();
+ if (c->isSlotObject)
+ c->slotObj->destroyIfLastRef();
+ if (!c->receiver.loadRelaxed()) {
+ // the connection has been disconnected while we were unlocked
+ locker.unlock();
+ delete ev;
+ return;
+ }
-/*!
- \internal
- */
-void QMetaObject::activate(QObject *sender, const QMetaObject *m, int local_signal_index,
- void **argv)
-{
- activate(sender, QMetaObjectPrivate::signalOffset(m), local_signal_index, argv);
+ QCoreApplication::postEvent(c->receiver.loadRelaxed(), ev);
}
-/*!
- \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;
Q_TRACE_SCOPE(QMetaObject_activate, sender, signal_index);
- if (sender->d_func()->isDeclarativeSignalConnected(signal_index)
+ if (sp->isDeclarativeSignalConnected(signal_index)
&& QAbstractDeclarativeData::signalEmitted) {
Q_TRACE_SCOPE(QMetaObject_activate_declarative_signal, sender, signal_index);
- QAbstractDeclarativeData::signalEmitted(sender->d_func()->declarativeData, sender,
+ QAbstractDeclarativeData::signalEmitted(sp->declarativeData, sender,
signal_index, argv);
}
- 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) {
- // 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.loadAcquire() : 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);
+ if (callbacks_enabled && signal_spy_set->signal_end_callback != nullptr)
+ signal_spy_set->signal_end_callback(sender, signal_index);
+ return;
}
- {
- 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;
- }
- }
+ if (callbacks_enabled && signal_spy_set->signal_begin_callback != nullptr)
+ signal_spy_set->signal_begin_callback(sender, signal_index, argv);
- 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);
- return;
- }
+ bool senderDeleted = false;
+ {
+ Q_ASSERT(sp->connections.loadAcquire());
+ QObjectPrivate::ConnectionDataPointer connections(sp->connections.loadRelaxed());
+ QObjectPrivate::SignalVector *signalVector = connections->signalVector.loadRelaxed();
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.loadRelaxed();
+ // 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.loadRelaxed();
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.loadRelaxed();
+ if (!c)
+ continue;
do {
- if (!c->receiver)
+ QObject * const receiver = c->receiver.loadRelaxed();
+ if (!receiver)
continue;
- QObject * const receiver = c->receiver;
- const bool receiverInSameThread = currentThreadId == receiver->d_func()->threadData->threadId.load();
+ QThreadData *td = c->receiverThreadData.loadRelaxed();
+ if (!td)
+ continue;
+
+ bool receiverInSameThread;
+ if (inSenderThread) {
+ receiverInSameThread = currentThreadId == td->threadId.loadRelaxed();
+ } else {
+ // need to lock before reading the threadId, because moveToThread() could interfere
+ QMutexLocker lock(signalSlotLock(receiver));
+ receiverInSameThread = currentThreadId == td->threadId.loadRelaxed();
+ }
+
// 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) {
@@ -3763,92 +3838,113 @@ 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.loadAcquire())
+ continue;
+ QMetaCallEvent *ev = c->isSlotObject ?
+ new QMetaCallEvent(c->slotObj, sender, signal_index, argv, &semaphore) :
+ new QMetaCallEvent(c->method_offset, c->method_relative, c->callFunction,
+ sender, signal_index, argv, &semaphore);
+ QCoreApplication::postEvent(receiver, ev);
+ }
semaphore.acquire();
- 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();
+
+ struct Deleter {
+ void operator()(QtPrivate::QSlotObjectBase *slot) const {
+ if (slot) slot->destroyIfLastRef();
+ }
+ };
+ const std::unique_ptr<QtPrivate::QSlotObjectBase, Deleter> obj{c->slotObj};
{
- Q_TRACE_SCOPE(QMetaObject_activate_slot_functor, obj.data());
+ Q_TRACE_SCOPE(QMetaObject_activate_slot_functor, obj.get());
obj->call(receiver, argv);
}
-
- // 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_SCOPE(QMetaObject_activate_slot, receiver, methodIndex);
callFunction(receiver, QMetaObject::InvokeMetaMethod, method_relative, argv);
}
- 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_SCOPE(QMetaObject_activate_slot, receiver, method);
- metacall(receiver, QMetaObject::InvokeMetaMethod, method, argv);
+ QMetaObject::metacall(receiver, QMetaObject::InvokeMetaMethod, method, argv);
}
- 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.loadRelaxed()) != 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.loadRelaxed() == 0)
+ senderDeleted = true;
}
+ if (!senderDeleted) {
+ sp->connections.loadRelaxed()->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);
+ }
}
/*!
\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.loadRelaxed()))
+ 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.loadRelaxed()))
+ 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)
@@ -3861,7 +3957,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.
@@ -4044,6 +4140,7 @@ static void dumpRecursive(int level, const QObject *object)
}
}
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
/*!
\overload
\obsolete
@@ -4057,6 +4154,7 @@ void QObject::dumpObjectTree()
{
const_cast<const QObject *>(this)->dumpObjectTree();
}
+#endif
/*!
Dumps a tree of children to the debug output.
@@ -4071,6 +4169,7 @@ void QObject::dumpObjectTree() const
dumpRecursive(0, this);
}
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
/*!
\overload
\obsolete
@@ -4085,6 +4184,7 @@ void QObject::dumpObjectInfo()
{
const_cast<const QObject *>(this)->dumpObjectInfo();
}
+#endif
/*!
Dumps information about signal connections, etc. for this object
@@ -4101,37 +4201,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.loadRelaxed();
+ if (cd && cd->signalVectorCount()) {
+ QObjectPrivate::SignalVector *signalVector = cd->signalVector.loadRelaxed();
+ for (int signal_index = 0; signal_index < signalVector->count(); ++signal_index) {
+ const QObjectPrivate::Connection *c = signalVector->at(signal_index).first.loadRelaxed();
+ 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.loadRelaxed()) {
qDebug(" <Disconnected receiver>");
- c = c->nextConnectionList;
+ c = c->nextConnectionList.loadRelaxed();
continue;
}
if (c->isSlotObject) {
qDebug(" <functor or function pointer>");
- c = c->nextConnectionList;
+ c = c->nextConnectionList.loadRelaxed();
continue;
}
- const QMetaObject *receiverMetaObject = c->receiver->metaObject();
+ const QMetaObject *receiverMetaObject = c->receiver.loadRelaxed()->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.loadRelaxed()->objectName().isEmpty() ? "unnamed" : qPrintable(c->receiver.loadRelaxed()->objectName()),
method.methodSignature().constData());
- c = c->nextConnectionList;
+ c = c->nextConnectionList.loadRelaxed();
}
}
} else {
@@ -4141,8 +4244,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());
@@ -4159,16 +4262,22 @@ void QObject::dumpObjectInfo() const
}
#ifndef QT_NO_USERDATA
+static QBasicAtomicInteger<uint> user_data_registration = Q_BASIC_ATOMIC_INITIALIZER(0);
+
/*!
\internal
*/
uint QObject::registerUserData()
{
- static int user_data_registration = 0;
- return user_data_registration++;
+ return user_data_registration.fetchAndAddRelaxed(1);
}
/*!
+ \fn QObjectUserData::QObjectUserData()
+ \internal
+ */
+
+/*!
\internal
*/
QObjectUserData::~QObjectUserData()
@@ -4489,6 +4598,24 @@ QDebug operator<<(QDebug dbg, const QObject *o)
Q_NAMESPACE makes an external variable, \c{staticMetaObject}, available.
\c{staticMetaObject} is of type QMetaObject and provides access to the
enums declared with Q_ENUM_NS/Q_FLAG_NS.
+
+ \sa Q_NAMESPACE_EXPORT
+*/
+
+/*!
+ \macro Q_NAMESPACE_EXPORT(EXPORT_MACRO)
+ \relates QObject
+ \since 5.14
+
+ The Q_NAMESPACE_EXPORT macro can be used to add QMetaObject capabilities
+ to a namespace.
+
+ It works exactly like the Q_NAMESPACE macro. However, the external
+ \c{staticMetaObject} variable that gets defined in the namespace
+ is declared with the supplied \c{EXPORT_MACRO} qualifier. This is
+ useful if the object needs to be exported from a dynamic library.
+
+ \sa Q_NAMESPACE, {Creating Shared Libraries}
*/
/*!
@@ -4873,37 +5000,39 @@ 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.loadRelaxed()) {
+ QObjectPrivate::ConnectionData *connections = QObjectPrivate::get(s)->connections.loadRelaxed();
+ if (connections->signalVectorCount() > signal_index) {
+ const QObjectPrivate::Connection *c2 = connections->signalVector.loadRelaxed()->at(signal_index).first.loadRelaxed();
while (c2) {
- if (c2->receiver == receiver && c2->isSlotObject && c2->slotObj->compare(slot)) {
+ if (c2->receiver.loadRelaxed() == receiver && c2->isSlotObject && c2->slotObj->compare(slot)) {
slotObj->destroyIfLastRef();
return QMetaObject::Connection();
}
- c2 = c2->nextConnectionList;
+ c2 = c2->nextConnectionList.loadRelaxed();
}
}
type = static_cast<Qt::ConnectionType>(type ^ Qt::UniqueConnection);
}
- QScopedPointer<QObjectPrivate::Connection> c(new QObjectPrivate::Connection);
+ std::unique_ptr<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.storeRelaxed(td);
+ c->receiver.storeRelaxed(r);
c->slotObj = slotObj;
c->connectionType = type;
c->isSlotObject = true;
if (types) {
- c->argumentTypes.store(types);
+ c->argumentTypes.storeRelaxed(types);
c->ownArgumentTypes = false;
}
- QObjectPrivate::get(s)->addConnection(signal_index, c.data());
- QMetaObject::Connection ret(c.take());
+ QObjectPrivate::get(s)->addConnection(signal_index, c.get());
+ QMetaObject::Connection ret(c.release());
locker.unlock();
QMetaMethod method = QMetaObjectPrivate::signal(senderMetaObject, signal_index);
@@ -4925,35 +5054,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.loadRelaxed();
+ 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.loadRelaxed();
+ 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.loadRelaxed();
+ 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;
@@ -5036,7 +5165,7 @@ bool QObject::disconnectImpl(const QObject *sender, void **signal, const QObject
}
if (!senderMetaObject) {
qWarning("QObject::disconnect: signal not found in %s", sender->metaObject()->className());
- return QMetaObject::Connection(0);
+ return false;
}
signal_index += QMetaObjectPrivate::signalOffset(senderMetaObject);
}
@@ -5135,7 +5264,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.loadRelaxed();
}
diff --git a/src/corelib/kernel/qobject.h b/src/corelib/kernel/qobject.h
index fc1d7c956c..540b8b32c1 100644
--- a/src/corelib/kernel/qobject.h
+++ b/src/corelib/kernel/qobject.h
@@ -71,12 +71,16 @@ class QObjectPrivate;
class QObject;
class QThread;
class QWidget;
+class QAccessibleWidget;
#ifndef QT_NO_REGEXP
class QRegExp;
#endif
#if QT_CONFIG(regularexpression)
class QRegularExpression;
#endif
+#if !QT_DEPRECATED_SINCE(5, 14) || QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+# define QT_NO_USERDATA
+#endif
#ifndef QT_NO_USERDATA
class QObjectUserData;
#endif
@@ -93,7 +97,9 @@ Q_CORE_EXPORT void qt_qFindChildren_helper(const QObject *parent, const QRegular
Q_CORE_EXPORT QObject *qt_qFindChild_helper(const QObject *parent, const QString &name, const QMetaObject &mo, Qt::FindChildOptions options);
class Q_CORE_EXPORT QObjectData {
+ Q_DISABLE_COPY(QObjectData)
public:
+ QObjectData() = default;
virtual ~QObjectData() = 0;
QObject *q_ptr;
QObject *parent;
@@ -111,6 +117,10 @@ public:
int postedEvents;
QDynamicMetaObjectData *metaObject;
QMetaObject *dynamicMetaObject() const;
+
+#ifdef QT_DEBUG
+ enum { CheckForParentChildLoopsWarnDepth = 4096 };
+#endif
};
@@ -143,8 +153,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);
@@ -399,8 +409,11 @@ public:
#endif // QT_NO_PROPERTIES
#ifndef QT_NO_USERDATA
+ QT_DEPRECATED_VERSION_5_14
static uint registerUserData();
+ QT_DEPRECATED_VERSION_X_5_14("Use setProperty()")
void setUserData(uint id, QObjectUserData* data);
+ QT_DEPRECATED_VERSION_X_5_14("Use property()")
QObjectUserData* userData(uint id) const;
#endif // QT_NO_USERDATA
@@ -437,7 +450,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;
@@ -447,6 +460,7 @@ protected:
friend class QCoreApplication;
friend class QCoreApplicationPrivate;
friend class QWidget;
+ friend class QAccessibleWidget;
friend class QThreadData;
private:
@@ -468,12 +482,14 @@ 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
class Q_CORE_EXPORT QObjectUserData {
+ Q_DISABLE_COPY(QObjectUserData)
public:
+ QObjectUserData() = default;
virtual ~QObjectUserData();
};
#endif
@@ -541,17 +557,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;
@@ -559,20 +573,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)
@@ -580,7 +593,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:
@@ -595,7 +608,6 @@ QSignalBlocker &QSignalBlocker::operator=(QSignalBlocker &&other) Q_DECL_NOTHROW
}
return *this;
}
-#endif
QSignalBlocker::~QSignalBlocker()
{
@@ -603,13 +615,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..feafcaf323 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.loadRelaxed());
+ 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.loadRelaxed();
+ previous = cd->currentSender;
+ cd->currentSender = this;
+ }
+ }
+ ~Sender()
+ {
+ if (receiver)
+ receiver->d_func()->connections.loadRelaxed()->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() const { 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.loadRelaxed());
+ SignalVector *v = signalVector.loadRelaxed();
+ 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.loadRelaxed() && ref.loadAcquire() == 1)
+ cleanOrphanedConnectionsImpl(sender);
+ }
+ void cleanOrphanedConnectionsImpl(QObject *sender);
+
+ ConnectionList &connectionsForSignal(int signal)
+ {
+ return signalVector.loadRelaxed()->at(signal);
+ }
+
+ void resizeSignalVector(uint size) {
+ SignalVector *vector = this->signalVector.loadRelaxed();
+ 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.storeRelaxed(newVector);
+ if (vector) {
+ vector->nextInOrphanList = orphaned.loadRelaxed();
+ orphaned.storeRelaxed(ConnectionOrSignalVector::fromSignalVector(vector));
+ }
+ }
+ int signalVectorCount() const {
+ return signalVector.loadAcquire() ? signalVector.loadRelaxed()->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.loadRelaxed())
+ return;
+ ConnectionData *cd = new ConnectionData;
+ cd->ref.ref();
+ connections.storeRelaxed(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,37 +482,74 @@ 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:
- QMetaCallEvent(ushort method_offset, ushort method_relative, QObjectPrivate::StaticMetaCallFunction callFunction , const QObject *sender, int signalId,
- int nargs = 0, int *types = nullptr, void **args = nullptr, QSemaphore *semaphore = nullptr);
- /*! \internal
- \a signalId is in the signal index range (see QObjectPrivate::signalIndex()).
- */
- QMetaCallEvent(QtPrivate::QSlotObjectBase *slotObj, const QObject *sender, int signalId,
- int nargs = 0, int *types = nullptr, void **args = nullptr, QSemaphore *semaphore = nullptr);
+ QAbstractMetaCallEvent(const QObject *sender, int signalId, QSemaphore *semaphore = nullptr)
+ : QEvent(MetaCall), signalId_(signalId), sender_(sender)
+#if QT_CONFIG(thread)
+ , semaphore_(semaphore)
+#endif
+ { Q_UNUSED(semaphore); }
+ ~QAbstractMetaCallEvent();
- ~QMetaCallEvent();
+ virtual void placeMetaCall(QObject *object) = 0;
- 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);
private:
- QtPrivate::QSlotObjectBase *slotObj_;
- const QObject *sender_;
int signalId_;
- int nargs_;
- int *types_;
- void **args_;
+ const QObject *sender_;
+#if QT_CONFIG(thread)
QSemaphore *semaphore_;
- QObjectPrivate::StaticMetaCallFunction callFunction_;
- ushort method_offset_;
- ushort method_relative_;
+#endif
+};
+
+class Q_CORE_EXPORT QMetaCallEvent : public QAbstractMetaCallEvent
+{
+public:
+ // blocking queued with semaphore - args always owned by caller
+ QMetaCallEvent(ushort method_offset, ushort method_relative,
+ QObjectPrivate::StaticMetaCallFunction callFunction,
+ const QObject *sender, int signalId,
+ void **args, QSemaphore *semaphore);
+ QMetaCallEvent(QtPrivate::QSlotObjectBase *slotObj,
+ const QObject *sender, int signalId,
+ void **args, QSemaphore *semaphore);
+
+ // queued - args allocated by event, copied by caller
+ QMetaCallEvent(ushort method_offset, ushort method_relative,
+ QObjectPrivate::StaticMetaCallFunction callFunction,
+ const QObject *sender, int signalId,
+ int nargs);
+ QMetaCallEvent(QtPrivate::QSlotObjectBase *slotObj,
+ const QObject *sender, int signalId,
+ int nargs);
+
+ ~QMetaCallEvent() override;
+
+ inline int id() const { return d.method_offset_ + d.method_relative_; }
+ inline const void * const* args() const { return d.args_; }
+ inline void ** args() { return d.args_; }
+ inline const int *types() const { return reinterpret_cast<int*>(d.args_ + d.nargs_); }
+ inline int *types() { return reinterpret_cast<int*>(d.args_ + d.nargs_); }
+
+ virtual void placeMetaCall(QObject *object) override;
+
+private:
+ inline void allocArgs();
+
+ struct Data {
+ QtPrivate::QSlotObjectBase *slotObj_;
+ void **args_;
+ QObjectPrivate::StaticMetaCallFunction callFunction_;
+ int nargs_;
+ ushort method_offset_;
+ ushort method_relative_;
+ } d;
+ // preallocate enough space for three arguments
+ char prealloc_[3*(sizeof(void*) + sizeof(int))];
};
class QBoolBlocker
diff --git a/src/corelib/kernel/qobjectdefs.h b/src/corelib/kernel/qobjectdefs.h
index b84e87959a..dc2d832fe5 100644
--- a/src/corelib/kernel/qobjectdefs.h
+++ b/src/corelib/kernel/qobjectdefs.h
@@ -1,7 +1,7 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
+** Copyright (C) 2019 The Qt Company Ltd.
+** Copyright (C) 2019 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -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)
@@ -209,12 +201,16 @@ private: \
QT_ANNOTATE_CLASS(qt_qgadget, "") \
/*end*/
-/* qmake ignore Q_NAMESPACE */
-#define Q_NAMESPACE \
- extern const QMetaObject staticMetaObject; \
+/* qmake ignore Q_NAMESPACE_EXPORT */
+#define Q_NAMESPACE_EXPORT(...) \
+ extern __VA_ARGS__ const QMetaObject staticMetaObject; \
QT_ANNOTATE_CLASS(qt_qnamespace, "") \
/*end*/
+/* qmake ignore Q_NAMESPACE */
+#define Q_NAMESPACE Q_NAMESPACE_EXPORT() \
+ /*end*/
+
#endif // QT_NO_META_MACROS
#else // Q_MOC_RUN
@@ -344,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;
@@ -576,18 +572,48 @@ struct Q_CORE_EXPORT QMetaObject
int static_metacall(Call, int, void **) const;
static int metacall(QObject *, Call, int, void **);
+ template <const QMetaObject &MO> static constexpr const QMetaObject *staticMetaObject()
+ {
+ return &MO;
+ }
+
+ struct SuperData {
+ const QMetaObject *direct;
+ SuperData() = default;
+ constexpr SuperData(std::nullptr_t) : direct(nullptr) {}
+ constexpr SuperData(const QMetaObject *mo) : direct(mo) {}
+
+ constexpr const QMetaObject *operator->() const { return operator const QMetaObject *(); }
+
+#ifdef QT_NO_DATA_RELOCATION
+ using Getter = const QMetaObject *(*)();
+ Getter indirect = nullptr;
+ constexpr SuperData(Getter g) : direct(nullptr), indirect(g) {}
+ constexpr operator const QMetaObject *() const
+ { return indirect ? indirect() : direct; }
+ template <const QMetaObject &MO> static constexpr SuperData link()
+ { return SuperData(QMetaObject::staticMetaObject<MO>); }
+#else
+ constexpr operator const QMetaObject *() const
+ { return direct; }
+ template <const QMetaObject &MO> static constexpr SuperData link()
+ { return SuperData(QMetaObject::staticMetaObject<MO>()); }
+#endif
+ };
+
struct { // private data
- const QMetaObject *superdata;
+ SuperData superdata;
const QByteArrayData *stringdata;
const uint *data;
typedef void (*StaticMetacallFunction)(QObject *, QMetaObject::Call, int, void **);
StaticMetacallFunction static_metacall;
- const QMetaObject * const *relatedMetaObjects;
+ const SuperData *relatedMetaObjects;
void *extradata; //reserved for future use
} d;
private:
static bool invokeMethodImpl(QObject *object, QtPrivate::QSlotObjectBase *slot, Qt::ConnectionType type, void *ret);
+ friend class QTimer;
};
class Q_CORE_EXPORT QMetaObject::Connection {
@@ -609,8 +635,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/qpointer.h b/src/corelib/kernel/qpointer.h
index b2b3cda4ab..5efdb0b395 100644
--- a/src/corelib/kernel/qpointer.h
+++ b/src/corelib/kernel/qpointer.h
@@ -54,20 +54,11 @@ class QPointer
{
Q_STATIC_ASSERT_X(!std::is_pointer<T>::value, "QPointer's template type must not be a pointer type");
- template<typename U>
- struct TypeSelector
- {
- typedef QObject Type;
- };
- template<typename U>
- struct TypeSelector<const U>
- {
- typedef const QObject Type;
- };
- typedef typename TypeSelector<T>::Type QObjectType;
+ using QObjectType =
+ typename std::conditional<std::is_const<T>::value, const QObject, QObject>::type;
QWeakPointer<QObjectType> wp;
public:
- inline QPointer() { }
+ QPointer() = default;
inline QPointer(T *p) : wp(p, true) { }
// compiler-generated copy/move ctor/assignment operators are fine!
// compiler-generated dtor is fine!
@@ -77,13 +68,13 @@ public:
~QPointer();
#endif
- inline void swap(QPointer &other) { wp.swap(other.wp); }
+ inline void swap(QPointer &other) noexcept { wp.swap(other.wp); }
inline QPointer<T> &operator=(T* p)
{ wp.assign(static_cast<QObjectType*>(p)); return *this; }
inline T* data() const
- { return static_cast<T*>( wp.data()); }
+ { return static_cast<T*>(wp.internalData()); }
inline T* operator->() const
{ return data(); }
inline T& operator*() const
@@ -143,9 +134,14 @@ template<typename T>
QPointer<T>
qPointerFromVariant(const QVariant &variant)
{
- return QPointer<T>(qobject_cast<T*>(QtSharedPointer::weakPointerFromVariant_internal(variant).data()));
+ const auto wp = QtSharedPointer::weakPointerFromVariant_internal(variant);
+ return QPointer<T>{qobject_cast<T*>(QtPrivate::EnableInternalData::internalData(wp))};
}
+template <class T>
+inline void swap(QPointer<T> &p1, QPointer<T> &p2) noexcept
+{ p1.swap(p2); }
+
QT_END_NAMESPACE
#endif // QT_NO_QOBJECT
diff --git a/src/corelib/kernel/qpoll.cpp b/src/corelib/kernel/qpoll.cpp
index 8e93c4d363..8b87bfe79d 100644
--- a/src/corelib/kernel/qpoll.cpp
+++ b/src/corelib/kernel/qpoll.cpp
@@ -39,6 +39,10 @@
#include "qcore_unix_p.h"
+#ifdef Q_OS_RTEMS
+#include <rtems/rtems_bsdnet_internal.h>
+#endif
+
QT_BEGIN_NAMESPACE
#define QT_POLL_READ_MASK (POLLIN | POLLRDNORM)
@@ -135,6 +139,11 @@ static inline int qt_poll_sweep(struct pollfd *fds, nfds_t nfds,
static inline bool qt_poll_is_bad_fd(int fd)
{
+#ifdef Q_OS_RTEMS
+ if (!rtems_bsdnet_fdToSocket(fd))
+ return true;
+#endif
+
int ret;
EINTR_LOOP(ret, fcntl(fd, F_GETFD));
return (ret == -1 && errno == EBADF);
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.cpp b/src/corelib/kernel/qsharedmemory.cpp
index c952655cb8..39f3002394 100644
--- a/src/corelib/kernel/qsharedmemory.cpp
+++ b/src/corelib/kernel/qsharedmemory.cpp
@@ -150,11 +150,18 @@ QSharedMemoryPrivate::makePlatformSafeKey(const QString &key,
\sa setKey()
*/
+
+#ifndef QT_NO_QOBJECT
QSharedMemory::QSharedMemory(QObject *parent)
: QObject(*new QSharedMemoryPrivate, parent)
{
}
-
+#else
+QSharedMemory::QSharedMemory()
+ : d_ptr(new QSharedMemoryPrivate)
+{
+}
+#endif
/*!
Constructs a shared memory object with the given \a parent and with
its key set to \a key. Because its key is set, its create() and
@@ -162,11 +169,19 @@ QSharedMemory::QSharedMemory(QObject *parent)
\sa setKey(), create(), attach()
*/
+#ifndef QT_NO_QOBJECT
QSharedMemory::QSharedMemory(const QString &key, QObject *parent)
: QObject(*new QSharedMemoryPrivate, parent)
{
setKey(key);
}
+#else
+QSharedMemory::QSharedMemory(const QString &key)
+ : d_ptr(new QSharedMemoryPrivate)
+{
+ setKey(key);
+}
+#endif
/*!
The destructor clears the key, which forces the shared memory object
@@ -604,4 +619,6 @@ QString QSharedMemory::errorString() const
QT_END_NAMESPACE
+#ifndef QT_NO_QOBJECT
#include "moc_qsharedmemory.cpp"
+#endif
diff --git a/src/corelib/kernel/qsharedmemory.h b/src/corelib/kernel/qsharedmemory.h
index 67cf52ac17..6236c6aa4c 100644
--- a/src/corelib/kernel/qsharedmemory.h
+++ b/src/corelib/kernel/qsharedmemory.h
@@ -40,8 +40,14 @@
#ifndef QSHAREDMEMORY_H
#define QSHAREDMEMORY_H
-#include <QtCore/qobject.h>
-
+#include <QtCore/qglobal.h>
+#ifndef QT_NO_QOBJECT
+# include <QtCore/qobject.h>
+#else
+# include <QtCore/qobjectdefs.h>
+# include <QtCore/qscopedpointer.h>
+# include <QtCore/qstring.h>
+#endif
QT_BEGIN_NAMESPACE
@@ -49,9 +55,14 @@ QT_BEGIN_NAMESPACE
class QSharedMemoryPrivate;
-class Q_CORE_EXPORT QSharedMemory : public QObject
+class Q_CORE_EXPORT QSharedMemory
+#ifndef QT_NO_QOBJECT
+ : public QObject
+#endif
{
+#ifndef QT_NO_QOBJECT
Q_OBJECT
+#endif
Q_DECLARE_PRIVATE(QSharedMemory)
public:
@@ -74,8 +85,17 @@ public:
UnknownError
};
+#ifndef QT_NO_QOBJECT
QSharedMemory(QObject *parent = nullptr);
QSharedMemory(const QString &key, QObject *parent = nullptr);
+#else
+ QSharedMemory();
+ QSharedMemory(const QString &key);
+ static QString tr(const char * str)
+ {
+ return QString::fromLatin1(str);
+ }
+#endif
~QSharedMemory();
void setKey(const QString &key);
@@ -104,6 +124,9 @@ public:
private:
Q_DISABLE_COPY(QSharedMemory)
+#ifdef QT_NO_QOBJECT
+ QScopedPointer<QSharedMemoryPrivate> d_ptr;
+#endif
};
#endif // QT_NO_SHAREDMEMORY
diff --git a/src/corelib/kernel/qsharedmemory_p.h b/src/corelib/kernel/qsharedmemory_p.h
index 95fe0d1083..e6e989abda 100644
--- a/src/corelib/kernel/qsharedmemory_p.h
+++ b/src/corelib/kernel/qsharedmemory_p.h
@@ -67,9 +67,12 @@ namespace QSharedMemoryPrivate
#else
#include "qsystemsemaphore.h"
-#include "private/qobject_p.h"
-#if !defined(Q_OS_WIN) && !defined(Q_OS_ANDROID) && !defined(Q_OS_INTEGRITY)
+#ifndef QT_NO_QOBJECT
+# include "private/qobject_p.h"
+#endif
+
+#if !defined(Q_OS_WIN) && !defined(Q_OS_ANDROID) && !defined(Q_OS_INTEGRITY) && !defined(Q_OS_RTEMS)
# include <sys/sem.h>
#endif
@@ -98,7 +101,7 @@ public:
{
if (q_sm && q_sm->lock())
return true;
- q_sm = 0;
+ q_sm = nullptr;
return false;
}
@@ -107,9 +110,14 @@ private:
};
#endif // QT_NO_SYSTEMSEMAPHORE
-class Q_AUTOTEST_EXPORT QSharedMemoryPrivate : public QObjectPrivate
+class Q_AUTOTEST_EXPORT QSharedMemoryPrivate
+#ifndef QT_NO_QOBJECT
+ : public QObjectPrivate
+#endif
{
+#ifndef QT_NO_QOBJECT
Q_DECLARE_PUBLIC(QSharedMemory)
+#endif
public:
QSharedMemoryPrivate();
diff --git a/src/corelib/kernel/qsharedmemory_unix.cpp b/src/corelib/kernel/qsharedmemory_unix.cpp
index d1d44747e0..f6d7e78441 100644
--- a/src/corelib/kernel/qsharedmemory_unix.cpp
+++ b/src/corelib/kernel/qsharedmemory_unix.cpp
@@ -64,8 +64,11 @@
#ifndef QT_NO_SHAREDMEMORY
QT_BEGIN_NAMESPACE
-QSharedMemoryPrivate::QSharedMemoryPrivate()
- : QObjectPrivate(), memory(0), size(0), error(QSharedMemory::NoError),
+QSharedMemoryPrivate::QSharedMemoryPrivate() :
+#ifndef QT_NO_QOBJECT
+ QObjectPrivate(),
+#endif
+ memory(0), size(0), error(QSharedMemory::NoError),
#ifndef QT_NO_SYSTEMSEMAPHORE
systemSemaphore(QString()), lockedByMe(false),
#endif
diff --git a/src/corelib/kernel/qsharedmemory_win.cpp b/src/corelib/kernel/qsharedmemory_win.cpp
index c1dba30e2b..02de2339a5 100644
--- a/src/corelib/kernel/qsharedmemory_win.cpp
+++ b/src/corelib/kernel/qsharedmemory_win.cpp
@@ -47,7 +47,10 @@ QT_BEGIN_NAMESPACE
#ifndef QT_NO_SHAREDMEMORY
-QSharedMemoryPrivate::QSharedMemoryPrivate() : QObjectPrivate(),
+QSharedMemoryPrivate::QSharedMemoryPrivate() :
+#ifndef QT_NO_QOBJECT
+ QObjectPrivate(),
+#endif
memory(0), size(0), error(QSharedMemory::NoError),
systemSemaphore(QString()), lockedByMe(false), hand(0)
{
diff --git a/src/corelib/kernel/qsignalmapper.cpp b/src/corelib/kernel/qsignalmapper.cpp
index 34fea861cd..24b174972f 100644
--- a/src/corelib/kernel/qsignalmapper.cpp
+++ b/src/corelib/kernel/qsignalmapper.cpp
@@ -38,7 +38,6 @@
****************************************************************************/
#include "qglobal.h"
-#if QT_DEPRECATED_SINCE(5, 10)
#include "qsignalmapper.h"
#include "qhash.h"
@@ -64,7 +63,6 @@ public:
/*!
\class QSignalMapper
\inmodule QtCore
- \obsolete The recommended solution is connecting the signal to a lambda.
\brief The QSignalMapper class bundles signals from identifiable senders.
\ingroup objectmodel
@@ -72,7 +70,9 @@ public:
This class collects a set of parameterless signals, and re-emits
them with integer, string or widget parameters corresponding to
- the object that sent the signal.
+ the object that sent the signal. Note that in most cases you can
+ use lambdas for passing custom parameters to slots. This is less
+ costly and will simplify the code.
The class supports the mapping of particular strings or integers
with particular objects using setMapping(). The objects' signals
@@ -314,5 +314,3 @@ void QSignalMapper::map(QObject *sender)
QT_END_NAMESPACE
#include "moc_qsignalmapper.cpp"
-
-#endif
diff --git a/src/corelib/kernel/qsignalmapper.h b/src/corelib/kernel/qsignalmapper.h
index 6c4cfa9627..0da1e8f87d 100644
--- a/src/corelib/kernel/qsignalmapper.h
+++ b/src/corelib/kernel/qsignalmapper.h
@@ -42,8 +42,6 @@
#include <QtCore/qobject.h>
-#if QT_DEPRECATED_SINCE(5, 10)
-
QT_BEGIN_NAMESPACE
class QSignalMapperPrivate;
@@ -53,7 +51,7 @@ class Q_CORE_EXPORT QSignalMapper : public QObject
Q_OBJECT
Q_DECLARE_PRIVATE(QSignalMapper)
public:
- QT_DEPRECATED explicit QSignalMapper(QObject *parent = nullptr);
+ explicit QSignalMapper(QObject *parent = nullptr);
~QSignalMapper();
void setMapping(QObject *sender, int id);
@@ -84,6 +82,4 @@ private:
QT_END_NAMESPACE
-#endif
-
#endif // QSIGNALMAPPER_H
diff --git a/src/corelib/kernel/qsocketnotifier.cpp b/src/corelib/kernel/qsocketnotifier.cpp
index 6ff8268978..2a246b1204 100644
--- a/src/corelib/kernel/qsocketnotifier.cpp
+++ b/src/corelib/kernel/qsocketnotifier.cpp
@@ -152,7 +152,7 @@ QSocketNotifier::QSocketNotifier(qintptr socket, Type type, QObject *parent)
else if (!d->threadData->hasEventDispatcher())
qWarning("QSocketNotifier: Can only be used with threads started with QThread");
else
- d->threadData->eventDispatcher.load()->registerSocketNotifier(this);
+ d->threadData->eventDispatcher.loadRelaxed()->registerSocketNotifier(this);
}
/*!
@@ -241,9 +241,9 @@ void QSocketNotifier::setEnabled(bool enable)
return;
}
if (d->snenabled)
- d->threadData->eventDispatcher.load()->registerSocketNotifier(this);
+ d->threadData->eventDispatcher.loadRelaxed()->registerSocketNotifier(this);
else
- d->threadData->eventDispatcher.load()->unregisterSocketNotifier(this);
+ d->threadData->eventDispatcher.loadRelaxed()->unregisterSocketNotifier(this);
}
diff --git a/src/corelib/kernel/qsystemerror.cpp b/src/corelib/kernel/qsystemerror.cpp
index 9d0394e4a5..a735e12925 100644
--- a/src/corelib/kernel/qsystemerror.cpp
+++ b/src/corelib/kernel/qsystemerror.cpp
@@ -112,7 +112,7 @@ static QString windowsErrorString(int errorCode)
static QString standardLibraryErrorString(int errorCode)
{
- const char *s = 0;
+ const char *s = nullptr;
QString ret;
switch (errorCode) {
case 0:
diff --git a/src/corelib/kernel/qsystemsemaphore_systemv.cpp b/src/corelib/kernel/qsystemsemaphore_systemv.cpp
index 9e438ae2a6..2c38d74d2d 100644
--- a/src/corelib/kernel/qsystemsemaphore_systemv.cpp
+++ b/src/corelib/kernel/qsystemsemaphore_systemv.cpp
@@ -76,7 +76,7 @@ key_t QSystemSemaphorePrivate::handle(QSystemSemaphore::AccessMode mode)
#if QT_CONFIG(translation)
QCoreApplication::tr("%1: key is empty", "QSystemSemaphore")
#else
- QString::fromLatin1("%1: key is empty")
+ QLatin1String("%1: key is empty")
#endif
.arg(QLatin1String("QSystemSemaphore::handle:"));
error = QSystemSemaphore::KeyError;
@@ -94,7 +94,7 @@ key_t QSystemSemaphorePrivate::handle(QSystemSemaphore::AccessMode mode)
#if QT_CONFIG(translation)
QCoreApplication::tr("%1: unable to make key", "QSystemSemaphore")
#else
- QString::fromLatin1("%1: unable to make key")
+ QLatin1String("%1: unable to make key")
#endif
.arg(QLatin1String("QSystemSemaphore::handle:"));
error = QSystemSemaphore::KeyError;
@@ -111,7 +111,7 @@ key_t QSystemSemaphorePrivate::handle(QSystemSemaphore::AccessMode mode)
#if QT_CONFIG(translation)
QCoreApplication::tr("%1: ftok failed", "QSystemSemaphore")
#else
- QString::fromLatin1("%1: ftok failed")
+ QLatin1String("%1: ftok failed")
#endif
.arg(QLatin1String("QSystemSemaphore::handle:"));
error = QSystemSemaphore::KeyError;
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 9d3bd5fdbf..948f697dc5 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);
}
@@ -575,8 +604,8 @@ void QTimer::singleShot(int msec, Qt::TimerType timerType, const QObject *receiv
\since 5.12
\overload
- Creates a connection from the timeout() signal to \a slot, and returns a
- handle to the connection.
+ Creates a connection of type \a connectionType from the timeout() signal
+ to \a slot, and returns a handle to the connection.
This method is provided for convenience.
It's equivalent to calling \c {QObject::connect(timer, &QTimer::timeout, timer, slot, connectionType)}.
diff --git a/src/corelib/kernel/qtimer.h b/src/corelib/kernel/qtimer.h
index 336b814b27..eb7185c12d 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/qtimerinfo_unix.cpp b/src/corelib/kernel/qtimerinfo_unix.cpp
index c3b8c86063..39010c19cb 100644
--- a/src/corelib/kernel/qtimerinfo_unix.cpp
+++ b/src/corelib/kernel/qtimerinfo_unix.cpp
@@ -215,7 +215,7 @@ static timespec roundToMillisecond(timespec val)
QDebug operator<<(QDebug s, timeval tv)
{
QDebugStateSaver saver(s);
- s.nospace() << tv.tv_sec << "." << qSetFieldWidth(6) << qSetPadChar(QChar(48)) << tv.tv_usec << reset;
+ s.nospace() << tv.tv_sec << "." << qSetFieldWidth(6) << qSetPadChar(QChar(48)) << tv.tv_usec << Qt::reset;
return s;
}
QDebug operator<<(QDebug s, Qt::TimerType t)
@@ -373,7 +373,7 @@ static void calculateNextTimeout(QTimerInfo *t, timespec currentTime)
#ifdef QTIMERINFO_DEBUG
if (t->timerType != Qt::PreciseTimer)
- qDebug() << "timer" << t->timerType << hex << t->id << dec << "interval" << t->interval
+ qDebug() << "timer" << t->timerType << Qt::hex << t->id << Qt::dec << "interval" << t->interval
<< "originally expected at" << t->expected << "will fire at" << t->timeout
<< "or" << (t->timeout - t->expected) << "s late";
#endif
@@ -500,7 +500,7 @@ void QTimerInfoList::registerTimer(int timerId, int interval, Qt::TimerType time
t->cumulativeError = 0;
t->count = 0;
if (t->timerType != Qt::PreciseTimer)
- qDebug() << "timer" << t->timerType << hex <<t->id << dec << "interval" << t->interval << "expected at"
+ qDebug() << "timer" << t->timerType << Qt::hex <<t->id << Qt::dec << "interval" << t->interval << "expected at"
<< t->expected << "will fire first at" << t->timeout;
#endif
}
@@ -620,7 +620,7 @@ int QTimerInfoList::activateTimers()
currentTimerInfo->cumulativeError += diff;
++currentTimerInfo->count;
if (currentTimerInfo->timerType != Qt::PreciseTimer)
- qDebug() << "timer" << currentTimerInfo->timerType << hex << currentTimerInfo->id << dec << "interval"
+ qDebug() << "timer" << currentTimerInfo->timerType << Qt::hex << currentTimerInfo->id << Qt::dec << "interval"
<< currentTimerInfo->interval << "firing at" << currentTime
<< "(orig" << currentTimerInfo->expected << "scheduled at" << currentTimerInfo->timeout
<< ") off by" << diff << "activation" << currentTimerInfo->count
diff --git a/src/corelib/kernel/qtranslator.cpp b/src/corelib/kernel/qtranslator.cpp
index 637ef84d21..ddb96ecad6 100644
--- a/src/corelib/kernel/qtranslator.cpp
+++ b/src/corelib/kernel/qtranslator.cpp
@@ -528,7 +528,8 @@ bool QTranslatorPrivate::do_load(const QString &realname, const QString &directo
// memory, so no need to use QFile to copy it again.
Q_ASSERT(!d->resource);
d->resource = new QResource(realname);
- if (resource->isValid() && !resource->isCompressed() && resource->size() >= MagicLength
+ if (resource->isValid() && resource->compressionAlgorithm() == QResource::NoCompression
+ && resource->size() >= MagicLength
&& !memcmp(resource->data(), magic, MagicLength)) {
d->unmapLength = resource->size();
d->unmapPointer = reinterpret_cast<char *>(const_cast<uchar *>(resource->data()));
diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp
index 3b7be3d12f..43a3fb1db0 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/
@@ -46,7 +46,9 @@
#include "qdebug.h"
#include "qmap.h"
#include "qdatetime.h"
+#if QT_CONFIG(easingcurve)
#include "qeasingcurve.h"
+#endif
#include "qlist.h"
#if QT_CONFIG(regularexpression)
#include "qregularexpression.h"
@@ -55,6 +57,7 @@
#include "qstringlist.h"
#include "qurl.h"
#include "qlocale.h"
+#include "qregexp.h"
#include "quuid.h"
#if QT_CONFIG(itemmodel)
#include "qabstractitemmodel.h"
@@ -118,19 +121,19 @@ namespace { // annonymous used to hide QVariant handlers
static void construct(QVariant::Private *x, const void *copy)
{
QVariantConstructor<CoreTypesFilter> constructor(x, copy);
- QMetaTypeSwitcher::switcher<void>(constructor, x->type, 0);
+ QMetaTypeSwitcher::switcher<void>(constructor, x->type);
}
static void clear(QVariant::Private *d)
{
QVariantDestructor<CoreTypesFilter> cleaner(d);
- QMetaTypeSwitcher::switcher<void>(cleaner, d->type, 0);
+ QMetaTypeSwitcher::switcher<void>(cleaner, d->type);
}
static bool isNull(const QVariant::Private *d)
{
QVariantIsNull<CoreTypesFilter> isNull(d);
- return QMetaTypeSwitcher::switcher<bool>(isNull, d->type, 0);
+ return QMetaTypeSwitcher::switcher<bool>(isNull, d->type);
}
/*!
@@ -142,7 +145,7 @@ static bool isNull(const QVariant::Private *d)
static bool compare(const QVariant::Private *a, const QVariant::Private *b)
{
QVariantComparator<CoreTypesFilter> comparator(a, b);
- return QMetaTypeSwitcher::switcher<bool>(comparator, a->type, 0);
+ return QMetaTypeSwitcher::switcher<bool>(comparator, a->type);
}
/*!
@@ -1400,7 +1403,7 @@ static void streamDebug(QDebug dbg, const QVariant &v)
{
QVariant::Private *d = const_cast<QVariant::Private *>(&v.data_ptr());
QVariantDebugStream<CoreTypesFilter> stream(dbg, d);
- QMetaTypeSwitcher::switcher<void>(stream, d->type, 0);
+ QMetaTypeSwitcher::switcher<void>(stream, d->type);
}
#endif
@@ -1409,16 +1412,16 @@ const QVariant::Handler qt_kernel_variant_handler = {
clear,
isNull,
#ifndef QT_NO_DATASTREAM
- 0,
- 0,
+ nullptr,
+ nullptr,
#endif
compare,
convert,
- 0,
+ nullptr,
#if !defined(QT_NO_DEBUG_STREAM)
streamDebug
#else
- 0
+ nullptr
#endif
};
@@ -1435,16 +1438,16 @@ const QVariant::Handler qt_dummy_variant_handler = {
dummyClear,
dummyIsNull,
#ifndef QT_NO_DATASTREAM
- 0,
- 0,
+ nullptr,
+ nullptr,
#endif
dummyCompare,
dummyConvert,
- 0,
+ nullptr,
#if !defined(QT_NO_DEBUG_STREAM)
dummyStreamDebug
#else
- 0
+ nullptr
#endif
};
@@ -1462,6 +1465,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 +1476,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);
}
@@ -1552,16 +1557,16 @@ const QVariant::Handler qt_custom_variant_handler = {
customClear,
customIsNull,
#ifndef QT_NO_DATASTREAM
- 0,
- 0,
+ nullptr,
+ nullptr,
#endif
customCompare,
customConvert,
- 0,
+ nullptr,
#if !defined(QT_NO_DEBUG_STREAM)
customStreamDebug
#else
- 0
+ nullptr
#endif
};
@@ -2122,7 +2127,7 @@ QVariant::QVariant(const char *val)
*/
QVariant::QVariant(Type type)
-{ create(type, 0); }
+{ create(type, nullptr); }
QVariant::QVariant(int typeId, const void *copy)
{ create(typeId, copy); d.is_null = false; }
@@ -2191,7 +2196,7 @@ QVariant::QVariant(const QTime &val)
QVariant::QVariant(const QDateTime &val)
: d(DateTime)
{ v_construct<QDateTime>(&d, val); }
-#ifndef QT_BOOTSTRAPPED
+#if QT_CONFIG(easingcurve)
QVariant::QVariant(const QEasingCurve &val)
: d(EasingCurve)
{ v_construct<QEasingCurve>(&d, val); }
@@ -2363,7 +2368,7 @@ QVariant& QVariant::operator=(const QVariant &variant)
void QVariant::detach()
{
- if (!d.is_shared || d.data.shared->ref.load() == 1)
+ if (!d.is_shared || d.data.shared->ref.loadRelaxed() == 1)
return;
Private dd;
@@ -2468,7 +2473,9 @@ static const ushort mapIdFromQt3ToCurrent[MapFromThreeCount] =
QVariant::Pen,
QVariant::LongLong,
QVariant::ULongLong,
+#if QT_CONFIG(easingcurve)
QVariant::EasingCurve
+#endif
};
/*!
@@ -2664,7 +2671,7 @@ inline T qVariantToHelper(const QVariant::Private &d, const HandlersManager &han
return ret;
}
- handlerManager[d.type]->convert(&d, targetType, &ret, 0);
+ handlerManager[d.type]->convert(&d, targetType, &ret, nullptr);
return ret;
}
@@ -2785,7 +2792,7 @@ QDateTime QVariant::toDateTime() const
\sa canConvert(int targetTypeId), convert()
*/
-#ifndef QT_BOOTSTRAPPED
+#if QT_CONFIG(easingcurve)
QEasingCurve QVariant::toEasingCurve() const
{
return qVariantToHelper<QEasingCurve>(d, handlerManager);
@@ -3214,7 +3221,7 @@ bool QVariant::toBool() const
return d.data.b;
bool res = false;
- handlerManager[d.type]->convert(&d, Bool, &res, 0);
+ handlerManager[d.type]->convert(&d, Bool, &res, nullptr);
return res;
}
@@ -3732,7 +3739,7 @@ bool QVariant::convert(int targetTypeId)
if (!oldValue.canConvert(targetTypeId))
return false;
- create(targetTypeId, 0);
+ create(targetTypeId, nullptr);
// Fail if the value is not initialized or was forced null by a previous failed convert.
if (oldValue.d.is_null && oldValue.d.type != QMetaType::Nullptr)
return false;
@@ -3757,7 +3764,7 @@ bool QVariant::convert(int targetTypeId)
*/
bool QVariant::convert(const int type, void *ptr) const
{
- return handlerManager[type]->convert(&d, type, ptr, 0);
+ return handlerManager[type]->convert(&d, type, ptr, nullptr);
}
@@ -4002,8 +4009,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 +4287,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 +4325,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 bb9db3d1ad..e7d3d9c835 100644
--- a/src/corelib/kernel/qvariant.h
+++ b/src/corelib/kernel/qvariant.h
@@ -66,7 +66,9 @@ class QBitArray;
class QDataStream;
class QDate;
class QDateTime;
+#if QT_CONFIG(easingcurve)
class QEasingCurve;
+#endif
class QLine;
class QLineF;
class QLocale;
@@ -92,9 +94,6 @@ class QUrl;
class QVariant;
class QVariantComparisonHelper;
-template <typename T>
-inline QVariant qVariantFromValue(const T &);
-
template<typename T>
inline T qvariant_cast(const QVariant &);
@@ -165,7 +164,9 @@ class Q_CORE_EXPORT QVariant
RegExp = QMetaType::QRegExp,
RegularExpression = QMetaType::QRegularExpression,
Hash = QMetaType::QVariantHash,
+#if QT_CONFIG(easingcurve)
EasingCurve = QMetaType::QEasingCurve,
+#endif
Uuid = QMetaType::QUuid,
#if QT_CONFIG(itemmodel)
ModelIndex = QMetaType::QModelIndex,
@@ -204,7 +205,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);
@@ -257,7 +258,9 @@ class Q_CORE_EXPORT QVariant
#endif // QT_CONFIG(regularexpression)
#ifndef QT_BOOTSTRAPPED
QVariant(const QUrl &url);
+#if QT_CONFIG(easingcurve)
QVariant(const QEasingCurve &easing);
+#endif
QVariant(const QUuid &uuid);
QVariant(const QJsonValue &jsonValue);
QVariant(const QJsonObject &jsonObject);
@@ -270,14 +273,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;
@@ -333,7 +334,9 @@ class Q_CORE_EXPORT QVariant
#endif // QT_CONFIG(regularexpression)
#ifndef QT_BOOTSTRAPPED
QUrl toUrl() const;
+#if QT_CONFIG(easingcurve)
QEasingCurve toEasingCurve() const;
+#endif
QUuid toUuid() const;
QJsonValue toJsonValue() const;
QJsonObject toJsonObject() const;
@@ -365,7 +368,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) || defined(Q_CLANG_QDOC)
template<typename... Types>
@@ -390,20 +393,20 @@ 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)
{}
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
- Private(const Private &other) Q_DECL_NOTHROW
+ Private(const Private &other) noexcept
: data(other.data), type(other.type),
is_shared(other.is_shared), is_null(other.is_null)
{}
- Private &operator=(const Private &other) Q_DECL_NOTHROW = default;
+ Private &operator=(const Private &other) noexcept = default;
#endif
union Data
{
@@ -491,27 +494,27 @@ public:
private:
// force compile error, prevent QVariant(bool) to be called
- inline QVariant(void *) Q_DECL_EQ_DELETE;
+ inline QVariant(void *) = delete;
// QVariant::Type is marked as \obsolete, but we don't want to
// provide a constructor from its intended replacement,
// QMetaType::Type, instead, because the idea behind these
// constructors is flawed in the first place. But we also don't
// want QVariant(QMetaType::String) to compile and falsely be an
// int variant, so delete this constructor:
- QVariant(QMetaType::Type) Q_DECL_EQ_DELETE;
+ QVariant(QMetaType::Type) = delete;
// These constructors don't create QVariants of the type associcated
// with the enum, as expected, but they would create a QVariant of
// type int with the value of the enum value.
// Use QVariant v = QColor(Qt::red) instead of QVariant v = Qt::red for
// example.
- QVariant(Qt::GlobalColor) Q_DECL_EQ_DELETE;
- QVariant(Qt::BrushStyle) Q_DECL_EQ_DELETE;
- QVariant(Qt::PenStyle) Q_DECL_EQ_DELETE;
- QVariant(Qt::CursorShape) Q_DECL_EQ_DELETE;
+ QVariant(Qt::GlobalColor) = delete;
+ QVariant(Qt::BrushStyle) = delete;
+ QVariant(Qt::PenStyle) = delete;
+ QVariant(Qt::CursorShape) = delete;
#ifdef QT_NO_CAST_FROM_ASCII
// force compile error when implicit conversion is not wanted
- inline QVariant(const char *) Q_DECL_EQ_DELETE;
+ inline QVariant(const char *) = delete;
#endif
public:
typedef Private DataPtr;
@@ -519,50 +522,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 <>
-inline QVariant qVariantFromValue(const QVariant &t) { return 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 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);
@@ -571,7 +585,7 @@ Q_CORE_EXPORT QDataStream& operator<< (QDataStream& s, const QVariant::Type p);
#endif
inline bool QVariant::isDetached() const
-{ return !d.is_shared || d.data.shared->ref.load() == 1; }
+{ return !d.is_shared || d.data.shared->ref.loadRelaxed() == 1; }
#ifdef Q_QDOC
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));
diff --git a/src/corelib/kernel/qwineventnotifier.cpp b/src/corelib/kernel/qwineventnotifier.cpp
index 3c73c0b851..d2ae9668fe 100644
--- a/src/corelib/kernel/qwineventnotifier.cpp
+++ b/src/corelib/kernel/qwineventnotifier.cpp
@@ -124,7 +124,7 @@ QWinEventNotifier::QWinEventNotifier(HANDLE hEvent, QObject *parent)
: QObject(*new QWinEventNotifierPrivate(hEvent, false), parent)
{
Q_D(QWinEventNotifier);
- QAbstractEventDispatcher *eventDispatcher = d->threadData->eventDispatcher.load();
+ QAbstractEventDispatcher *eventDispatcher = d->threadData->eventDispatcher.loadRelaxed();
if (Q_UNLIKELY(!eventDispatcher)) {
qWarning("QWinEventNotifier: Can only be used with threads started with QThread");
return;
@@ -197,7 +197,7 @@ void QWinEventNotifier::setEnabled(bool enable)
return;
d->enabled = enable;
- QAbstractEventDispatcher *eventDispatcher = d->threadData->eventDispatcher.load();
+ QAbstractEventDispatcher *eventDispatcher = d->threadData->eventDispatcher.loadRelaxed();
if (!eventDispatcher) { // perhaps application is shutting down
if (!enable && d->waitHandle != nullptr)
d->unregisterWaitObject();
@@ -256,7 +256,7 @@ void QWinEventNotifierPrivate::unregisterWaitObject()
static void CALLBACK wfsoCallback(void *context, BOOLEAN /*ignore*/)
{
QWinEventNotifierPrivate *nd = reinterpret_cast<QWinEventNotifierPrivate *>(context);
- QAbstractEventDispatcher *eventDispatcher = nd->threadData->eventDispatcher.load();
+ QAbstractEventDispatcher *eventDispatcher = nd->threadData->eventDispatcher.loadRelaxed();
// Happens when Q(Core)Application is destroyed before QWinEventNotifier.
// https://bugreports.qt.io/browse/QTBUG-70214
diff --git a/src/corelib/kernel/qwinregistry.cpp b/src/corelib/kernel/qwinregistry.cpp
new file mode 100644
index 0000000000..6566dd3c76
--- /dev/null
+++ b/src/corelib/kernel/qwinregistry.cpp
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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 "qwinregistry_p.h"
+
+#include <QtCore/qvarlengtharray.h>
+
+#include <algorithm>
+
+QT_BEGIN_NAMESPACE
+
+QWinRegistryKey::QWinRegistryKey() :
+ m_key(nullptr)
+{
+}
+
+// Open a key with the specified permissions (KEY_READ/KEY_WRITE).
+// "access" is to explicitly use the 32- or 64-bit branch.
+QWinRegistryKey::QWinRegistryKey(HKEY parentHandle, QStringView subKey,
+ REGSAM permissions, REGSAM access)
+{
+ if (RegOpenKeyEx(parentHandle, reinterpret_cast<const wchar_t *>(subKey.utf16()),
+ 0, permissions | access, &m_key) != ERROR_SUCCESS) {
+ m_key = nullptr;
+ }
+}
+
+QWinRegistryKey::~QWinRegistryKey()
+{
+ close();
+}
+
+void QWinRegistryKey::close()
+{
+ if (isValid()) {
+ RegCloseKey(m_key);
+ m_key = nullptr;
+ }
+}
+
+QString QWinRegistryKey::stringValue(QStringView subKey) const
+{
+ QString result;
+ if (!isValid())
+ return result;
+ DWORD type;
+ DWORD size;
+ auto subKeyC = reinterpret_cast<const wchar_t *>(subKey.utf16());
+ if (RegQueryValueEx(m_key, subKeyC, nullptr, &type, nullptr, &size) != ERROR_SUCCESS
+ || (type != REG_SZ && type != REG_EXPAND_SZ) || size <= 2) {
+ return result;
+ }
+ // Reserve more for rare cases where trailing '\0' are missing in registry,
+ // otherwise chop off the '\0' received.
+ QString buffer(int(size / sizeof(wchar_t)), Qt::Uninitialized);
+ if (RegQueryValueEx(m_key, subKeyC, nullptr, &type,
+ reinterpret_cast<LPBYTE>(buffer.data()), &size) == ERROR_SUCCESS) {
+ if (buffer.endsWith(QChar::Null))
+ buffer.chop(1);
+ } else {
+ buffer.clear();
+ }
+ return buffer;
+}
+
+QPair<DWORD, bool> QWinRegistryKey::dwordValue(QStringView subKey) const
+{
+ if (!isValid())
+ return qMakePair(0, false);
+ DWORD type;
+ auto subKeyC = reinterpret_cast<const wchar_t *>(subKey.utf16());
+ if (RegQueryValueEx(m_key, subKeyC, nullptr, &type, nullptr, nullptr) != ERROR_SUCCESS
+ || type != REG_DWORD) {
+ return qMakePair(0, false);
+ }
+ DWORD value = 0;
+ DWORD size = sizeof(value);
+ const bool ok =
+ RegQueryValueEx(m_key, subKeyC, nullptr, nullptr,
+ reinterpret_cast<unsigned char *>(&value), &size) == ERROR_SUCCESS;
+ return qMakePair(value, ok);
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qwinregistry_p.h b/src/corelib/kernel/qwinregistry_p.h
new file mode 100644
index 0000000000..d249a97988
--- /dev/null
+++ b/src/corelib/kernel/qwinregistry_p.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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$
+**
+****************************************************************************/
+
+#ifndef QWINREGISTRY_H
+#define QWINREGISTRY_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qpair.h>
+#include <QtCore/qstring.h>
+#include <QtCore/qstringview.h>
+#include <QtCore/qt_windows.h>
+
+QT_BEGIN_NAMESPACE
+
+class Q_CORE_EXPORT QWinRegistryKey
+{
+public:
+ Q_DISABLE_COPY(QWinRegistryKey)
+
+ QWinRegistryKey();
+ explicit QWinRegistryKey(HKEY parentHandle, QStringView subKey,
+ REGSAM permissions = KEY_READ, REGSAM access = 0);
+ ~QWinRegistryKey();
+
+ QWinRegistryKey(QWinRegistryKey &&other) noexcept { swap(other); }
+ QWinRegistryKey &operator=(QWinRegistryKey &&other) noexcept { swap(other); return *this; }
+
+ void swap(QWinRegistryKey &other) noexcept { qSwap(m_key, other.m_key); }
+
+ bool isValid() const { return m_key != nullptr; }
+ operator HKEY() const { return m_key; }
+ void close();
+
+ QString stringValue(QStringView subKey) const;
+ QPair<DWORD, bool> dwordValue(QStringView subKey) const;
+
+private:
+ HKEY m_key;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWINREGISTRY_H