summaryrefslogtreecommitdiffstats
path: root/src/corelib/thread
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/thread')
-rw-r--r--src/corelib/thread/qatomic.cpp75
-rw-r--r--src/corelib/thread/qatomic.h24
-rw-r--r--src/corelib/thread/qatomic_bootstrap.h10
-rw-r--r--src/corelib/thread/qatomic_cxx11.h106
-rw-r--r--src/corelib/thread/qatomic_msvc.h94
-rw-r--r--src/corelib/thread/qbasicatomic.h206
-rw-r--r--src/corelib/thread/qfutex_p.h32
-rw-r--r--src/corelib/thread/qfuture.h82
-rw-r--r--src/corelib/thread/qfutureinterface.cpp47
-rw-r--r--src/corelib/thread/qfutureinterface.h13
-rw-r--r--src/corelib/thread/qfutureinterface_p.h4
-rw-r--r--src/corelib/thread/qfuturewatcher.cpp6
-rw-r--r--src/corelib/thread/qgenericatomic.h120
-rw-r--r--src/corelib/thread/qlocking_p.h119
-rw-r--r--src/corelib/thread/qmutex.cpp158
-rw-r--r--src/corelib/thread/qmutex.h90
-rw-r--r--src/corelib/thread/qmutex_linux.cpp12
-rw-r--r--src/corelib/thread/qmutex_mac.cpp2
-rw-r--r--src/corelib/thread/qmutex_p.h14
-rw-r--r--src/corelib/thread/qmutex_unix.cpp6
-rw-r--r--src/corelib/thread/qmutex_win.cpp2
-rw-r--r--src/corelib/thread/qmutexpool.cpp151
-rw-r--r--src/corelib/thread/qmutexpool_p.h88
-rw-r--r--src/corelib/thread/qorderedmutexlocker_p.h62
-rw-r--r--src/corelib/thread/qreadwritelock.cpp25
-rw-r--r--src/corelib/thread/qreadwritelock.h36
-rw-r--r--src/corelib/thread/qreadwritelock_p.h18
-rw-r--r--src/corelib/thread/qresultstore.h4
-rw-r--r--src/corelib/thread/qsemaphore.cpp6
-rw-r--r--src/corelib/thread/qsemaphore.h14
-rw-r--r--src/corelib/thread/qthread.cpp45
-rw-r--r--src/corelib/thread/qthread.h6
-rw-r--r--src/corelib/thread/qthread_p.h20
-rw-r--r--src/corelib/thread/qthread_unix.cpp64
-rw-r--r--src/corelib/thread/qthread_win.cpp20
-rw-r--r--src/corelib/thread/qthreadpool_p.h2
-rw-r--r--src/corelib/thread/qthreadstorage.cpp6
-rw-r--r--src/corelib/thread/qthreadstorage.h4
-rw-r--r--src/corelib/thread/qwaitcondition_unix.cpp2
-rw-r--r--src/corelib/thread/thread.pri3
40 files changed, 1004 insertions, 794 deletions
diff --git a/src/corelib/thread/qatomic.cpp b/src/corelib/thread/qatomic.cpp
index c161bec537..b1a7edad91 100644
--- a/src/corelib/thread/qatomic.cpp
+++ b/src/corelib/thread/qatomic.cpp
@@ -258,12 +258,26 @@
/*!
\fn template <typename T> T QAtomicInteger<T>::load() const
+ \obsolete
+
+ Use loadRelaxed() instead.
Atomically loads the value of this QAtomicInteger using relaxed memory
ordering. The value is not modified in any way, but note that there's no
guarantee that it remains so.
- \sa store(), loadAcquire()
+ \sa storeRelaxed(), loadAcquire()
+*/
+
+/*!
+ \fn template <typename T> T QAtomicInteger<T>::loadRelaxed() const
+ \since 5.14
+
+ Atomically loads the value of this QAtomicInteger using relaxed memory
+ ordering. The value is not modified in any way, but note that there's no
+ guarantee that it remains so.
+
+ \sa storeRelaxed(), loadAcquire()
*/
/*!
@@ -273,16 +287,29 @@
ordering. The value is not modified in any way, but note that there's no
guarantee that it remains so.
- \sa store(), load()
+ \sa storeRelaxed(), loadRelaxed()
*/
/*!
\fn template <typename T> void QAtomicInteger<T>::store(T newValue)
+ \obsolete
+
+ Use storeRelaxed() instead.
Atomically stores the \a newValue value into this atomic type, using
relaxed memory ordering.
- \sa storeRelease(), load()
+ \sa storeRelease(), loadRelaxed()
+*/
+
+/*!
+ \fn template <typename T> void QAtomicInteger<T>::storeRelaxed(T newValue)
+ \since 5.14
+
+ Atomically stores the \a newValue value into this atomic type, using
+ relaxed memory ordering.
+
+ \sa storeRelease(), loadRelaxed()
*/
/*!
@@ -291,7 +318,7 @@
Atomically stores the \a newValue value into this atomic type, using
the "Release" memory ordering.
- \sa store(), load()
+ \sa store(), loadAcquire()
*/
/*!
@@ -303,7 +330,7 @@
value is not modified in any way, but note that there's no guarantee that
it remains so.
- \sa load(), loadAcquire()
+ \sa loadRelaxed(), loadAcquire()
*/
/*!
@@ -314,7 +341,7 @@
sequentially consistent memory ordering if possible; or "Release" ordering
if not. This function returns a reference to this object.
- \sa store(), storeRelease()
+ \sa storeRelaxed(), storeRelease()
*/
/*! \fn template <typename T> bool QAtomicInteger<T>::isReferenceCountingNative()
@@ -1278,31 +1305,59 @@
/*!
\fn template <typename T> T *QAtomicPointer<T>::load() const
+ \obsolete
+
+ Use loadRelaxed() instead.
Atomically loads the value of this QAtomicPointer using relaxed memory
ordering. The value is not modified in any way, but note that there's no
guarantee that it remains so.
- \sa store(), loadAcquire()
+ \sa storeRelaxed(), loadAcquire()
*/
/*!
+ \fn template <typename T> T *QAtomicPointer<T>::loadRelaxed() const
+ \since 5.14
+
+ Atomically loads the value of this QAtomicPointer using relaxed memory
+ ordering. The value is not modified in any way, but note that there's no
+ guarantee that it remains so.
+
+ \sa storeRelaxed(), loadAcquire()
+*/
+
+
+/*!
\fn template <typename T> T *QAtomicPointer<T>::loadAcquire() const
Atomically loads the value of this QAtomicPointer using the "Acquire" memory
ordering. The value is not modified in any way, but note that there's no
guarantee that it remains so.
- \sa store(), load()
+ \sa storeRelease(), loadRelaxed()
*/
/*!
\fn template <typename T> void QAtomicPointer<T>::store(T *newValue)
+ \obsolete
+
+ Use storeRelaxed() instead.
+
+ Atomically stores the \a newValue value into this atomic type, using
+ relaxed memory ordering.
+
+ \sa storeRelease(), loadRelaxed()
+*/
+
+/*!
+ \fn template <typename T> void QAtomicPointer<T>::storeRelaxed(T *newValue)
+ \since 5.14
Atomically stores the \a newValue value into this atomic type, using
relaxed memory ordering.
- \sa storeRelease(), load()
+ \sa storeRelease(), loadRelaxed()
*/
/*!
@@ -1311,7 +1366,7 @@
Atomically stores the \a newValue value into this atomic type, using
the "Release" memory ordering.
- \sa store(), load()
+ \sa storeRelaxed(), loadRelaxed()
*/
/*! \fn template <typename T> bool QAtomicPointer<T>::isTestAndSetNative()
diff --git a/src/corelib/thread/qatomic.h b/src/corelib/thread/qatomic.h
index f842534c38..a3b9be0729 100644
--- a/src/corelib/thread/qatomic.h
+++ b/src/corelib/thread/qatomic.h
@@ -57,15 +57,15 @@ class QAtomicInteger : public QBasicAtomicInteger<T>
public:
// Non-atomic API
#ifdef QT_BASIC_ATOMIC_HAS_CONSTRUCTORS
- constexpr QAtomicInteger(T value = 0) Q_DECL_NOTHROW : QBasicAtomicInteger<T>(value) {}
+ constexpr QAtomicInteger(T value = 0) noexcept : QBasicAtomicInteger<T>(value) {}
#else
- inline QAtomicInteger(T value = 0) Q_DECL_NOTHROW
+ inline QAtomicInteger(T value = 0) noexcept
{
this->_q_value = value;
}
#endif
- inline QAtomicInteger(const QAtomicInteger &other) Q_DECL_NOTHROW
+ inline QAtomicInteger(const QAtomicInteger &other) noexcept
#ifdef QT_BASIC_ATOMIC_HAS_CONSTRUCTORS
: QBasicAtomicInteger<T>()
#endif
@@ -73,7 +73,7 @@ public:
this->storeRelease(other.loadAcquire());
}
- inline QAtomicInteger &operator=(const QAtomicInteger &other) Q_DECL_NOTHROW
+ inline QAtomicInteger &operator=(const QAtomicInteger &other) noexcept
{
this->storeRelease(other.loadAcquire());
return *this;
@@ -81,8 +81,10 @@ public:
#ifdef Q_CLANG_QDOC
T load() const;
+ T loadRelaxed() const;
T loadAcquire() const;
void store(T newValue);
+ void storeRelaxed(T newValue);
void storeRelease(T newValue);
operator T() const;
@@ -159,7 +161,7 @@ public:
#ifdef QT_BASIC_ATOMIC_HAS_CONSTRUCTORS
constexpr
#endif
- QAtomicInt(int value = 0) Q_DECL_NOTHROW : QAtomicInteger<int>(value) {}
+ QAtomicInt(int value = 0) noexcept : QAtomicInteger<int>(value) {}
};
// High-level atomic pointer operations
@@ -168,14 +170,14 @@ class QAtomicPointer : public QBasicAtomicPointer<T>
{
public:
#ifdef QT_BASIC_ATOMIC_HAS_CONSTRUCTORS
- constexpr QAtomicPointer(T *value = nullptr) Q_DECL_NOTHROW : QBasicAtomicPointer<T>(value) {}
+ constexpr QAtomicPointer(T *value = nullptr) noexcept : QBasicAtomicPointer<T>(value) {}
#else
- inline QAtomicPointer(T *value = nullptr) Q_DECL_NOTHROW
+ inline QAtomicPointer(T *value = nullptr) noexcept
{
- this->store(value);
+ this->storeRelaxed(value);
}
#endif
- inline QAtomicPointer(const QAtomicPointer<T> &other) Q_DECL_NOTHROW
+ inline QAtomicPointer(const QAtomicPointer<T> &other) noexcept
#ifdef QT_BASIC_ATOMIC_HAS_CONSTRUCTORS
: QBasicAtomicPointer<T>()
#endif
@@ -183,7 +185,7 @@ public:
this->storeRelease(other.loadAcquire());
}
- inline QAtomicPointer<T> &operator=(const QAtomicPointer<T> &other) Q_DECL_NOTHROW
+ inline QAtomicPointer<T> &operator=(const QAtomicPointer<T> &other) noexcept
{
this->storeRelease(other.loadAcquire());
return *this;
@@ -255,7 +257,7 @@ inline void qAtomicAssign(T *&d, T *x)
template <typename T>
inline void qAtomicDetach(T *&d)
{
- if (d->ref.load() == 1)
+ if (d->ref.loadRelaxed() == 1)
return;
T *x = d;
d = new T(*d);
diff --git a/src/corelib/thread/qatomic_bootstrap.h b/src/corelib/thread/qatomic_bootstrap.h
index b463f817bd..c4279ee7b1 100644
--- a/src/corelib/thread/qatomic_bootstrap.h
+++ b/src/corelib/thread/qatomic_bootstrap.h
@@ -56,16 +56,16 @@ template <typename T> struct QAtomicOps: QGenericAtomicOps<QAtomicOps<T> >
{
typedef T Type;
- static bool ref(T &_q_value) Q_DECL_NOTHROW
+ static bool ref(T &_q_value) noexcept
{
return ++_q_value != 0;
}
- static bool deref(T &_q_value) Q_DECL_NOTHROW
+ static bool deref(T &_q_value) noexcept
{
return --_q_value != 0;
}
- static bool testAndSetRelaxed(T &_q_value, T expectedValue, T newValue, T *currentValue = 0) Q_DECL_NOTHROW
+ static bool testAndSetRelaxed(T &_q_value, T expectedValue, T newValue, T *currentValue = nullptr) noexcept
{
if (currentValue)
*currentValue = _q_value;
@@ -76,7 +76,7 @@ template <typename T> struct QAtomicOps: QGenericAtomicOps<QAtomicOps<T> >
return false;
}
- static T fetchAndStoreRelaxed(T &_q_value, T newValue) Q_DECL_NOTHROW
+ static T fetchAndStoreRelaxed(T &_q_value, T newValue) noexcept
{
T tmp = _q_value;
_q_value = newValue;
@@ -84,7 +84,7 @@ template <typename T> struct QAtomicOps: QGenericAtomicOps<QAtomicOps<T> >
}
template <typename AdditiveType> static
- T fetchAndAddRelaxed(T &_q_value, AdditiveType valueToAdd) Q_DECL_NOTHROW
+ T fetchAndAddRelaxed(T &_q_value, AdditiveType valueToAdd) noexcept
{
T returnValue = _q_value;
_q_value += valueToAdd;
diff --git a/src/corelib/thread/qatomic_cxx11.h b/src/corelib/thread/qatomic_cxx11.h
index 2fc0bf5419..7386aee126 100644
--- a/src/corelib/thread/qatomic_cxx11.h
+++ b/src/corelib/thread/qatomic_cxx11.h
@@ -222,43 +222,61 @@ template <typename X> struct QAtomicOps
typedef std::atomic<X> Type;
template <typename T> static inline
- T load(const std::atomic<T> &_q_value) Q_DECL_NOTHROW
+ T load(const std::atomic<T> &_q_value) noexcept
{
return _q_value.load(std::memory_order_relaxed);
}
template <typename T> static inline
- T load(const volatile std::atomic<T> &_q_value) Q_DECL_NOTHROW
+ T load(const volatile std::atomic<T> &_q_value) noexcept
{
return _q_value.load(std::memory_order_relaxed);
}
template <typename T> static inline
- T loadAcquire(const std::atomic<T> &_q_value) Q_DECL_NOTHROW
+ T loadRelaxed(const std::atomic<T> &_q_value) noexcept
+ {
+ return _q_value.load(std::memory_order_relaxed);
+ }
+
+ template <typename T> static inline
+ T loadRelaxed(const volatile std::atomic<T> &_q_value) noexcept
+ {
+ return _q_value.load(std::memory_order_relaxed);
+ }
+
+ template <typename T> static inline
+ T loadAcquire(const std::atomic<T> &_q_value) noexcept
{
return _q_value.load(std::memory_order_acquire);
}
template <typename T> static inline
- T loadAcquire(const volatile std::atomic<T> &_q_value) Q_DECL_NOTHROW
+ T loadAcquire(const volatile std::atomic<T> &_q_value) noexcept
{
return _q_value.load(std::memory_order_acquire);
}
template <typename T> static inline
- void store(std::atomic<T> &_q_value, T newValue) Q_DECL_NOTHROW
+ void store(std::atomic<T> &_q_value, T newValue) noexcept
+ {
+ _q_value.store(newValue, std::memory_order_relaxed);
+ }
+
+ template <typename T> static inline
+ void storeRelaxed(std::atomic<T> &_q_value, T newValue) noexcept
{
_q_value.store(newValue, std::memory_order_relaxed);
}
template <typename T> static inline
- void storeRelease(std::atomic<T> &_q_value, T newValue) Q_DECL_NOTHROW
+ void storeRelease(std::atomic<T> &_q_value, T newValue) noexcept
{
_q_value.store(newValue, std::memory_order_release);
}
- static inline Q_DECL_CONSTEXPR bool isReferenceCountingNative() Q_DECL_NOTHROW { return isTestAndSetNative(); }
- static inline Q_DECL_CONSTEXPR bool isReferenceCountingWaitFree() Q_DECL_NOTHROW { return false; }
+ static inline Q_DECL_CONSTEXPR bool isReferenceCountingNative() noexcept { return isTestAndSetNative(); }
+ static inline Q_DECL_CONSTEXPR bool isReferenceCountingWaitFree() noexcept { return false; }
template <typename T>
static inline bool ref(std::atomic<T> &_q_value)
{
@@ -266,17 +284,17 @@ template <typename X> struct QAtomicOps
}
template <typename T>
- static inline bool deref(std::atomic<T> &_q_value) Q_DECL_NOTHROW
+ static inline bool deref(std::atomic<T> &_q_value) noexcept
{
return --_q_value != 0;
}
- static inline Q_DECL_CONSTEXPR bool isTestAndSetNative() Q_DECL_NOTHROW
+ static inline Q_DECL_CONSTEXPR bool isTestAndSetNative() noexcept
{ return QAtomicTraits<sizeof(X)>::isLockFree(); }
- static inline Q_DECL_CONSTEXPR bool isTestAndSetWaitFree() Q_DECL_NOTHROW { return false; }
+ static inline Q_DECL_CONSTEXPR bool isTestAndSetWaitFree() noexcept { return false; }
template <typename T>
- static bool testAndSetRelaxed(std::atomic<T> &_q_value, T expectedValue, T newValue, T *currentValue = nullptr) Q_DECL_NOTHROW
+ static bool testAndSetRelaxed(std::atomic<T> &_q_value, T expectedValue, T newValue, T *currentValue = nullptr) noexcept
{
bool tmp = _q_value.compare_exchange_strong(expectedValue, newValue, std::memory_order_relaxed, std::memory_order_relaxed);
if (currentValue)
@@ -285,7 +303,7 @@ template <typename X> struct QAtomicOps
}
template <typename T>
- static bool testAndSetAcquire(std::atomic<T> &_q_value, T expectedValue, T newValue, T *currentValue = nullptr) Q_DECL_NOTHROW
+ static bool testAndSetAcquire(std::atomic<T> &_q_value, T expectedValue, T newValue, T *currentValue = nullptr) noexcept
{
bool tmp = _q_value.compare_exchange_strong(expectedValue, newValue, std::memory_order_acquire, std::memory_order_acquire);
if (currentValue)
@@ -294,7 +312,7 @@ template <typename X> struct QAtomicOps
}
template <typename T>
- static bool testAndSetRelease(std::atomic<T> &_q_value, T expectedValue, T newValue, T *currentValue = nullptr) Q_DECL_NOTHROW
+ static bool testAndSetRelease(std::atomic<T> &_q_value, T expectedValue, T newValue, T *currentValue = nullptr) noexcept
{
bool tmp = _q_value.compare_exchange_strong(expectedValue, newValue, std::memory_order_release, std::memory_order_relaxed);
if (currentValue)
@@ -303,7 +321,7 @@ template <typename X> struct QAtomicOps
}
template <typename T>
- static bool testAndSetOrdered(std::atomic<T> &_q_value, T expectedValue, T newValue, T *currentValue = nullptr) Q_DECL_NOTHROW
+ static bool testAndSetOrdered(std::atomic<T> &_q_value, T expectedValue, T newValue, T *currentValue = nullptr) noexcept
{
bool tmp = _q_value.compare_exchange_strong(expectedValue, newValue, std::memory_order_acq_rel, std::memory_order_acquire);
if (currentValue)
@@ -311,158 +329,158 @@ template <typename X> struct QAtomicOps
return tmp;
}
- static inline Q_DECL_CONSTEXPR bool isFetchAndStoreNative() Q_DECL_NOTHROW { return isTestAndSetNative(); }
- static inline Q_DECL_CONSTEXPR bool isFetchAndStoreWaitFree() Q_DECL_NOTHROW { return false; }
+ static inline Q_DECL_CONSTEXPR bool isFetchAndStoreNative() noexcept { return isTestAndSetNative(); }
+ static inline Q_DECL_CONSTEXPR bool isFetchAndStoreWaitFree() noexcept { return false; }
template <typename T>
- static T fetchAndStoreRelaxed(std::atomic<T> &_q_value, T newValue) Q_DECL_NOTHROW
+ static T fetchAndStoreRelaxed(std::atomic<T> &_q_value, T newValue) noexcept
{
return _q_value.exchange(newValue, std::memory_order_relaxed);
}
template <typename T>
- static T fetchAndStoreAcquire(std::atomic<T> &_q_value, T newValue) Q_DECL_NOTHROW
+ static T fetchAndStoreAcquire(std::atomic<T> &_q_value, T newValue) noexcept
{
return _q_value.exchange(newValue, std::memory_order_acquire);
}
template <typename T>
- static T fetchAndStoreRelease(std::atomic<T> &_q_value, T newValue) Q_DECL_NOTHROW
+ static T fetchAndStoreRelease(std::atomic<T> &_q_value, T newValue) noexcept
{
return _q_value.exchange(newValue, std::memory_order_release);
}
template <typename T>
- static T fetchAndStoreOrdered(std::atomic<T> &_q_value, T newValue) Q_DECL_NOTHROW
+ static T fetchAndStoreOrdered(std::atomic<T> &_q_value, T newValue) noexcept
{
return _q_value.exchange(newValue, std::memory_order_acq_rel);
}
- static inline Q_DECL_CONSTEXPR bool isFetchAndAddNative() Q_DECL_NOTHROW { return isTestAndSetNative(); }
- static inline Q_DECL_CONSTEXPR bool isFetchAndAddWaitFree() Q_DECL_NOTHROW { return false; }
+ static inline Q_DECL_CONSTEXPR bool isFetchAndAddNative() noexcept { return isTestAndSetNative(); }
+ static inline Q_DECL_CONSTEXPR bool isFetchAndAddWaitFree() noexcept { return false; }
template <typename T> static inline
- T fetchAndAddRelaxed(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
+ T fetchAndAddRelaxed(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
{
return _q_value.fetch_add(valueToAdd, std::memory_order_relaxed);
}
template <typename T> static inline
- T fetchAndAddAcquire(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
+ T fetchAndAddAcquire(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
{
return _q_value.fetch_add(valueToAdd, std::memory_order_acquire);
}
template <typename T> static inline
- T fetchAndAddRelease(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
+ T fetchAndAddRelease(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
{
return _q_value.fetch_add(valueToAdd, std::memory_order_release);
}
template <typename T> static inline
- T fetchAndAddOrdered(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
+ T fetchAndAddOrdered(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
{
return _q_value.fetch_add(valueToAdd, std::memory_order_acq_rel);
}
template <typename T> static inline
- T fetchAndSubRelaxed(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
+ T fetchAndSubRelaxed(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
{
return _q_value.fetch_sub(valueToAdd, std::memory_order_relaxed);
}
template <typename T> static inline
- T fetchAndSubAcquire(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
+ T fetchAndSubAcquire(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
{
return _q_value.fetch_sub(valueToAdd, std::memory_order_acquire);
}
template <typename T> static inline
- T fetchAndSubRelease(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
+ T fetchAndSubRelease(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
{
return _q_value.fetch_sub(valueToAdd, std::memory_order_release);
}
template <typename T> static inline
- T fetchAndSubOrdered(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
+ T fetchAndSubOrdered(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
{
return _q_value.fetch_sub(valueToAdd, std::memory_order_acq_rel);
}
template <typename T> static inline
- T fetchAndAndRelaxed(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
+ T fetchAndAndRelaxed(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
{
return _q_value.fetch_and(valueToAdd, std::memory_order_relaxed);
}
template <typename T> static inline
- T fetchAndAndAcquire(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
+ T fetchAndAndAcquire(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
{
return _q_value.fetch_and(valueToAdd, std::memory_order_acquire);
}
template <typename T> static inline
- T fetchAndAndRelease(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
+ T fetchAndAndRelease(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
{
return _q_value.fetch_and(valueToAdd, std::memory_order_release);
}
template <typename T> static inline
- T fetchAndAndOrdered(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
+ T fetchAndAndOrdered(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
{
return _q_value.fetch_and(valueToAdd, std::memory_order_acq_rel);
}
template <typename T> static inline
- T fetchAndOrRelaxed(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
+ T fetchAndOrRelaxed(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
{
return _q_value.fetch_or(valueToAdd, std::memory_order_relaxed);
}
template <typename T> static inline
- T fetchAndOrAcquire(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
+ T fetchAndOrAcquire(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
{
return _q_value.fetch_or(valueToAdd, std::memory_order_acquire);
}
template <typename T> static inline
- T fetchAndOrRelease(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
+ T fetchAndOrRelease(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
{
return _q_value.fetch_or(valueToAdd, std::memory_order_release);
}
template <typename T> static inline
- T fetchAndOrOrdered(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
+ T fetchAndOrOrdered(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
{
return _q_value.fetch_or(valueToAdd, std::memory_order_acq_rel);
}
template <typename T> static inline
- T fetchAndXorRelaxed(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
+ T fetchAndXorRelaxed(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
{
return _q_value.fetch_xor(valueToAdd, std::memory_order_relaxed);
}
template <typename T> static inline
- T fetchAndXorAcquire(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
+ T fetchAndXorAcquire(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
{
return _q_value.fetch_xor(valueToAdd, std::memory_order_acquire);
}
template <typename T> static inline
- T fetchAndXorRelease(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
+ T fetchAndXorRelease(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
{
return _q_value.fetch_xor(valueToAdd, std::memory_order_release);
}
template <typename T> static inline
- T fetchAndXorOrdered(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
+ T fetchAndXorOrdered(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
{
return _q_value.fetch_xor(valueToAdd, std::memory_order_acq_rel);
}
};
-#if defined(Q_COMPILER_CONSTEXPR) && defined(Q_COMPILER_DEFAULT_MEMBERS) && defined(Q_COMPILER_DELETE_MEMBERS)
+#if defined(Q_COMPILER_CONSTEXPR)
# define Q_BASIC_ATOMIC_INITIALIZER(a) { a }
#else
# define Q_BASIC_ATOMIC_INITIALIZER(a) { ATOMIC_VAR_INIT(a) }
diff --git a/src/corelib/thread/qatomic_msvc.h b/src/corelib/thread/qatomic_msvc.h
index 5eae2bdc48..67b5224cd7 100644
--- a/src/corelib/thread/qatomic_msvc.h
+++ b/src/corelib/thread/qatomic_msvc.h
@@ -269,24 +269,24 @@ template <> struct QAtomicWindowsType<4> { typedef long Type; };
template <int N> struct QAtomicOpsBySize : QGenericAtomicOps<QAtomicOpsBySize<N> >
{
- static inline Q_DECL_CONSTEXPR bool isReferenceCountingNative() Q_DECL_NOTHROW { return true; }
- static inline Q_DECL_CONSTEXPR bool isReferenceCountingWaitFree() Q_DECL_NOTHROW { return true; }
- template <typename T> static bool ref(T &_q_value) Q_DECL_NOTHROW;
- template <typename T> static bool deref(T &_q_value) Q_DECL_NOTHROW;
-
- static inline Q_DECL_CONSTEXPR bool isTestAndSetNative() Q_DECL_NOTHROW { return true; }
- static inline Q_DECL_CONSTEXPR bool isTestAndSetWaitFree() Q_DECL_NOTHROW { return true; }
- template <typename T> static bool testAndSetRelaxed(T &_q_value, T expectedValue, T newValue) Q_DECL_NOTHROW;
+ static inline Q_DECL_CONSTEXPR bool isReferenceCountingNative() noexcept { return true; }
+ static inline Q_DECL_CONSTEXPR bool isReferenceCountingWaitFree() noexcept { return true; }
+ template <typename T> static bool ref(T &_q_value) noexcept;
+ template <typename T> static bool deref(T &_q_value) noexcept;
+
+ static inline Q_DECL_CONSTEXPR bool isTestAndSetNative() noexcept { return true; }
+ static inline Q_DECL_CONSTEXPR bool isTestAndSetWaitFree() noexcept { return true; }
+ template <typename T> static bool testAndSetRelaxed(T &_q_value, T expectedValue, T newValue) noexcept;
template <typename T>
- static bool testAndSetRelaxed(T &_q_value, T expectedValue, T newValue, T *currentValue) Q_DECL_NOTHROW;
+ static bool testAndSetRelaxed(T &_q_value, T expectedValue, T newValue, T *currentValue) noexcept;
- static inline Q_DECL_CONSTEXPR bool isFetchAndStoreNative() Q_DECL_NOTHROW { return true; }
- static inline Q_DECL_CONSTEXPR bool isFetchAndStoreWaitFree() Q_DECL_NOTHROW { return true; }
- template <typename T> static T fetchAndStoreRelaxed(T &_q_value, T newValue) Q_DECL_NOTHROW;
+ static inline Q_DECL_CONSTEXPR bool isFetchAndStoreNative() noexcept { return true; }
+ static inline Q_DECL_CONSTEXPR bool isFetchAndStoreWaitFree() noexcept { return true; }
+ template <typename T> static T fetchAndStoreRelaxed(T &_q_value, T newValue) noexcept;
- static inline Q_DECL_CONSTEXPR bool isFetchAndAddNative() Q_DECL_NOTHROW { return true; }
- static inline Q_DECL_CONSTEXPR bool isFetchAndAddWaitFree() Q_DECL_NOTHROW { return true; }
- template <typename T> static T fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW;
+ static inline Q_DECL_CONSTEXPR bool isFetchAndAddNative() noexcept { return true; }
+ static inline Q_DECL_CONSTEXPR bool isFetchAndAddWaitFree() noexcept { return true; }
+ template <typename T> static T fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept;
private:
typedef typename QAtomicWindowsType<N>::Type Type;
@@ -303,76 +303,76 @@ struct QAtomicOps : QAtomicOpsBySize<sizeof(T)>
};
template<> template<typename T>
-inline bool QAtomicOpsBySize<4>::ref(T &_q_value) Q_DECL_NOTHROW
+inline bool QAtomicOpsBySize<4>::ref(T &_q_value) noexcept
{
return QT_INTERLOCKED_FUNCTION(Increment)(atomic(&_q_value)) != 0;
}
template<> template<typename T>
-inline bool QAtomicOpsBySize<4>::deref(T &_q_value) Q_DECL_NOTHROW
+inline bool QAtomicOpsBySize<4>::deref(T &_q_value) noexcept
{
return QT_INTERLOCKED_FUNCTION(Decrement)(atomic(&_q_value)) != 0;
}
template<> template<typename T>
-inline bool QAtomicOpsBySize<4>::testAndSetRelaxed(T &_q_value, T expectedValue, T newValue) Q_DECL_NOTHROW
+inline bool QAtomicOpsBySize<4>::testAndSetRelaxed(T &_q_value, T expectedValue, T newValue) noexcept
{
return QT_INTERLOCKED_FUNCTION(CompareExchange)(atomic(&_q_value), value(newValue), value(expectedValue)) == value(expectedValue);
}
template<> template <typename T>
-inline bool QAtomicOpsBySize<4>::testAndSetRelaxed(T &_q_value, T expectedValue, T newValue, T *currentValue) Q_DECL_NOTHROW
+inline bool QAtomicOpsBySize<4>::testAndSetRelaxed(T &_q_value, T expectedValue, T newValue, T *currentValue) noexcept
{
*currentValue = T(QT_INTERLOCKED_FUNCTION(CompareExchange)(atomic(&_q_value), newValue, expectedValue));
return *currentValue == expectedValue;
}
template<> template<typename T>
-inline T QAtomicOpsBySize<4>::fetchAndStoreRelaxed(T &_q_value, T newValue) Q_DECL_NOTHROW
+inline T QAtomicOpsBySize<4>::fetchAndStoreRelaxed(T &_q_value, T newValue) noexcept
{
return QT_INTERLOCKED_FUNCTION(Exchange)(atomic(&_q_value), value(newValue));
}
template<> template<typename T>
-inline T QAtomicOpsBySize<4>::fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
+inline T QAtomicOpsBySize<4>::fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
{
return QT_INTERLOCKED_FUNCTION(ExchangeAdd)(atomic(&_q_value), value<T>(valueToAdd * QAtomicAdditiveType<T>::AddScale));
}
#ifdef Q_ATOMIC_INT16_IS_SUPPORTED
template<> template<typename T>
-inline bool QAtomicOpsBySize<2>::ref(T &_q_value) Q_DECL_NOTHROW
+inline bool QAtomicOpsBySize<2>::ref(T &_q_value) noexcept
{
return QT_INTERLOCKED_FUNCTION(Increment16)(atomic(&_q_value)) != 0;
}
template<> template<typename T>
-inline bool QAtomicOpsBySize<2>::deref(T &_q_value) Q_DECL_NOTHROW
+inline bool QAtomicOpsBySize<2>::deref(T &_q_value) noexcept
{
return QT_INTERLOCKED_FUNCTION(Decrement16)(atomic(&_q_value)) != 0;
}
template<> template<typename T>
-inline bool QAtomicOpsBySize<2>::testAndSetRelaxed(T &_q_value, T expectedValue, T newValue) Q_DECL_NOTHROW
+inline bool QAtomicOpsBySize<2>::testAndSetRelaxed(T &_q_value, T expectedValue, T newValue) noexcept
{
return QT_INTERLOCKED_FUNCTION(CompareExchange16)(atomic(&_q_value), value(newValue), value(expectedValue)) == value(expectedValue);
}
template<> template <typename T>
-inline bool QAtomicOpsBySize<2>::testAndSetRelaxed(T &_q_value, T expectedValue, T newValue, T *currentValue) Q_DECL_NOTHROW
+inline bool QAtomicOpsBySize<2>::testAndSetRelaxed(T &_q_value, T expectedValue, T newValue, T *currentValue) noexcept
{
*currentValue = T(QT_INTERLOCKED_FUNCTION(CompareExchange16)(atomic(&_q_value), newValue, expectedValue));
return *currentValue == expectedValue;
}
template<> template<typename T>
-inline T QAtomicOpsBySize<2>::fetchAndStoreRelaxed(T &_q_value, T newValue) Q_DECL_NOTHROW
+inline T QAtomicOpsBySize<2>::fetchAndStoreRelaxed(T &_q_value, T newValue) noexcept
{
return QT_INTERLOCKED_FUNCTION(Exchange16)(atomic(&_q_value), value(newValue));
}
template<> template<typename T>
-inline T QAtomicOpsBySize<2>::fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
+inline T QAtomicOpsBySize<2>::fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
{
return QT_INTERLOCKED_FUNCTION(ExchangeAdd16)(atomic(&_q_value), value<T>(valueToAdd * QAtomicAdditiveType<T>::AddScale));
}
@@ -380,38 +380,38 @@ inline T QAtomicOpsBySize<2>::fetchAndAddRelaxed(T &_q_value, typename QAtomicAd
#ifdef Q_ATOMIC_INT64_IS_SUPPORTED
template<> template<typename T>
-inline bool QAtomicOpsBySize<8>::ref(T &_q_value) Q_DECL_NOTHROW
+inline bool QAtomicOpsBySize<8>::ref(T &_q_value) noexcept
{
return QT_INTERLOCKED_FUNCTION(Increment64)(atomic(&_q_value)) != 0;
}
template<> template<typename T>
-inline bool QAtomicOpsBySize<8>::deref(T &_q_value) Q_DECL_NOTHROW
+inline bool QAtomicOpsBySize<8>::deref(T &_q_value) noexcept
{
return QT_INTERLOCKED_FUNCTION(Decrement64)(atomic(&_q_value)) != 0;
}
template<> template<typename T>
-inline bool QAtomicOpsBySize<8>::testAndSetRelaxed(T &_q_value, T expectedValue, T newValue) Q_DECL_NOTHROW
+inline bool QAtomicOpsBySize<8>::testAndSetRelaxed(T &_q_value, T expectedValue, T newValue) noexcept
{
return QT_INTERLOCKED_FUNCTION(CompareExchange64)(atomic(&_q_value), value(newValue), value(expectedValue)) == value(expectedValue);
}
template<> template <typename T>
-inline bool QAtomicOpsBySize<8>::testAndSetRelaxed(T &_q_value, T expectedValue, T newValue, T *currentValue) Q_DECL_NOTHROW
+inline bool QAtomicOpsBySize<8>::testAndSetRelaxed(T &_q_value, T expectedValue, T newValue, T *currentValue) noexcept
{
*currentValue = T(QT_INTERLOCKED_FUNCTION(CompareExchange64)(atomic(&_q_value), newValue, expectedValue));
return *currentValue == expectedValue;
}
template<> template<typename T>
-inline T QAtomicOpsBySize<8>::fetchAndStoreRelaxed(T &_q_value, T newValue) Q_DECL_NOTHROW
+inline T QAtomicOpsBySize<8>::fetchAndStoreRelaxed(T &_q_value, T newValue) noexcept
{
return QT_INTERLOCKED_FUNCTION(Exchange64)(atomic(&_q_value), value(newValue));
}
template<> template<typename T>
-inline T QAtomicOpsBySize<8>::fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
+inline T QAtomicOpsBySize<8>::fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
{
return QT_INTERLOCKED_FUNCTION(ExchangeAdd64)(atomic(&_q_value), value<T>(valueToAdd * QAtomicAdditiveType<T>::AddScale));
}
@@ -423,41 +423,41 @@ struct QAtomicOps<T *> : QGenericAtomicOps<QAtomicOps<T *> >
{
typedef T *Type;
- static inline Q_DECL_CONSTEXPR bool isTestAndSetNative() Q_DECL_NOTHROW { return true; }
- static inline Q_DECL_CONSTEXPR bool isTestAndSetWaitFree() Q_DECL_NOTHROW { return true; }
- static bool testAndSetRelaxed(T *&_q_value, T *expectedValue, T *newValue) Q_DECL_NOTHROW;
- static bool testAndSetRelaxed(T *&_q_value, T *expectedValue, T *newValue, T **currentValue) Q_DECL_NOTHROW;
+ static inline Q_DECL_CONSTEXPR bool isTestAndSetNative() noexcept { return true; }
+ static inline Q_DECL_CONSTEXPR bool isTestAndSetWaitFree() noexcept { return true; }
+ static bool testAndSetRelaxed(T *&_q_value, T *expectedValue, T *newValue) noexcept;
+ static bool testAndSetRelaxed(T *&_q_value, T *expectedValue, T *newValue, T **currentValue) noexcept;
- static inline Q_DECL_CONSTEXPR bool isFetchAndStoreNative() Q_DECL_NOTHROW { return true; }
- static inline Q_DECL_CONSTEXPR bool isFetchAndStoreWaitFree() Q_DECL_NOTHROW { return true; }
- static T *fetchAndStoreRelaxed(T *&_q_value, T *newValue) Q_DECL_NOTHROW;
+ static inline Q_DECL_CONSTEXPR bool isFetchAndStoreNative() noexcept { return true; }
+ static inline Q_DECL_CONSTEXPR bool isFetchAndStoreWaitFree() noexcept { return true; }
+ static T *fetchAndStoreRelaxed(T *&_q_value, T *newValue) noexcept;
- static inline Q_DECL_CONSTEXPR bool isFetchAndAddNative() Q_DECL_NOTHROW { return true; }
- static inline Q_DECL_CONSTEXPR bool isFetchAndAddWaitFree() Q_DECL_NOTHROW { return true; }
- static T *fetchAndAddRelaxed(T *&_q_value, qptrdiff valueToAdd) Q_DECL_NOTHROW;
+ static inline Q_DECL_CONSTEXPR bool isFetchAndAddNative() noexcept { return true; }
+ static inline Q_DECL_CONSTEXPR bool isFetchAndAddWaitFree() noexcept { return true; }
+ static T *fetchAndAddRelaxed(T *&_q_value, qptrdiff valueToAdd) noexcept;
};
template <typename T>
-inline bool QAtomicOps<T *>::testAndSetRelaxed(T *&_q_value, T *expectedValue, T *newValue) Q_DECL_NOTHROW
+inline bool QAtomicOps<T *>::testAndSetRelaxed(T *&_q_value, T *expectedValue, T *newValue) noexcept
{
return QT_INTERLOCKED_COMPARE_EXCHANGE_POINTER(&_q_value, newValue, expectedValue) == expectedValue;
}
template <typename T>
-inline bool QAtomicOps<T *>::testAndSetRelaxed(T *&_q_value, T *expectedValue, T *newValue, T **currentValue) Q_DECL_NOTHROW
+inline bool QAtomicOps<T *>::testAndSetRelaxed(T *&_q_value, T *expectedValue, T *newValue, T **currentValue) noexcept
{
*currentValue = reinterpret_cast<T *>(QT_INTERLOCKED_COMPARE_EXCHANGE_POINTER(&_q_value, newValue, expectedValue));
return *currentValue == expectedValue;
}
template <typename T>
-inline T *QAtomicOps<T *>::fetchAndStoreRelaxed(T *&_q_value, T *newValue) Q_DECL_NOTHROW
+inline T *QAtomicOps<T *>::fetchAndStoreRelaxed(T *&_q_value, T *newValue) noexcept
{
return reinterpret_cast<T *>(QT_INTERLOCKED_EXCHANGE_POINTER(&_q_value, newValue));
}
template <typename T>
-inline T *QAtomicOps<T *>::fetchAndAddRelaxed(T *&_q_value, qptrdiff valueToAdd) Q_DECL_NOTHROW
+inline T *QAtomicOps<T *>::fetchAndAddRelaxed(T *&_q_value, qptrdiff valueToAdd) noexcept
{
return reinterpret_cast<T *>(QT_INTERLOCKED_EXCHANGE_ADD_POINTER(&_q_value, valueToAdd * sizeof(T)));
}
diff --git a/src/corelib/thread/qbasicatomic.h b/src/corelib/thread/qbasicatomic.h
index 6b6ac10713..9804e60119 100644
--- a/src/corelib/thread/qbasicatomic.h
+++ b/src/corelib/thread/qbasicatomic.h
@@ -75,7 +75,7 @@ QT_END_NAMESPACE
// New atomics
-#if defined(Q_COMPILER_CONSTEXPR) && defined(Q_COMPILER_DEFAULT_MEMBERS) && defined(Q_COMPILER_DELETE_MEMBERS)
+#if defined(Q_COMPILER_CONSTEXPR)
# if defined(Q_CC_CLANG) && Q_CC_CLANG < 303
/*
Do not define QT_BASIC_ATOMIC_HAS_CONSTRUCTORS for Clang before version 3.3.
@@ -99,126 +99,130 @@ public:
typename Ops::Type _q_value;
// Everything below is either implemented in ../arch/qatomic_XXX.h or (as fallback) in qgenericatomic.h
+#if QT_DEPRECATED_SINCE(5, 14)
+ QT_DEPRECATED_VERSION_X_5_14("Use loadRelaxed") T load() const noexcept { return loadRelaxed(); }
+ QT_DEPRECATED_VERSION_X_5_14("Use storeRelaxed") void store(T newValue) noexcept { storeRelaxed(newValue); }
+#endif
- T load() const Q_DECL_NOTHROW { return Ops::load(_q_value); }
- void store(T newValue) Q_DECL_NOTHROW { Ops::store(_q_value, newValue); }
+ T loadRelaxed() const noexcept { return Ops::loadRelaxed(_q_value); }
+ void storeRelaxed(T newValue) noexcept { Ops::storeRelaxed(_q_value, newValue); }
- T loadAcquire() const Q_DECL_NOTHROW { return Ops::loadAcquire(_q_value); }
- void storeRelease(T newValue) Q_DECL_NOTHROW { Ops::storeRelease(_q_value, newValue); }
- operator T() const Q_DECL_NOTHROW { return loadAcquire(); }
- T operator=(T newValue) Q_DECL_NOTHROW { storeRelease(newValue); return newValue; }
+ T loadAcquire() const noexcept { return Ops::loadAcquire(_q_value); }
+ void storeRelease(T newValue) noexcept { Ops::storeRelease(_q_value, newValue); }
+ operator T() const noexcept { return loadAcquire(); }
+ T operator=(T newValue) noexcept { storeRelease(newValue); return newValue; }
- static Q_DECL_CONSTEXPR bool isReferenceCountingNative() Q_DECL_NOTHROW { return Ops::isReferenceCountingNative(); }
- static Q_DECL_CONSTEXPR bool isReferenceCountingWaitFree() Q_DECL_NOTHROW { return Ops::isReferenceCountingWaitFree(); }
+ static Q_DECL_CONSTEXPR bool isReferenceCountingNative() noexcept { return Ops::isReferenceCountingNative(); }
+ static Q_DECL_CONSTEXPR bool isReferenceCountingWaitFree() noexcept { return Ops::isReferenceCountingWaitFree(); }
- bool ref() Q_DECL_NOTHROW { return Ops::ref(_q_value); }
- bool deref() Q_DECL_NOTHROW { return Ops::deref(_q_value); }
+ bool ref() noexcept { return Ops::ref(_q_value); }
+ bool deref() noexcept { return Ops::deref(_q_value); }
- static Q_DECL_CONSTEXPR bool isTestAndSetNative() Q_DECL_NOTHROW { return Ops::isTestAndSetNative(); }
- static Q_DECL_CONSTEXPR bool isTestAndSetWaitFree() Q_DECL_NOTHROW { return Ops::isTestAndSetWaitFree(); }
+ static Q_DECL_CONSTEXPR bool isTestAndSetNative() noexcept { return Ops::isTestAndSetNative(); }
+ static Q_DECL_CONSTEXPR bool isTestAndSetWaitFree() noexcept { return Ops::isTestAndSetWaitFree(); }
- bool testAndSetRelaxed(T expectedValue, T newValue) Q_DECL_NOTHROW
+ bool testAndSetRelaxed(T expectedValue, T newValue) noexcept
{ return Ops::testAndSetRelaxed(_q_value, expectedValue, newValue); }
- bool testAndSetAcquire(T expectedValue, T newValue) Q_DECL_NOTHROW
+ bool testAndSetAcquire(T expectedValue, T newValue) noexcept
{ return Ops::testAndSetAcquire(_q_value, expectedValue, newValue); }
- bool testAndSetRelease(T expectedValue, T newValue) Q_DECL_NOTHROW
+ bool testAndSetRelease(T expectedValue, T newValue) noexcept
{ return Ops::testAndSetRelease(_q_value, expectedValue, newValue); }
- bool testAndSetOrdered(T expectedValue, T newValue) Q_DECL_NOTHROW
+ bool testAndSetOrdered(T expectedValue, T newValue) noexcept
{ return Ops::testAndSetOrdered(_q_value, expectedValue, newValue); }
- bool testAndSetRelaxed(T expectedValue, T newValue, T &currentValue) Q_DECL_NOTHROW
+ bool testAndSetRelaxed(T expectedValue, T newValue, T &currentValue) noexcept
{ return Ops::testAndSetRelaxed(_q_value, expectedValue, newValue, &currentValue); }
- bool testAndSetAcquire(T expectedValue, T newValue, T &currentValue) Q_DECL_NOTHROW
+ bool testAndSetAcquire(T expectedValue, T newValue, T &currentValue) noexcept
{ return Ops::testAndSetAcquire(_q_value, expectedValue, newValue, &currentValue); }
- bool testAndSetRelease(T expectedValue, T newValue, T &currentValue) Q_DECL_NOTHROW
+ bool testAndSetRelease(T expectedValue, T newValue, T &currentValue) noexcept
{ return Ops::testAndSetRelease(_q_value, expectedValue, newValue, &currentValue); }
- bool testAndSetOrdered(T expectedValue, T newValue, T &currentValue) Q_DECL_NOTHROW
+ bool testAndSetOrdered(T expectedValue, T newValue, T &currentValue) noexcept
{ return Ops::testAndSetOrdered(_q_value, expectedValue, newValue, &currentValue); }
- static Q_DECL_CONSTEXPR bool isFetchAndStoreNative() Q_DECL_NOTHROW { return Ops::isFetchAndStoreNative(); }
- static Q_DECL_CONSTEXPR bool isFetchAndStoreWaitFree() Q_DECL_NOTHROW { return Ops::isFetchAndStoreWaitFree(); }
+ static Q_DECL_CONSTEXPR bool isFetchAndStoreNative() noexcept { return Ops::isFetchAndStoreNative(); }
+ static Q_DECL_CONSTEXPR bool isFetchAndStoreWaitFree() noexcept { return Ops::isFetchAndStoreWaitFree(); }
- T fetchAndStoreRelaxed(T newValue) Q_DECL_NOTHROW
+ T fetchAndStoreRelaxed(T newValue) noexcept
{ return Ops::fetchAndStoreRelaxed(_q_value, newValue); }
- T fetchAndStoreAcquire(T newValue) Q_DECL_NOTHROW
+ T fetchAndStoreAcquire(T newValue) noexcept
{ return Ops::fetchAndStoreAcquire(_q_value, newValue); }
- T fetchAndStoreRelease(T newValue) Q_DECL_NOTHROW
+ T fetchAndStoreRelease(T newValue) noexcept
{ return Ops::fetchAndStoreRelease(_q_value, newValue); }
- T fetchAndStoreOrdered(T newValue) Q_DECL_NOTHROW
+ T fetchAndStoreOrdered(T newValue) noexcept
{ return Ops::fetchAndStoreOrdered(_q_value, newValue); }
- static Q_DECL_CONSTEXPR bool isFetchAndAddNative() Q_DECL_NOTHROW { return Ops::isFetchAndAddNative(); }
- static Q_DECL_CONSTEXPR bool isFetchAndAddWaitFree() Q_DECL_NOTHROW { return Ops::isFetchAndAddWaitFree(); }
+ static Q_DECL_CONSTEXPR bool isFetchAndAddNative() noexcept { return Ops::isFetchAndAddNative(); }
+ static Q_DECL_CONSTEXPR bool isFetchAndAddWaitFree() noexcept { return Ops::isFetchAndAddWaitFree(); }
- T fetchAndAddRelaxed(T valueToAdd) Q_DECL_NOTHROW
+ T fetchAndAddRelaxed(T valueToAdd) noexcept
{ return Ops::fetchAndAddRelaxed(_q_value, valueToAdd); }
- T fetchAndAddAcquire(T valueToAdd) Q_DECL_NOTHROW
+ T fetchAndAddAcquire(T valueToAdd) noexcept
{ return Ops::fetchAndAddAcquire(_q_value, valueToAdd); }
- T fetchAndAddRelease(T valueToAdd) Q_DECL_NOTHROW
+ T fetchAndAddRelease(T valueToAdd) noexcept
{ return Ops::fetchAndAddRelease(_q_value, valueToAdd); }
- T fetchAndAddOrdered(T valueToAdd) Q_DECL_NOTHROW
+ T fetchAndAddOrdered(T valueToAdd) noexcept
{ return Ops::fetchAndAddOrdered(_q_value, valueToAdd); }
- T fetchAndSubRelaxed(T valueToAdd) Q_DECL_NOTHROW
+ T fetchAndSubRelaxed(T valueToAdd) noexcept
{ return Ops::fetchAndSubRelaxed(_q_value, valueToAdd); }
- T fetchAndSubAcquire(T valueToAdd) Q_DECL_NOTHROW
+ T fetchAndSubAcquire(T valueToAdd) noexcept
{ return Ops::fetchAndSubAcquire(_q_value, valueToAdd); }
- T fetchAndSubRelease(T valueToAdd) Q_DECL_NOTHROW
+ T fetchAndSubRelease(T valueToAdd) noexcept
{ return Ops::fetchAndSubRelease(_q_value, valueToAdd); }
- T fetchAndSubOrdered(T valueToAdd) Q_DECL_NOTHROW
+ T fetchAndSubOrdered(T valueToAdd) noexcept
{ return Ops::fetchAndSubOrdered(_q_value, valueToAdd); }
- T fetchAndAndRelaxed(T valueToAdd) Q_DECL_NOTHROW
+ T fetchAndAndRelaxed(T valueToAdd) noexcept
{ return Ops::fetchAndAndRelaxed(_q_value, valueToAdd); }
- T fetchAndAndAcquire(T valueToAdd) Q_DECL_NOTHROW
+ T fetchAndAndAcquire(T valueToAdd) noexcept
{ return Ops::fetchAndAndAcquire(_q_value, valueToAdd); }
- T fetchAndAndRelease(T valueToAdd) Q_DECL_NOTHROW
+ T fetchAndAndRelease(T valueToAdd) noexcept
{ return Ops::fetchAndAndRelease(_q_value, valueToAdd); }
- T fetchAndAndOrdered(T valueToAdd) Q_DECL_NOTHROW
+ T fetchAndAndOrdered(T valueToAdd) noexcept
{ return Ops::fetchAndAndOrdered(_q_value, valueToAdd); }
- T fetchAndOrRelaxed(T valueToAdd) Q_DECL_NOTHROW
+ T fetchAndOrRelaxed(T valueToAdd) noexcept
{ return Ops::fetchAndOrRelaxed(_q_value, valueToAdd); }
- T fetchAndOrAcquire(T valueToAdd) Q_DECL_NOTHROW
+ T fetchAndOrAcquire(T valueToAdd) noexcept
{ return Ops::fetchAndOrAcquire(_q_value, valueToAdd); }
- T fetchAndOrRelease(T valueToAdd) Q_DECL_NOTHROW
+ T fetchAndOrRelease(T valueToAdd) noexcept
{ return Ops::fetchAndOrRelease(_q_value, valueToAdd); }
- T fetchAndOrOrdered(T valueToAdd) Q_DECL_NOTHROW
+ T fetchAndOrOrdered(T valueToAdd) noexcept
{ return Ops::fetchAndOrOrdered(_q_value, valueToAdd); }
- T fetchAndXorRelaxed(T valueToAdd) Q_DECL_NOTHROW
+ T fetchAndXorRelaxed(T valueToAdd) noexcept
{ return Ops::fetchAndXorRelaxed(_q_value, valueToAdd); }
- T fetchAndXorAcquire(T valueToAdd) Q_DECL_NOTHROW
+ T fetchAndXorAcquire(T valueToAdd) noexcept
{ return Ops::fetchAndXorAcquire(_q_value, valueToAdd); }
- T fetchAndXorRelease(T valueToAdd) Q_DECL_NOTHROW
+ T fetchAndXorRelease(T valueToAdd) noexcept
{ return Ops::fetchAndXorRelease(_q_value, valueToAdd); }
- T fetchAndXorOrdered(T valueToAdd) Q_DECL_NOTHROW
+ T fetchAndXorOrdered(T valueToAdd) noexcept
{ return Ops::fetchAndXorOrdered(_q_value, valueToAdd); }
- T operator++() Q_DECL_NOTHROW
+ T operator++() noexcept
{ return fetchAndAddOrdered(1) + 1; }
- T operator++(int) Q_DECL_NOTHROW
+ T operator++(int) noexcept
{ return fetchAndAddOrdered(1); }
- T operator--() Q_DECL_NOTHROW
+ T operator--() noexcept
{ return fetchAndSubOrdered(1) - 1; }
- T operator--(int) Q_DECL_NOTHROW
+ T operator--(int) noexcept
{ return fetchAndSubOrdered(1); }
- T operator+=(T v) Q_DECL_NOTHROW
+ T operator+=(T v) noexcept
{ return fetchAndAddOrdered(v) + v; }
- T operator-=(T v) Q_DECL_NOTHROW
+ T operator-=(T v) noexcept
{ return fetchAndSubOrdered(v) - v; }
- T operator&=(T v) Q_DECL_NOTHROW
+ T operator&=(T v) noexcept
{ return fetchAndAndOrdered(v) & v; }
- T operator|=(T v) Q_DECL_NOTHROW
+ T operator|=(T v) noexcept
{ return fetchAndOrOrdered(v) | v; }
- T operator^=(T v) Q_DECL_NOTHROW
+ T operator^=(T v) noexcept
{ return fetchAndXorOrdered(v) ^ v; }
#ifdef QT_BASIC_ATOMIC_HAS_CONSTRUCTORS
QBasicAtomicInteger() = default;
- constexpr QBasicAtomicInteger(T value) Q_DECL_NOTHROW : _q_value(value) {}
+ constexpr QBasicAtomicInteger(T value) noexcept : _q_value(value) {}
QBasicAtomicInteger(const QBasicAtomicInteger &) = delete;
QBasicAtomicInteger &operator=(const QBasicAtomicInteger &) = delete;
QBasicAtomicInteger &operator=(const QBasicAtomicInteger &) volatile = delete;
@@ -236,85 +240,91 @@ public:
AtomicType _q_value;
- Type load() const Q_DECL_NOTHROW { return Ops::load(_q_value); }
- void store(Type newValue) Q_DECL_NOTHROW { Ops::store(_q_value, newValue); }
- operator Type() const Q_DECL_NOTHROW { return loadAcquire(); }
- Type operator=(Type newValue) Q_DECL_NOTHROW { storeRelease(newValue); return newValue; }
+#if QT_DEPRECATED_SINCE(5, 14)
+ QT_DEPRECATED_VERSION_X_5_14("Use loadRelaxed") Type load() const noexcept { return loadRelaxed(); }
+ QT_DEPRECATED_VERSION_X_5_14("Use storeRelaxed") void store(Type newValue) noexcept { storeRelaxed(newValue); }
+#endif
+
+ Type loadRelaxed() const noexcept { return Ops::loadRelaxed(_q_value); }
+ void storeRelaxed(Type newValue) noexcept { Ops::storeRelaxed(_q_value, newValue); }
+
+ operator Type() const noexcept { return loadAcquire(); }
+ Type operator=(Type newValue) noexcept { storeRelease(newValue); return newValue; }
// Atomic API, implemented in qatomic_XXX.h
- Type loadAcquire() const Q_DECL_NOTHROW { return Ops::loadAcquire(_q_value); }
- void storeRelease(Type newValue) Q_DECL_NOTHROW { Ops::storeRelease(_q_value, newValue); }
+ Type loadAcquire() const noexcept { return Ops::loadAcquire(_q_value); }
+ void storeRelease(Type newValue) noexcept { Ops::storeRelease(_q_value, newValue); }
- static Q_DECL_CONSTEXPR bool isTestAndSetNative() Q_DECL_NOTHROW { return Ops::isTestAndSetNative(); }
- static Q_DECL_CONSTEXPR bool isTestAndSetWaitFree() Q_DECL_NOTHROW { return Ops::isTestAndSetWaitFree(); }
+ static Q_DECL_CONSTEXPR bool isTestAndSetNative() noexcept { return Ops::isTestAndSetNative(); }
+ static Q_DECL_CONSTEXPR bool isTestAndSetWaitFree() noexcept { return Ops::isTestAndSetWaitFree(); }
- bool testAndSetRelaxed(Type expectedValue, Type newValue) Q_DECL_NOTHROW
+ bool testAndSetRelaxed(Type expectedValue, Type newValue) noexcept
{ return Ops::testAndSetRelaxed(_q_value, expectedValue, newValue); }
- bool testAndSetAcquire(Type expectedValue, Type newValue) Q_DECL_NOTHROW
+ bool testAndSetAcquire(Type expectedValue, Type newValue) noexcept
{ return Ops::testAndSetAcquire(_q_value, expectedValue, newValue); }
- bool testAndSetRelease(Type expectedValue, Type newValue) Q_DECL_NOTHROW
+ bool testAndSetRelease(Type expectedValue, Type newValue) noexcept
{ return Ops::testAndSetRelease(_q_value, expectedValue, newValue); }
- bool testAndSetOrdered(Type expectedValue, Type newValue) Q_DECL_NOTHROW
+ bool testAndSetOrdered(Type expectedValue, Type newValue) noexcept
{ return Ops::testAndSetOrdered(_q_value, expectedValue, newValue); }
- bool testAndSetRelaxed(Type expectedValue, Type newValue, Type &currentValue) Q_DECL_NOTHROW
+ bool testAndSetRelaxed(Type expectedValue, Type newValue, Type &currentValue) noexcept
{ return Ops::testAndSetRelaxed(_q_value, expectedValue, newValue, &currentValue); }
- bool testAndSetAcquire(Type expectedValue, Type newValue, Type &currentValue) Q_DECL_NOTHROW
+ bool testAndSetAcquire(Type expectedValue, Type newValue, Type &currentValue) noexcept
{ return Ops::testAndSetAcquire(_q_value, expectedValue, newValue, &currentValue); }
- bool testAndSetRelease(Type expectedValue, Type newValue, Type &currentValue) Q_DECL_NOTHROW
+ bool testAndSetRelease(Type expectedValue, Type newValue, Type &currentValue) noexcept
{ return Ops::testAndSetRelease(_q_value, expectedValue, newValue, &currentValue); }
- bool testAndSetOrdered(Type expectedValue, Type newValue, Type &currentValue) Q_DECL_NOTHROW
+ bool testAndSetOrdered(Type expectedValue, Type newValue, Type &currentValue) noexcept
{ return Ops::testAndSetOrdered(_q_value, expectedValue, newValue, &currentValue); }
- static Q_DECL_CONSTEXPR bool isFetchAndStoreNative() Q_DECL_NOTHROW { return Ops::isFetchAndStoreNative(); }
- static Q_DECL_CONSTEXPR bool isFetchAndStoreWaitFree() Q_DECL_NOTHROW { return Ops::isFetchAndStoreWaitFree(); }
+ static Q_DECL_CONSTEXPR bool isFetchAndStoreNative() noexcept { return Ops::isFetchAndStoreNative(); }
+ static Q_DECL_CONSTEXPR bool isFetchAndStoreWaitFree() noexcept { return Ops::isFetchAndStoreWaitFree(); }
- Type fetchAndStoreRelaxed(Type newValue) Q_DECL_NOTHROW
+ Type fetchAndStoreRelaxed(Type newValue) noexcept
{ return Ops::fetchAndStoreRelaxed(_q_value, newValue); }
- Type fetchAndStoreAcquire(Type newValue) Q_DECL_NOTHROW
+ Type fetchAndStoreAcquire(Type newValue) noexcept
{ return Ops::fetchAndStoreAcquire(_q_value, newValue); }
- Type fetchAndStoreRelease(Type newValue) Q_DECL_NOTHROW
+ Type fetchAndStoreRelease(Type newValue) noexcept
{ return Ops::fetchAndStoreRelease(_q_value, newValue); }
- Type fetchAndStoreOrdered(Type newValue) Q_DECL_NOTHROW
+ Type fetchAndStoreOrdered(Type newValue) noexcept
{ return Ops::fetchAndStoreOrdered(_q_value, newValue); }
- static Q_DECL_CONSTEXPR bool isFetchAndAddNative() Q_DECL_NOTHROW { return Ops::isFetchAndAddNative(); }
- static Q_DECL_CONSTEXPR bool isFetchAndAddWaitFree() Q_DECL_NOTHROW { return Ops::isFetchAndAddWaitFree(); }
+ static Q_DECL_CONSTEXPR bool isFetchAndAddNative() noexcept { return Ops::isFetchAndAddNative(); }
+ static Q_DECL_CONSTEXPR bool isFetchAndAddWaitFree() noexcept { return Ops::isFetchAndAddWaitFree(); }
- Type fetchAndAddRelaxed(qptrdiff valueToAdd) Q_DECL_NOTHROW
+ Type fetchAndAddRelaxed(qptrdiff valueToAdd) noexcept
{ return Ops::fetchAndAddRelaxed(_q_value, valueToAdd); }
- Type fetchAndAddAcquire(qptrdiff valueToAdd) Q_DECL_NOTHROW
+ Type fetchAndAddAcquire(qptrdiff valueToAdd) noexcept
{ return Ops::fetchAndAddAcquire(_q_value, valueToAdd); }
- Type fetchAndAddRelease(qptrdiff valueToAdd) Q_DECL_NOTHROW
+ Type fetchAndAddRelease(qptrdiff valueToAdd) noexcept
{ return Ops::fetchAndAddRelease(_q_value, valueToAdd); }
- Type fetchAndAddOrdered(qptrdiff valueToAdd) Q_DECL_NOTHROW
+ Type fetchAndAddOrdered(qptrdiff valueToAdd) noexcept
{ return Ops::fetchAndAddOrdered(_q_value, valueToAdd); }
- Type fetchAndSubRelaxed(qptrdiff valueToAdd) Q_DECL_NOTHROW
+ Type fetchAndSubRelaxed(qptrdiff valueToAdd) noexcept
{ return Ops::fetchAndSubRelaxed(_q_value, valueToAdd); }
- Type fetchAndSubAcquire(qptrdiff valueToAdd) Q_DECL_NOTHROW
+ Type fetchAndSubAcquire(qptrdiff valueToAdd) noexcept
{ return Ops::fetchAndSubAcquire(_q_value, valueToAdd); }
- Type fetchAndSubRelease(qptrdiff valueToAdd) Q_DECL_NOTHROW
+ Type fetchAndSubRelease(qptrdiff valueToAdd) noexcept
{ return Ops::fetchAndSubRelease(_q_value, valueToAdd); }
- Type fetchAndSubOrdered(qptrdiff valueToAdd) Q_DECL_NOTHROW
+ Type fetchAndSubOrdered(qptrdiff valueToAdd) noexcept
{ return Ops::fetchAndSubOrdered(_q_value, valueToAdd); }
- Type operator++() Q_DECL_NOTHROW
+ Type operator++() noexcept
{ return fetchAndAddOrdered(1) + 1; }
- Type operator++(int) Q_DECL_NOTHROW
+ Type operator++(int) noexcept
{ return fetchAndAddOrdered(1); }
- Type operator--() Q_DECL_NOTHROW
+ Type operator--() noexcept
{ return fetchAndSubOrdered(1) - 1; }
- Type operator--(int) Q_DECL_NOTHROW
+ Type operator--(int) noexcept
{ return fetchAndSubOrdered(1); }
- Type operator+=(qptrdiff valueToAdd) Q_DECL_NOTHROW
+ Type operator+=(qptrdiff valueToAdd) noexcept
{ return fetchAndAddOrdered(valueToAdd) + valueToAdd; }
- Type operator-=(qptrdiff valueToSub) Q_DECL_NOTHROW
+ Type operator-=(qptrdiff valueToSub) noexcept
{ return fetchAndSubOrdered(valueToSub) - valueToSub; }
#ifdef QT_BASIC_ATOMIC_HAS_CONSTRUCTORS
QBasicAtomicPointer() = default;
- constexpr QBasicAtomicPointer(Type value) Q_DECL_NOTHROW : _q_value(value) {}
+ constexpr QBasicAtomicPointer(Type value) noexcept : _q_value(value) {}
QBasicAtomicPointer(const QBasicAtomicPointer &) = delete;
QBasicAtomicPointer &operator=(const QBasicAtomicPointer &) = delete;
QBasicAtomicPointer &operator=(const QBasicAtomicPointer &) volatile = delete;
diff --git a/src/corelib/thread/qfutex_p.h b/src/corelib/thread/qfutex_p.h
index 483664c783..7bec4554b7 100644
--- a/src/corelib/thread/qfutex_p.h
+++ b/src/corelib/thread/qfutex_p.h
@@ -81,15 +81,43 @@ QT_END_NAMESPACE
// if not defined in linux/futex.h
# define FUTEX_PRIVATE_FLAG 128 // added in v2.6.22
+# if QT_HAS_FEATURE(thread_sanitizer) || defined(__SANITIZE_THREAD__)
+# include <sanitizer/tsan_interface.h>
+inline void _q_tsan_acquire(void *addr, void *addr2)
+{
+ __tsan_acquire(addr);
+ if (addr2)
+ __tsan_acquire(addr2);
+}
+inline void _q_tsan_release(void *addr, void *addr2)
+{
+ if (addr2)
+ __tsan_release(addr2);
+ __tsan_release(addr);
+}
+# else
+inline void _q_tsan_acquire(void *, void *) {}
+inline void _q_tsan_release(void *, void *) {}
+# endif // QT_HAS_FEATURE(thread_sanitizer) || defined(__SANITIZE_THREAD__)
+
QT_BEGIN_NAMESPACE
namespace QtLinuxFutex {
constexpr inline bool futexAvailable() { return true; }
inline int _q_futex(int *addr, int op, int val, quintptr val2 = 0,
- int *addr2 = nullptr, int val3 = 0) Q_DECL_NOTHROW
+ int *addr2 = nullptr, int val3 = 0) noexcept
{
+ // A futex call ensures total ordering on the futex words
+ // (in either success or failure of the call). Instruct TSAN accordingly,
+ // as TSAN does not understand the futex(2) syscall.
+ _q_tsan_release(addr, addr2);
+
// we use __NR_futex because some libcs (like Android's bionic) don't
// provide SYS_futex etc.
- return syscall(__NR_futex, addr, op | FUTEX_PRIVATE_FLAG, val, val2, addr2, val3);
+ int result = syscall(__NR_futex, addr, op | FUTEX_PRIVATE_FLAG, val, val2, addr2, val3);
+
+ _q_tsan_acquire(addr, addr2);
+
+ return result;
}
template <typename T> int *addr(T *ptr)
{
diff --git a/src/corelib/thread/qfuture.h b/src/corelib/thread/qfuture.h
index a456dd9139..d3135510b3 100644
--- a/src/corelib/thread/qfuture.h
+++ b/src/corelib/thread/qfuture.h
@@ -111,33 +111,79 @@ public:
typedef const T &reference;
inline const_iterator() {}
- inline const_iterator(QFuture const * const _future, int _index) : future(_future), index(_index) {}
+ inline const_iterator(QFuture const * const _future, int _index)
+ : future(_future), index(advanceIndex(_index, 0)) { }
inline const_iterator(const const_iterator &o) : future(o.future), index(o.index) {}
inline const_iterator &operator=(const const_iterator &o)
{ future = o.future; index = o.index; return *this; }
inline const T &operator*() const { return future->d.resultReference(index); }
inline const T *operator->() const { return future->d.resultPointer(index); }
-
- inline bool operator!=(const const_iterator &other) const
+ inline bool operator!=(const const_iterator &other) const { return index != other.index; }
+ inline bool operator==(const const_iterator &o) const { return !operator!=(o); }
+ inline const_iterator &operator++()
+ { index = advanceIndex(index, 1); return *this; }
+ inline const_iterator &operator--()
+ { index = advanceIndex(index, -1); return *this; }
+ inline const_iterator operator++(int)
+ {
+ const_iterator r = *this;
+ index = advanceIndex(index, 1);
+ return r;
+ }
+ inline const_iterator operator--(int)
{
- if (index == -1 && other.index == -1) // comparing end != end?
- return false;
- if (other.index == -1)
- return (future->isRunning() || (index < future->resultCount()));
- return (index != other.index);
+ const_iterator r = *this;
+ index = advanceIndex(index, -1);
+ return r;
}
+ inline const_iterator operator+(int j) const
+ { return const_iterator(future, advanceIndex(index, j)); }
+ inline const_iterator operator-(int j) const
+ { return const_iterator(future, advanceIndex(index, -j)); }
+ inline const_iterator &operator+=(int j)
+ { index = advanceIndex(index, j); return *this; }
+ inline const_iterator &operator-=(int j)
+ { index = advanceIndex(index, -j); return *this; }
+ friend inline const_iterator operator+(int j, const_iterator k)
+ { return const_iterator(k.future, k.advanceIndex(k.index, j)); }
- inline bool operator==(const const_iterator &o) const { return !operator!=(o); }
- inline const_iterator &operator++() { ++index; return *this; }
- inline const_iterator operator++(int) { const_iterator r = *this; ++index; return r; }
- inline const_iterator &operator--() { --index; return *this; }
- inline const_iterator operator--(int) { const_iterator r = *this; --index; return r; }
- inline const_iterator operator+(int j) const { return const_iterator(future, index + j); }
- inline const_iterator operator-(int j) const { return const_iterator(future, index - j); }
- inline const_iterator &operator+=(int j) { index += j; return *this; }
- inline const_iterator &operator-=(int j) { index -= j; return *this; }
- friend inline const_iterator operator+(int j, const_iterator k) { return k + j; }
private:
+ /*! \internal
+
+ Advances the iterator index \a idx \a n steps, waits for the
+ result at the target index, and returns the target index.
+
+ The index may be -1, indicating the end iterator, either
+ as the argument or as the return value. The end iterator
+ may be decremented.
+
+ The caller is responsible for not advancing the iterator
+ before begin() or past end(), with the exception that
+ attempting to advance a non-end iterator past end() for
+ a running future is allowed and will return the end iterator.
+
+ Note that n == 0 is valid and will wait for the result
+ at the given index.
+ */
+ int advanceIndex(int idx, int n) const
+ {
+ // The end iterator can be decremented, leave as-is for other cases
+ if (idx == -1 && n >= 0)
+ return idx;
+
+ // Special case for decrementing the end iterator: wait for
+ // finished to get the total result count.
+ if (idx == -1 && future->isRunning())
+ future->d.waitForFinished();
+
+ // Wait for result at target index
+ const int targetIndex = (idx == -1) ? future->resultCount() + n : idx + n;
+ future->d.waitForResult(targetIndex);
+
+ // After waiting there is either a result or the end was reached
+ return (targetIndex < future->resultCount()) ? targetIndex : -1;
+ }
+
QFuture const * future;
int index;
};
diff --git a/src/corelib/thread/qfutureinterface.cpp b/src/corelib/thread/qfutureinterface.cpp
index dfbed5fb0f..6430f38a3b 100644
--- a/src/corelib/thread/qfutureinterface.cpp
+++ b/src/corelib/thread/qfutureinterface.cpp
@@ -97,7 +97,7 @@ static inline int switch_off(QAtomicInt &a, int which)
static inline int switch_from_to(QAtomicInt &a, int from, int to)
{
int newValue;
- int expected = a.load();
+ int expected = a.loadRelaxed();
do {
newValue = (expected & ~from) | to;
} while (!a.testAndSetRelaxed(expected, newValue, expected));
@@ -107,7 +107,7 @@ static inline int switch_from_to(QAtomicInt &a, int from, int to)
void QFutureInterfaceBase::cancel()
{
QMutexLocker locker(&d->m_mutex);
- if (d->state.load() & Canceled)
+ if (d->state.loadRelaxed() & Canceled)
return;
switch_from_to(d->state, Paused, Canceled);
@@ -132,7 +132,7 @@ void QFutureInterfaceBase::setPaused(bool paused)
void QFutureInterfaceBase::togglePaused()
{
QMutexLocker locker(&d->m_mutex);
- if (d->state.load() & Paused) {
+ if (d->state.loadRelaxed() & Paused) {
switch_off(d->state, Paused);
d->pausedWaitCondition.wakeAll();
d->sendCallOut(QFutureCallOutEvent(QFutureCallOutEvent::Resumed));
@@ -149,7 +149,7 @@ void QFutureInterfaceBase::setThrottled(bool enable)
switch_on(d->state, Throttled);
} else {
switch_off(d->state, Throttled);
- if (!(d->state.load() & Paused))
+ if (!(d->state.loadRelaxed() & Paused))
d->pausedWaitCondition.wakeAll();
}
}
@@ -201,13 +201,13 @@ void QFutureInterfaceBase::waitForResume()
{
// return early if possible to avoid taking the mutex lock.
{
- const int state = d->state.load();
+ const int state = d->state.loadRelaxed();
if (!(state & Paused) || (state & Canceled))
return;
}
QMutexLocker lock(&d->m_mutex);
- const int state = d->state.load();
+ const int state = d->state.loadRelaxed();
if (!(state & Paused) || (state & Canceled))
return;
@@ -256,7 +256,7 @@ bool QFutureInterfaceBase::isProgressUpdateNeeded() const
void QFutureInterfaceBase::reportStarted()
{
QMutexLocker locker(&d->m_mutex);
- if (d->state.load() & (Started|Canceled|Finished))
+ if (d->state.loadRelaxed() & (Started|Canceled|Finished))
return;
d->setState(State(Started | Running));
@@ -272,7 +272,7 @@ void QFutureInterfaceBase::reportCanceled()
void QFutureInterfaceBase::reportException(const QException &exception)
{
QMutexLocker locker(&d->m_mutex);
- if (d->state.load() & (Canceled|Finished))
+ if (d->state.loadRelaxed() & (Canceled|Finished))
return;
d->m_exceptionStore.setException(exception);
@@ -307,7 +307,7 @@ int QFutureInterfaceBase::expectedResultCount()
bool QFutureInterfaceBase::queryState(State state) const
{
- return d->state.load() & state;
+ return d->state.loadRelaxed() & state;
}
void QFutureInterfaceBase::waitForResult(int resultIndex)
@@ -352,7 +352,7 @@ void QFutureInterfaceBase::waitForFinished()
void QFutureInterfaceBase::reportResultsReady(int beginIndex, int endIndex)
{
- if (beginIndex == endIndex || (d->state.load() & (Canceled|Finished)))
+ if (beginIndex == endIndex || (d->state.loadRelaxed() & (Canceled|Finished)))
return;
d->waitCondition.wakeAll();
@@ -414,7 +414,7 @@ void QFutureInterfaceBase::setProgressValueAndText(int progressValue,
if (d->m_progressValue >= progressValue)
return;
- if (d->state.load() & (Canceled|Finished))
+ if (d->state.loadRelaxed() & (Canceled|Finished))
return;
if (d->internal_updateProgress(progressValue, progressText)) {
@@ -429,6 +429,11 @@ QMutex *QFutureInterfaceBase::mutex() const
return &d->m_mutex;
}
+QMutex &QFutureInterfaceBase::mutex(int) const
+{
+ return d->m_mutex;
+}
+
QtPrivate::ExceptionStore &QFutureInterfaceBase::exceptionStore()
{
return d->m_exceptionStore;
@@ -486,10 +491,10 @@ bool QFutureInterfaceBasePrivate::internal_waitForNextResult()
if (m_results.hasNextResult())
return true;
- while ((state.load() & QFutureInterfaceBase::Running) && m_results.hasNextResult() == false)
+ while ((state.loadRelaxed() & QFutureInterfaceBase::Running) && m_results.hasNextResult() == false)
waitCondition.wait(&m_mutex);
- return !(state.load() & QFutureInterfaceBase::Canceled) && m_results.hasNextResult();
+ return !(state.loadRelaxed() & QFutureInterfaceBase::Canceled) && m_results.hasNextResult();
}
bool QFutureInterfaceBasePrivate::internal_updateProgress(int progress,
@@ -512,8 +517,8 @@ bool QFutureInterfaceBasePrivate::internal_updateProgress(int progress,
void QFutureInterfaceBasePrivate::internal_setThrottled(bool enable)
{
// bail out if we are not changing the state
- if ((enable && (state.load() & QFutureInterfaceBase::Throttled))
- || (!enable && !(state.load() & QFutureInterfaceBase::Throttled)))
+ if ((enable && (state.loadRelaxed() & QFutureInterfaceBase::Throttled))
+ || (!enable && !(state.loadRelaxed() & QFutureInterfaceBase::Throttled)))
return;
// change the state
@@ -521,7 +526,7 @@ void QFutureInterfaceBasePrivate::internal_setThrottled(bool enable)
switch_on(state, QFutureInterfaceBase::Throttled);
} else {
switch_off(state, QFutureInterfaceBase::Throttled);
- if (!(state.load() & QFutureInterfaceBase::Paused))
+ if (!(state.loadRelaxed() & QFutureInterfaceBase::Paused))
pausedWaitCondition.wakeAll();
}
}
@@ -556,7 +561,7 @@ void QFutureInterfaceBasePrivate::connectOutputInterface(QFutureCallOutInterface
{
QMutexLocker locker(&m_mutex);
- if (state.load() & QFutureInterfaceBase::Started) {
+ if (state.loadRelaxed() & QFutureInterfaceBase::Started) {
interface->postCallOutEvent(QFutureCallOutEvent(QFutureCallOutEvent::Started));
interface->postCallOutEvent(QFutureCallOutEvent(QFutureCallOutEvent::ProgressRange,
m_progressMinimum,
@@ -576,13 +581,13 @@ void QFutureInterfaceBasePrivate::connectOutputInterface(QFutureCallOutInterface
it.batchedAdvance();
}
- if (state.load() & QFutureInterfaceBase::Paused)
+ if (state.loadRelaxed() & QFutureInterfaceBase::Paused)
interface->postCallOutEvent(QFutureCallOutEvent(QFutureCallOutEvent::Paused));
- if (state.load() & QFutureInterfaceBase::Canceled)
+ if (state.loadRelaxed() & QFutureInterfaceBase::Canceled)
interface->postCallOutEvent(QFutureCallOutEvent(QFutureCallOutEvent::Canceled));
- if (state.load() & QFutureInterfaceBase::Finished)
+ if (state.loadRelaxed() & QFutureInterfaceBase::Finished)
interface->postCallOutEvent(QFutureCallOutEvent(QFutureCallOutEvent::Finished));
outputConnections.append(interface);
@@ -601,7 +606,7 @@ void QFutureInterfaceBasePrivate::disconnectOutputInterface(QFutureCallOutInterf
void QFutureInterfaceBasePrivate::setState(QFutureInterfaceBase::State newState)
{
- state.store(newState);
+ state.storeRelaxed(newState);
}
QT_END_NAMESPACE
diff --git a/src/corelib/thread/qfutureinterface.h b/src/corelib/thread/qfutureinterface.h
index d5e2401eee..bcdae24833 100644
--- a/src/corelib/thread/qfutureinterface.h
+++ b/src/corelib/thread/qfutureinterface.h
@@ -45,6 +45,8 @@
#include <QtCore/qexception.h>
#include <QtCore/qresultstore.h>
+#include <mutex>
+
QT_REQUIRE_CONFIG(future);
QT_BEGIN_NAMESPACE
@@ -118,6 +120,7 @@ public:
void waitForResume();
QMutex *mutex() const;
+ QMutex &mutex(int) const;
QtPrivate::ExceptionStore &exceptionStore();
QtPrivate::ResultStoreBase &resultStoreBase();
const QtPrivate::ResultStoreBase &resultStoreBase() const;
@@ -188,7 +191,7 @@ public:
template <typename T>
inline void QFutureInterface<T>::reportResult(const T *result, int index)
{
- QMutexLocker locker(mutex());
+ std::lock_guard<QMutex> locker(mutex(0));
if (this->queryState(Canceled) || this->queryState(Finished)) {
return;
}
@@ -214,7 +217,7 @@ inline void QFutureInterface<T>::reportResult(const T &result, int index)
template <typename T>
inline void QFutureInterface<T>::reportResults(const QVector<T> &_results, int beginIndex, int count)
{
- QMutexLocker locker(mutex());
+ std::lock_guard<QMutex> locker(mutex(0));
if (this->queryState(Canceled) || this->queryState(Finished)) {
return;
}
@@ -242,14 +245,14 @@ inline void QFutureInterface<T>::reportFinished(const T *result)
template <typename T>
inline const T &QFutureInterface<T>::resultReference(int index) const
{
- QMutexLocker lock(mutex());
+ std::lock_guard<QMutex> locker(mutex(0));
return resultStoreBase().resultAt(index).template value<T>();
}
template <typename T>
inline const T *QFutureInterface<T>::resultPointer(int index) const
{
- QMutexLocker lock(mutex());
+ std::lock_guard<QMutex> locker(mutex(0));
return resultStoreBase().resultAt(index).template pointer<T>();
}
@@ -263,7 +266,7 @@ inline QList<T> QFutureInterface<T>::results()
QFutureInterfaceBase::waitForResult(-1);
QList<T> res;
- QMutexLocker lock(mutex());
+ std::lock_guard<QMutex> locker(mutex(0));
QtPrivate::ResultIteratorBase it = resultStoreBase().begin();
while (it != resultStoreBase().end()) {
diff --git a/src/corelib/thread/qfutureinterface_p.h b/src/corelib/thread/qfutureinterface_p.h
index 63e534464f..b297dff633 100644
--- a/src/corelib/thread/qfutureinterface_p.h
+++ b/src/corelib/thread/qfutureinterface_p.h
@@ -144,11 +144,11 @@ public:
// Default ref counter for QFIBP
inline bool ref() { return m_refCount.ref(); }
inline bool deref() { return m_refCount.deref(); }
- inline int load() const { return m_refCount.load(); }
+ inline int load() const { return m_refCount.loadRelaxed(); }
// Ref counter for type T
inline bool refT() { return m_refCountT.ref(); }
inline bool derefT() { return m_refCountT.deref(); }
- inline int loadT() const { return m_refCountT.load(); }
+ inline int loadT() const { return m_refCountT.loadRelaxed(); }
private:
QAtomicInt m_refCount;
diff --git a/src/corelib/thread/qfuturewatcher.cpp b/src/corelib/thread/qfuturewatcher.cpp
index cf220bbd48..06bc4740f9 100644
--- a/src/corelib/thread/qfuturewatcher.cpp
+++ b/src/corelib/thread/qfuturewatcher.cpp
@@ -402,7 +402,7 @@ void QFutureWatcherBase::disconnectOutputInterface(bool pendingAssignment)
{
if (pendingAssignment) {
Q_D(QFutureWatcherBase);
- d->pendingResultsReady.store(0);
+ d->pendingResultsReady.storeRelaxed(0);
qDeleteAll(d->pendingCallOutEvents);
d->pendingCallOutEvents.clear();
d->finished = false; /* May soon be amended, during connectOutputInterface() */
@@ -441,7 +441,7 @@ void QFutureWatcherBasePrivate::sendCallOutEvent(QFutureCallOutEvent *event)
emit q->finished();
break;
case QFutureCallOutEvent::Canceled:
- pendingResultsReady.store(0);
+ pendingResultsReady.storeRelaxed(0);
emit q->canceled();
break;
case QFutureCallOutEvent::Paused:
@@ -466,7 +466,7 @@ void QFutureWatcherBasePrivate::sendCallOutEvent(QFutureCallOutEvent *event)
emit q->resultsReadyAt(beginIndex, endIndex);
- if (resultAtConnected.load() <= 0)
+ if (resultAtConnected.loadRelaxed() <= 0)
break;
for (int i = beginIndex; i < endIndex; ++i)
diff --git a/src/corelib/thread/qgenericatomic.h b/src/corelib/thread/qgenericatomic.h
index 89c4fe9a11..e9e5f3c74b 100644
--- a/src/corelib/thread/qgenericatomic.h
+++ b/src/corelib/thread/qgenericatomic.h
@@ -72,32 +72,44 @@ template <typename BaseClass> struct QGenericAtomicOps
{
template <typename T> struct AtomicType { typedef T Type; typedef T *PointerType; };
- template <typename T> static void acquireMemoryFence(const T &_q_value) Q_DECL_NOTHROW
+ template <typename T> static void acquireMemoryFence(const T &_q_value) noexcept
{
BaseClass::orderedMemoryFence(_q_value);
}
- template <typename T> static void releaseMemoryFence(const T &_q_value) Q_DECL_NOTHROW
+ template <typename T> static void releaseMemoryFence(const T &_q_value) noexcept
{
BaseClass::orderedMemoryFence(_q_value);
}
- template <typename T> static void orderedMemoryFence(const T &) Q_DECL_NOTHROW
+ template <typename T> static void orderedMemoryFence(const T &) noexcept
{
}
template <typename T> static Q_ALWAYS_INLINE
- T load(const T &_q_value) Q_DECL_NOTHROW
+ T load(const T &_q_value) noexcept
{
return _q_value;
}
template <typename T, typename X> static Q_ALWAYS_INLINE
- void store(T &_q_value, X newValue) Q_DECL_NOTHROW
+ void store(T &_q_value, X newValue) noexcept
{
_q_value = newValue;
}
template <typename T> static Q_ALWAYS_INLINE
- T loadAcquire(const T &_q_value) Q_DECL_NOTHROW
+ T loadRelaxed(const T &_q_value) noexcept
+ {
+ return _q_value;
+ }
+
+ template <typename T, typename X> static Q_ALWAYS_INLINE
+ void storeRelaxed(T &_q_value, X newValue) noexcept
+ {
+ _q_value = newValue;
+ }
+
+ template <typename T> static Q_ALWAYS_INLINE
+ T loadAcquire(const T &_q_value) noexcept
{
T tmp = *static_cast<const volatile T *>(&_q_value);
BaseClass::acquireMemoryFence(_q_value);
@@ -105,24 +117,24 @@ template <typename BaseClass> struct QGenericAtomicOps
}
template <typename T, typename X> static Q_ALWAYS_INLINE
- void storeRelease(T &_q_value, X newValue) Q_DECL_NOTHROW
+ void storeRelease(T &_q_value, X newValue) noexcept
{
BaseClass::releaseMemoryFence(_q_value);
*static_cast<volatile T *>(&_q_value) = newValue;
}
- static inline Q_DECL_CONSTEXPR bool isReferenceCountingNative() Q_DECL_NOTHROW
+ static inline Q_DECL_CONSTEXPR bool isReferenceCountingNative() noexcept
{ return BaseClass::isFetchAndAddNative(); }
- static inline Q_DECL_CONSTEXPR bool isReferenceCountingWaitFree() Q_DECL_NOTHROW
+ static inline Q_DECL_CONSTEXPR bool isReferenceCountingWaitFree() noexcept
{ return BaseClass::isFetchAndAddWaitFree(); }
template <typename T> static Q_ALWAYS_INLINE
- bool ref(T &_q_value) Q_DECL_NOTHROW
+ bool ref(T &_q_value) noexcept
{
return BaseClass::fetchAndAddRelaxed(_q_value, 1) != T(-1);
}
template <typename T> static Q_ALWAYS_INLINE
- bool deref(T &_q_value) Q_DECL_NOTHROW
+ bool deref(T &_q_value) noexcept
{
return BaseClass::fetchAndAddRelaxed(_q_value, -1) != 1;
}
@@ -130,16 +142,16 @@ template <typename BaseClass> struct QGenericAtomicOps
#if 0
// These functions have no default implementation
// Archictectures must implement them
- static inline Q_DECL_CONSTEXPR bool isTestAndSetNative() Q_DECL_NOTHROW;
- static inline Q_DECL_CONSTEXPR bool isTestAndSetWaitFree() Q_DECL_NOTHROW;
+ static inline Q_DECL_CONSTEXPR bool isTestAndSetNative() noexcept;
+ static inline Q_DECL_CONSTEXPR bool isTestAndSetWaitFree() noexcept;
template <typename T, typename X> static inline
- bool testAndSetRelaxed(T &_q_value, X expectedValue, X newValue) Q_DECL_NOTHROW;
+ bool testAndSetRelaxed(T &_q_value, X expectedValue, X newValue) noexcept;
template <typename T, typename X> static inline
- bool testAndSetRelaxed(T &_q_value, X expectedValue, X newValue, X *currentValue) Q_DECL_NOTHROW;
+ bool testAndSetRelaxed(T &_q_value, X expectedValue, X newValue, X *currentValue) noexcept;
#endif
template <typename T, typename X> static Q_ALWAYS_INLINE
- bool testAndSetAcquire(T &_q_value, X expectedValue, X newValue) Q_DECL_NOTHROW
+ bool testAndSetAcquire(T &_q_value, X expectedValue, X newValue) noexcept
{
bool tmp = BaseClass::testAndSetRelaxed(_q_value, expectedValue, newValue);
BaseClass::acquireMemoryFence(_q_value);
@@ -147,21 +159,21 @@ template <typename BaseClass> struct QGenericAtomicOps
}
template <typename T, typename X> static Q_ALWAYS_INLINE
- bool testAndSetRelease(T &_q_value, X expectedValue, X newValue) Q_DECL_NOTHROW
+ bool testAndSetRelease(T &_q_value, X expectedValue, X newValue) noexcept
{
BaseClass::releaseMemoryFence(_q_value);
return BaseClass::testAndSetRelaxed(_q_value, expectedValue, newValue);
}
template <typename T, typename X> static Q_ALWAYS_INLINE
- bool testAndSetOrdered(T &_q_value, X expectedValue, X newValue) Q_DECL_NOTHROW
+ bool testAndSetOrdered(T &_q_value, X expectedValue, X newValue) noexcept
{
BaseClass::orderedMemoryFence(_q_value);
return BaseClass::testAndSetRelaxed(_q_value, expectedValue, newValue);
}
template <typename T, typename X> static Q_ALWAYS_INLINE
- bool testAndSetAcquire(T &_q_value, X expectedValue, X newValue, X *currentValue) Q_DECL_NOTHROW
+ bool testAndSetAcquire(T &_q_value, X expectedValue, X newValue, X *currentValue) noexcept
{
bool tmp = BaseClass::testAndSetRelaxed(_q_value, expectedValue, newValue, currentValue);
BaseClass::acquireMemoryFence(_q_value);
@@ -169,35 +181,35 @@ template <typename BaseClass> struct QGenericAtomicOps
}
template <typename T, typename X> static Q_ALWAYS_INLINE
- bool testAndSetRelease(T &_q_value, X expectedValue, X newValue, X *currentValue) Q_DECL_NOTHROW
+ bool testAndSetRelease(T &_q_value, X expectedValue, X newValue, X *currentValue) noexcept
{
BaseClass::releaseMemoryFence(_q_value);
return BaseClass::testAndSetRelaxed(_q_value, expectedValue, newValue, currentValue);
}
template <typename T, typename X> static Q_ALWAYS_INLINE
- bool testAndSetOrdered(T &_q_value, X expectedValue, X newValue, X *currentValue) Q_DECL_NOTHROW
+ bool testAndSetOrdered(T &_q_value, X expectedValue, X newValue, X *currentValue) noexcept
{
BaseClass::orderedMemoryFence(_q_value);
return BaseClass::testAndSetRelaxed(_q_value, expectedValue, newValue, currentValue);
}
- static inline Q_DECL_CONSTEXPR bool isFetchAndStoreNative() Q_DECL_NOTHROW { return false; }
- static inline Q_DECL_CONSTEXPR bool isFetchAndStoreWaitFree() Q_DECL_NOTHROW { return false; }
+ static inline Q_DECL_CONSTEXPR bool isFetchAndStoreNative() noexcept { return false; }
+ static inline Q_DECL_CONSTEXPR bool isFetchAndStoreWaitFree() noexcept { return false; }
template <typename T, typename X> static Q_ALWAYS_INLINE
- T fetchAndStoreRelaxed(T &_q_value, X newValue) Q_DECL_NOTHROW
+ T fetchAndStoreRelaxed(T &_q_value, X newValue) noexcept
{
// implement fetchAndStore on top of testAndSet
Q_FOREVER {
- T tmp = load(_q_value);
+ T tmp = loadRelaxed(_q_value);
if (BaseClass::testAndSetRelaxed(_q_value, tmp, newValue))
return tmp;
}
}
template <typename T, typename X> static Q_ALWAYS_INLINE
- T fetchAndStoreAcquire(T &_q_value, X newValue) Q_DECL_NOTHROW
+ T fetchAndStoreAcquire(T &_q_value, X newValue) noexcept
{
T tmp = BaseClass::fetchAndStoreRelaxed(_q_value, newValue);
BaseClass::acquireMemoryFence(_q_value);
@@ -205,34 +217,34 @@ template <typename BaseClass> struct QGenericAtomicOps
}
template <typename T, typename X> static Q_ALWAYS_INLINE
- T fetchAndStoreRelease(T &_q_value, X newValue) Q_DECL_NOTHROW
+ T fetchAndStoreRelease(T &_q_value, X newValue) noexcept
{
BaseClass::releaseMemoryFence(_q_value);
return BaseClass::fetchAndStoreRelaxed(_q_value, newValue);
}
template <typename T, typename X> static Q_ALWAYS_INLINE
- T fetchAndStoreOrdered(T &_q_value, X newValue) Q_DECL_NOTHROW
+ T fetchAndStoreOrdered(T &_q_value, X newValue) noexcept
{
BaseClass::orderedMemoryFence(_q_value);
return BaseClass::fetchAndStoreRelaxed(_q_value, newValue);
}
- static inline Q_DECL_CONSTEXPR bool isFetchAndAddNative() Q_DECL_NOTHROW { return false; }
- static inline Q_DECL_CONSTEXPR bool isFetchAndAddWaitFree() Q_DECL_NOTHROW { return false; }
+ static inline Q_DECL_CONSTEXPR bool isFetchAndAddNative() noexcept { return false; }
+ static inline Q_DECL_CONSTEXPR bool isFetchAndAddWaitFree() noexcept { return false; }
template <typename T> static Q_ALWAYS_INLINE
- T fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
+ T fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
{
// implement fetchAndAdd on top of testAndSet
Q_FOREVER {
- T tmp = BaseClass::load(_q_value);
+ T tmp = BaseClass::loadRelaxed(_q_value);
if (BaseClass::testAndSetRelaxed(_q_value, tmp, T(tmp + valueToAdd)))
return tmp;
}
}
template <typename T> static Q_ALWAYS_INLINE
- T fetchAndAddAcquire(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
+ T fetchAndAddAcquire(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
{
T tmp = BaseClass::fetchAndAddRelaxed(_q_value, valueToAdd);
BaseClass::acquireMemoryFence(_q_value);
@@ -240,14 +252,14 @@ template <typename BaseClass> struct QGenericAtomicOps
}
template <typename T> static Q_ALWAYS_INLINE
- T fetchAndAddRelease(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
+ T fetchAndAddRelease(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
{
BaseClass::releaseMemoryFence(_q_value);
return BaseClass::fetchAndAddRelaxed(_q_value, valueToAdd);
}
template <typename T> static Q_ALWAYS_INLINE
- T fetchAndAddOrdered(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
+ T fetchAndAddOrdered(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
{
BaseClass::orderedMemoryFence(_q_value);
return BaseClass::fetchAndAddRelaxed(_q_value, valueToAdd);
@@ -256,7 +268,7 @@ template <typename BaseClass> struct QGenericAtomicOps
QT_WARNING_PUSH
QT_WARNING_DISABLE_MSVC(4146) // unary minus operator applied to unsigned type, result still unsigned
template <typename T> static Q_ALWAYS_INLINE
- T fetchAndSubRelaxed(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT operand) Q_DECL_NOTHROW
+ T fetchAndSubRelaxed(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT operand) noexcept
{
// implement fetchAndSub on top of fetchAndAdd
return fetchAndAddRelaxed(_q_value, -operand);
@@ -264,7 +276,7 @@ QT_WARNING_DISABLE_MSVC(4146) // unary minus operator applied to unsigned type
QT_WARNING_POP
template <typename T> static Q_ALWAYS_INLINE
- T fetchAndSubAcquire(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT operand) Q_DECL_NOTHROW
+ T fetchAndSubAcquire(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT operand) noexcept
{
T tmp = BaseClass::fetchAndSubRelaxed(_q_value, operand);
BaseClass::acquireMemoryFence(_q_value);
@@ -272,24 +284,24 @@ QT_WARNING_POP
}
template <typename T> static Q_ALWAYS_INLINE
- T fetchAndSubRelease(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT operand) Q_DECL_NOTHROW
+ T fetchAndSubRelease(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT operand) noexcept
{
BaseClass::releaseMemoryFence(_q_value);
return BaseClass::fetchAndSubRelaxed(_q_value, operand);
}
template <typename T> static Q_ALWAYS_INLINE
- T fetchAndSubOrdered(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT operand) Q_DECL_NOTHROW
+ T fetchAndSubOrdered(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT operand) noexcept
{
BaseClass::orderedMemoryFence(_q_value);
return BaseClass::fetchAndSubRelaxed(_q_value, operand);
}
template <typename T> static Q_ALWAYS_INLINE
- T fetchAndAndRelaxed(T &_q_value, typename std::enable_if<QTypeInfo<T>::isIntegral, T>::type operand) Q_DECL_NOTHROW
+ T fetchAndAndRelaxed(T &_q_value, typename std::enable_if<QTypeInfo<T>::isIntegral, T>::type operand) noexcept
{
// implement fetchAndAnd on top of testAndSet
- T tmp = BaseClass::load(_q_value);
+ T tmp = BaseClass::loadRelaxed(_q_value);
Q_FOREVER {
if (BaseClass::testAndSetRelaxed(_q_value, tmp, T(tmp & operand), &tmp))
return tmp;
@@ -297,7 +309,7 @@ QT_WARNING_POP
}
template <typename T> static Q_ALWAYS_INLINE
- T fetchAndAndAcquire(T &_q_value, typename std::enable_if<QTypeInfo<T>::isIntegral, T>::type operand) Q_DECL_NOTHROW
+ T fetchAndAndAcquire(T &_q_value, typename std::enable_if<QTypeInfo<T>::isIntegral, T>::type operand) noexcept
{
T tmp = BaseClass::fetchAndAndRelaxed(_q_value, operand);
BaseClass::acquireMemoryFence(_q_value);
@@ -305,24 +317,24 @@ QT_WARNING_POP
}
template <typename T> static Q_ALWAYS_INLINE
- T fetchAndAndRelease(T &_q_value, typename std::enable_if<QTypeInfo<T>::isIntegral, T>::type operand) Q_DECL_NOTHROW
+ T fetchAndAndRelease(T &_q_value, typename std::enable_if<QTypeInfo<T>::isIntegral, T>::type operand) noexcept
{
BaseClass::releaseMemoryFence(_q_value);
return BaseClass::fetchAndAndRelaxed(_q_value, operand);
}
template <typename T> static Q_ALWAYS_INLINE
- T fetchAndAndOrdered(T &_q_value, typename std::enable_if<QTypeInfo<T>::isIntegral, T>::type operand) Q_DECL_NOTHROW
+ T fetchAndAndOrdered(T &_q_value, typename std::enable_if<QTypeInfo<T>::isIntegral, T>::type operand) noexcept
{
BaseClass::orderedMemoryFence(_q_value);
return BaseClass::fetchAndAndRelaxed(_q_value, operand);
}
template <typename T> static Q_ALWAYS_INLINE
- T fetchAndOrRelaxed(T &_q_value, typename std::enable_if<QTypeInfo<T>::isIntegral, T>::type operand) Q_DECL_NOTHROW
+ T fetchAndOrRelaxed(T &_q_value, typename std::enable_if<QTypeInfo<T>::isIntegral, T>::type operand) noexcept
{
// implement fetchAndOr on top of testAndSet
- T tmp = BaseClass::load(_q_value);
+ T tmp = BaseClass::loadRelaxed(_q_value);
Q_FOREVER {
if (BaseClass::testAndSetRelaxed(_q_value, tmp, T(tmp | operand), &tmp))
return tmp;
@@ -330,7 +342,7 @@ QT_WARNING_POP
}
template <typename T> static Q_ALWAYS_INLINE
- T fetchAndOrAcquire(T &_q_value, typename std::enable_if<QTypeInfo<T>::isIntegral, T>::type operand) Q_DECL_NOTHROW
+ T fetchAndOrAcquire(T &_q_value, typename std::enable_if<QTypeInfo<T>::isIntegral, T>::type operand) noexcept
{
T tmp = BaseClass::fetchAndOrRelaxed(_q_value, operand);
BaseClass::acquireMemoryFence(_q_value);
@@ -338,24 +350,24 @@ QT_WARNING_POP
}
template <typename T> static Q_ALWAYS_INLINE
- T fetchAndOrRelease(T &_q_value, typename std::enable_if<QTypeInfo<T>::isIntegral, T>::type operand) Q_DECL_NOTHROW
+ T fetchAndOrRelease(T &_q_value, typename std::enable_if<QTypeInfo<T>::isIntegral, T>::type operand) noexcept
{
BaseClass::releaseMemoryFence(_q_value);
return BaseClass::fetchAndOrRelaxed(_q_value, operand);
}
template <typename T> static Q_ALWAYS_INLINE
- T fetchAndOrOrdered(T &_q_value, typename std::enable_if<QTypeInfo<T>::isIntegral, T>::type operand) Q_DECL_NOTHROW
+ T fetchAndOrOrdered(T &_q_value, typename std::enable_if<QTypeInfo<T>::isIntegral, T>::type operand) noexcept
{
BaseClass::orderedMemoryFence(_q_value);
return BaseClass::fetchAndOrRelaxed(_q_value, operand);
}
template <typename T> static Q_ALWAYS_INLINE
- T fetchAndXorRelaxed(T &_q_value, typename std::enable_if<QTypeInfo<T>::isIntegral, T>::type operand) Q_DECL_NOTHROW
+ T fetchAndXorRelaxed(T &_q_value, typename std::enable_if<QTypeInfo<T>::isIntegral, T>::type operand) noexcept
{
// implement fetchAndXor on top of testAndSet
- T tmp = BaseClass::load(_q_value);
+ T tmp = BaseClass::loadRelaxed(_q_value);
Q_FOREVER {
if (BaseClass::testAndSetRelaxed(_q_value, tmp, T(tmp ^ operand), &tmp))
return tmp;
@@ -363,7 +375,7 @@ QT_WARNING_POP
}
template <typename T> static Q_ALWAYS_INLINE
- T fetchAndXorAcquire(T &_q_value, typename std::enable_if<QTypeInfo<T>::isIntegral, T>::type operand) Q_DECL_NOTHROW
+ T fetchAndXorAcquire(T &_q_value, typename std::enable_if<QTypeInfo<T>::isIntegral, T>::type operand) noexcept
{
T tmp = BaseClass::fetchAndXorRelaxed(_q_value, operand);
BaseClass::acquireMemoryFence(_q_value);
@@ -371,14 +383,14 @@ QT_WARNING_POP
}
template <typename T> static Q_ALWAYS_INLINE
- T fetchAndXorRelease(T &_q_value, typename std::enable_if<QTypeInfo<T>::isIntegral, T>::type operand) Q_DECL_NOTHROW
+ T fetchAndXorRelease(T &_q_value, typename std::enable_if<QTypeInfo<T>::isIntegral, T>::type operand) noexcept
{
BaseClass::releaseMemoryFence(_q_value);
return BaseClass::fetchAndXorRelaxed(_q_value, operand);
}
template <typename T> static Q_ALWAYS_INLINE
- T fetchAndXorOrdered(T &_q_value, typename std::enable_if<QTypeInfo<T>::isIntegral, T>::type operand) Q_DECL_NOTHROW
+ T fetchAndXorOrdered(T &_q_value, typename std::enable_if<QTypeInfo<T>::isIntegral, T>::type operand) noexcept
{
BaseClass::orderedMemoryFence(_q_value);
return BaseClass::fetchAndXorRelaxed(_q_value, operand);
diff --git a/src/corelib/thread/qlocking_p.h b/src/corelib/thread/qlocking_p.h
new file mode 100644
index 0000000000..9a796cf7f7
--- /dev/null
+++ b/src/corelib/thread/qlocking_p.h
@@ -0,0 +1,119 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Klarรคlvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
+** 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 QLOCKING_P_H
+#define QLOCKING_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of qmutex.cpp, qmutex_unix.cpp, and qmutex_win.cpp. This header
+// file may change from version to version without notice, or even be
+// removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qmutex.h>
+
+#include <mutex>
+
+QT_BEGIN_NAMESPACE
+
+//
+// This API is bridging the time until we can depend on C++17:
+//
+// - qt_scoped_lock returns a lock that cannot be unlocked again before the end of the scope
+// - qt_unique_lock returns a lock that can be unlock()ed and moved around
+// - for compat with QMutexLocker, qt_unique_lock supports passing by pointer.
+// Do NOT use this overload lightly; it's only for cases such as where a Q_GLOBAL_STATIC
+// may have already been deleted. In particular, do NOT port from
+// QMutexLocker locker(&mutex);
+// to
+// auto locker = qt_unique_lock(&mutex);
+// as this will not port automatically to std::unique_lock come C++17!
+//
+// The intent, come C++17, is to replace
+// qt_scoped_lock(mutex);
+// qt_unique_lock(mutex); // except qt_unique_lock(&mutex)
+// with
+// std::scoped_lock(mutex);
+// std::unique_lock(mutex);
+// resp. (C++17 meaning CTAD, guaranteed copy elision + scoped_lock available on all platforms),
+// so please use these functions only in ways which don't break this mechanical search & replace.
+//
+
+namespace {
+
+template <typename Mutex, typename Lock =
+#if defined(__cpp_guaranteed_copy_elision) && __cpp_guaranteed_copy_elision >= 201606L
+# if defined(__cpp_lib_scoped_lock) && __cpp_lib_scoped_lock >= 201703L
+ std::scoped_lock
+# else
+ std::lock_guard
+# endif
+#else
+ std::unique_lock
+#endif
+ <typename std::decay<Mutex>::type>
+>
+Lock qt_scoped_lock(Mutex &mutex)
+{
+ return Lock(mutex);
+}
+
+template <typename Mutex, typename Lock = std::unique_lock<typename std::decay<Mutex>::type>>
+Lock qt_unique_lock(Mutex &mutex)
+{
+ return Lock(mutex);
+}
+
+template <typename Mutex, typename Lock = std::unique_lock<typename std::decay<Mutex>::type>>
+Lock qt_unique_lock(Mutex *mutex)
+{
+ return mutex ? Lock(*mutex) : Lock() ;
+}
+
+} // unnamed namespace
+
+QT_END_NAMESPACE
+
+#endif // QLOCKING_P_H
diff --git a/src/corelib/thread/qmutex.cpp b/src/corelib/thread/qmutex.cpp
index 3881ac017e..9e52f286ee 100644
--- a/src/corelib/thread/qmutex.cpp
+++ b/src/corelib/thread/qmutex.cpp
@@ -82,7 +82,7 @@ public:
QMutex mutex;
bool lock(int timeout) QT_MUTEX_LOCK_NOEXCEPT;
- void unlock() Q_DECL_NOTHROW;
+ void unlock() noexcept;
};
/*
@@ -147,7 +147,7 @@ public:
It is constructed and destroyed with almost no overhead,
which means it is fine to have many mutexes as part of other classes.
- \sa QMutexLocker, QReadWriteLock, QSemaphore, QWaitCondition
+ \sa QRecursiveMutex, QMutexLocker, QReadWriteLock, QSemaphore, QWaitCondition
*/
/*!
@@ -156,12 +156,19 @@ public:
\value Recursive In this mode, a thread can lock the same mutex
multiple times and the mutex won't be unlocked
until a corresponding number of unlock() calls
- have been made.
+ have been made. You should use QRecursiveMutex
+ for this use-case.
\value NonRecursive In this mode, a thread may only lock a mutex
once.
- \sa QMutex()
+ \sa QMutex(), QRecursiveMutex
+*/
+
+/*!
+ \fn QMutex::QMutex()
+
+ Constructs a new mutex. The mutex is created in an unlocked state.
*/
/*!
@@ -179,7 +186,7 @@ public:
*/
QMutex::QMutex(RecursionMode mode)
{
- d_ptr.store(mode == Recursive ? new QRecursiveMutexPrivate : 0);
+ d_ptr.storeRelaxed(mode == Recursive ? new QRecursiveMutexPrivate : 0);
}
/*!
@@ -189,12 +196,12 @@ QMutex::QMutex(RecursionMode mode)
*/
QMutex::~QMutex()
{
- QMutexData *d = d_ptr.load();
+ QMutexData *d = d_ptr.loadRelaxed();
if (isRecursive()) {
delete static_cast<QRecursiveMutexPrivate *>(d);
} else if (d) {
#ifndef QT_LINUX_FUTEX
- if (d != dummyLocked() && static_cast<QMutexPrivate *>(d)->possiblyUnlocked.load()
+ if (d != dummyLocked() && static_cast<QMutexPrivate *>(d)->possiblyUnlocked.loadRelaxed()
&& tryLock()) {
unlock();
return;
@@ -205,13 +212,15 @@ QMutex::~QMutex()
}
/*! \fn void QMutex::lock()
+ \fn QRecursiveMutex::lock()
+
Locks the mutex. If another thread has locked the mutex then this
call will block until that thread has unlocked it.
Calling this function multiple times on the same mutex from the
same thread is allowed if this mutex is a
- \l{QMutex::Recursive}{recursive mutex}. If this mutex is a
- \l{QMutex::NonRecursive}{non-recursive mutex}, this function will
+ \l{QRecursiveMutex}{recursive mutex}. If this mutex is a
+ \l{QMutex}{non-recursive mutex}, this function will
\e dead-lock when the mutex is locked recursively.
\sa unlock()
@@ -228,6 +237,7 @@ void QMutex::lock() QT_MUTEX_LOCK_NOEXCEPT
}
/*! \fn bool QMutex::tryLock(int timeout)
+ \fn bool QRecursiveMutex::tryLock(int timeout)
Attempts to lock the mutex. This function returns \c true if the lock
was obtained; otherwise it returns \c false. If another thread has
@@ -243,8 +253,8 @@ void QMutex::lock() QT_MUTEX_LOCK_NOEXCEPT
Calling this function multiple times on the same mutex from the
same thread is allowed if this mutex is a
- \l{QMutex::Recursive}{recursive mutex}. If this mutex is a
- \l{QMutex::NonRecursive}{non-recursive mutex}, this function will
+ \l{QRecursiveMutex}{recursive mutex}. If this mutex is a
+ \l{QMutex}{non-recursive mutex}, this function will
\e always return false when attempting to lock the mutex
recursively.
@@ -262,6 +272,7 @@ bool QMutex::tryLock(int timeout) QT_MUTEX_LOCK_NOEXCEPT
}
/*! \fn bool QMutex::try_lock()
+ \fn bool QRecursiveMutex::try_lock()
\since 5.8
Attempts to lock the mutex. This function returns \c true if the lock
@@ -275,6 +286,7 @@ bool QMutex::tryLock(int timeout) QT_MUTEX_LOCK_NOEXCEPT
*/
/*! \fn template <class Rep, class Period> bool QMutex::try_lock_for(std::chrono::duration<Rep, Period> duration)
+ \fn template <class Rep, class Period> bool QRecursiveMutex::try_lock_for(std::chrono::duration<Rep, Period> duration)
\since 5.8
Attempts to lock the mutex. This function returns \c true if the lock
@@ -290,8 +302,8 @@ bool QMutex::tryLock(int timeout) QT_MUTEX_LOCK_NOEXCEPT
Calling this function multiple times on the same mutex from the
same thread is allowed if this mutex is a
- \l{QMutex::Recursive}{recursive mutex}. If this mutex is a
- \l{QMutex::NonRecursive}{non-recursive mutex}, this function will
+ \l{QRecursiveMutex}{recursive mutex}. If this mutex is a
+ \l{QMutex}{non-recursive mutex}, this function will
\e always return false when attempting to lock the mutex
recursively.
@@ -299,6 +311,7 @@ bool QMutex::tryLock(int timeout) QT_MUTEX_LOCK_NOEXCEPT
*/
/*! \fn template<class Clock, class Duration> bool QMutex::try_lock_until(std::chrono::time_point<Clock, Duration> timePoint)
+ \fn template<class Clock, class Duration> bool QRecursiveMutex::try_lock_until(std::chrono::time_point<Clock, Duration> timePoint)
\since 5.8
Attempts to lock the mutex. This function returns \c true if the lock
@@ -314,8 +327,8 @@ bool QMutex::tryLock(int timeout) QT_MUTEX_LOCK_NOEXCEPT
Calling this function multiple times on the same mutex from the
same thread is allowed if this mutex is a
- \l{QMutex::Recursive}{recursive mutex}. If this mutex is a
- \l{QMutex::NonRecursive}{non-recursive mutex}, this function will
+ \l{QRecursiveMutex}{recursive mutex}. If this mutex is a
+ \l{QMutex}{non-recursive mutex}, this function will
\e always return false when attempting to lock the mutex
recursively.
@@ -323,13 +336,15 @@ bool QMutex::tryLock(int timeout) QT_MUTEX_LOCK_NOEXCEPT
*/
/*! \fn void QMutex::unlock()
+ \fn void QRecursiveMutex::unlock()
+
Unlocks the mutex. Attempting to unlock a mutex in a different
thread to the one that locked it results in an error. Unlocking a
mutex that is not locked results in undefined behavior.
\sa lock()
*/
-void QMutex::unlock() Q_DECL_NOTHROW
+void QMutex::unlock() noexcept
{
QMutexData *current;
if (fastTryUnlock(current))
@@ -348,7 +363,7 @@ void QMutex::unlock() Q_DECL_NOTHROW
Returns \c true if the mutex is recursive.
*/
-bool QBasicMutex::isRecursive() Q_DECL_NOTHROW
+bool QBasicMutex::isRecursive() noexcept
{
return QT_PREPEND_NAMESPACE(isRecursive)(d_ptr.loadAcquire());
}
@@ -358,12 +373,64 @@ bool QBasicMutex::isRecursive() Q_DECL_NOTHROW
Returns \c true if the mutex is recursive.
*/
-bool QBasicMutex::isRecursive() const Q_DECL_NOTHROW
+bool QBasicMutex::isRecursive() const noexcept
{
return QT_PREPEND_NAMESPACE(isRecursive)(d_ptr.loadAcquire());
}
/*!
+ \class QRecursiveMutex
+ \inmodule QtCore
+ \since 5.14
+ \brief The QRecursiveMutex class provides access serialization between threads.
+
+ \threadsafe
+
+ \ingroup thread
+
+ The QRecursiveMutex class is a mutex, like QMutex, with which it is
+ API-compatible. It differs from QMutex by accepting lock() calls from
+ the same thread any number of times. QMutex would deadlock in this situation.
+
+ QRecursiveMutex is much more expensive to construct and operate on, so
+ use a plain QMutex whenever you can. Sometimes, one public function,
+ however, calls another public function, and they both need to lock the
+ same mutex. In this case, you have two options:
+
+ \list
+ \li Factor the code that needs mutex protection into private functions,
+ which assume that the mutex is held when they are called, and lock a
+ plain QMutex in the public functions before you call the private
+ implementation ones.
+ \li Or use a recursive mutex, so it doesn't matter that the first public
+ function has already locked the mutex when the second one wishes to do so.
+ \endlist
+
+ \sa QMutex, QMutexLocker, QReadWriteLock, QSemaphore, QWaitCondition
+*/
+
+/*!
+ Constructs a new recursive mutex. The mutex is created in an unlocked state.
+
+ \sa lock(), unlock()
+*/
+QRecursiveMutex::QRecursiveMutex()
+ : QMutex()
+{
+ d_ptr.storeRelaxed(new QRecursiveMutexPrivate);
+}
+
+/*!
+ Destroys the mutex.
+
+ \warning Destroying a locked mutex may result in undefined behavior.
+*/
+QRecursiveMutex::~QRecursiveMutex()
+{
+ delete static_cast<QRecursiveMutexPrivate*>(d_ptr.fetchAndStoreAcquire(nullptr));
+}
+
+/*!
\class QMutexLocker
\inmodule QtCore
\brief The QMutexLocker class is a convenience class that simplifies
@@ -427,6 +494,17 @@ bool QBasicMutex::isRecursive() const Q_DECL_NOTHROW
*/
/*!
+ \fn QMutexLocker::QMutexLocker(QRecursiveMutex *mutex)
+ \since 5.14
+
+ Constructs a QMutexLocker and locks \a mutex. The mutex will be
+ unlocked (unlock() called) when the QMutexLocker is destroyed.
+ If \a mutex is \nullptr, QMutexLocker does nothing.
+
+ \sa QMutex::lock()
+*/
+
+/*!
\fn QMutexLocker::~QMutexLocker()
Destroys the QMutexLocker and unlocks the mutex that was locked
@@ -517,7 +595,7 @@ bool QBasicMutex::lockInternal(int timeout) QT_MUTEX_LOCK_NOEXCEPT
}
QMutexPrivate *d = static_cast<QMutexPrivate *>(copy);
- if (timeout == 0 && !d->possiblyUnlocked.load())
+ if (timeout == 0 && !d->possiblyUnlocked.loadRelaxed())
return false;
// At this point we have a pointer to a QMutexPrivate. But the other thread
@@ -541,7 +619,7 @@ bool QBasicMutex::lockInternal(int timeout) QT_MUTEX_LOCK_NOEXCEPT
// is set to the BigNumber magic value set in unlockInternal()
int old_waiters;
do {
- old_waiters = d->waiters.load();
+ old_waiters = d->waiters.loadRelaxed();
if (old_waiters == -QMutexPrivate::BigNumber) {
// we are unlocking, and the thread that unlocks is about to change d to 0
// we try to acquire the mutex by changing to dummyLocked()
@@ -550,7 +628,7 @@ bool QBasicMutex::lockInternal(int timeout) QT_MUTEX_LOCK_NOEXCEPT
d->deref();
return true;
} else {
- Q_ASSERT(d != d_ptr.load()); //else testAndSetAcquire should have succeeded
+ Q_ASSERT(d != d_ptr.loadRelaxed()); //else testAndSetAcquire should have succeeded
// Mutex is likely to bo 0, we should continue the outer-loop,
// set old_waiters to the magic value of BigNumber
old_waiters = QMutexPrivate::BigNumber;
@@ -563,7 +641,7 @@ bool QBasicMutex::lockInternal(int timeout) QT_MUTEX_LOCK_NOEXCEPT
// The mutex was unlocked before we incremented waiters.
if (old_waiters != QMutexPrivate::BigNumber) {
//we did not break the previous loop
- Q_ASSERT(d->waiters.load() >= 1);
+ Q_ASSERT(d->waiters.loadRelaxed() >= 1);
d->waiters.deref();
}
d->deref();
@@ -572,11 +650,11 @@ bool QBasicMutex::lockInternal(int timeout) QT_MUTEX_LOCK_NOEXCEPT
if (d->wait(timeout)) {
// reset the possiblyUnlocked flag if needed (and deref its corresponding reference)
- if (d->possiblyUnlocked.load() && d->possiblyUnlocked.testAndSetRelaxed(true, false))
+ if (d->possiblyUnlocked.loadRelaxed() && d->possiblyUnlocked.testAndSetRelaxed(true, false))
d->deref();
d->derefWaiters(1);
//we got the lock. (do not deref)
- Q_ASSERT(d == d_ptr.load());
+ Q_ASSERT(d == d_ptr.loadRelaxed());
return true;
} else {
Q_ASSERT(timeout >= 0);
@@ -593,14 +671,14 @@ bool QBasicMutex::lockInternal(int timeout) QT_MUTEX_LOCK_NOEXCEPT
return false;
}
}
- Q_ASSERT(d_ptr.load() != 0);
+ Q_ASSERT(d_ptr.loadRelaxed() != 0);
return true;
}
/*!
\internal
*/
-void QBasicMutex::unlockInternal() Q_DECL_NOTHROW
+void QBasicMutex::unlockInternal() noexcept
{
QMutexData *copy = d_ptr.loadAcquire();
Q_ASSERT(copy); //we must be locked
@@ -618,7 +696,7 @@ void QBasicMutex::unlockInternal() Q_DECL_NOTHROW
//there is no one waiting on this mutex anymore, set the mutex as unlocked (d = 0)
if (d_ptr.testAndSetRelease(d, 0)) {
// reset the possiblyUnlocked flag if needed (and deref its corresponding reference)
- if (d->possiblyUnlocked.load() && d->possiblyUnlocked.testAndSetRelaxed(true, false))
+ if (d->possiblyUnlocked.loadRelaxed() && d->possiblyUnlocked.testAndSetRelaxed(true, false))
d->deref();
}
d->derefWaiters(0);
@@ -657,30 +735,30 @@ QMutexPrivate *QMutexPrivate::allocate()
int i = freelist()->next();
QMutexPrivate *d = &(*freelist())[i];
d->id = i;
- Q_ASSERT(d->refCount.load() == 0);
+ Q_ASSERT(d->refCount.loadRelaxed() == 0);
Q_ASSERT(!d->recursive);
- Q_ASSERT(!d->possiblyUnlocked.load());
- Q_ASSERT(d->waiters.load() == 0);
- d->refCount.store(1);
+ Q_ASSERT(!d->possiblyUnlocked.loadRelaxed());
+ Q_ASSERT(d->waiters.loadRelaxed() == 0);
+ d->refCount.storeRelaxed(1);
return d;
}
void QMutexPrivate::release()
{
Q_ASSERT(!recursive);
- Q_ASSERT(refCount.load() == 0);
- Q_ASSERT(!possiblyUnlocked.load());
- Q_ASSERT(waiters.load() == 0);
+ Q_ASSERT(refCount.loadRelaxed() == 0);
+ Q_ASSERT(!possiblyUnlocked.loadRelaxed());
+ Q_ASSERT(waiters.loadRelaxed() == 0);
freelist()->release(id);
}
// atomically subtract "value" to the waiters, and remove the QMutexPrivate::BigNumber flag
-void QMutexPrivate::derefWaiters(int value) Q_DECL_NOTHROW
+void QMutexPrivate::derefWaiters(int value) noexcept
{
int old_waiters;
int new_waiters;
do {
- old_waiters = waiters.load();
+ old_waiters = waiters.loadRelaxed();
new_waiters = old_waiters;
if (new_waiters < 0) {
new_waiters += QMutexPrivate::BigNumber;
@@ -696,7 +774,7 @@ void QMutexPrivate::derefWaiters(int value) Q_DECL_NOTHROW
inline bool QRecursiveMutexPrivate::lock(int timeout) QT_MUTEX_LOCK_NOEXCEPT
{
Qt::HANDLE self = QThread::currentThreadId();
- if (owner.load() == self) {
+ if (owner.loadRelaxed() == self) {
++count;
Q_ASSERT_X(count != 0, "QMutex::lock", "Overflow in recursion counter");
return true;
@@ -709,19 +787,19 @@ inline bool QRecursiveMutexPrivate::lock(int timeout) QT_MUTEX_LOCK_NOEXCEPT
}
if (success)
- owner.store(self);
+ owner.storeRelaxed(self);
return success;
}
/*!
\internal
*/
-inline void QRecursiveMutexPrivate::unlock() Q_DECL_NOTHROW
+inline void QRecursiveMutexPrivate::unlock() noexcept
{
if (count > 0) {
count--;
} else {
- owner.store(0);
+ owner.storeRelaxed(0);
mutex.QBasicMutex::unlock();
}
}
diff --git a/src/corelib/thread/qmutex.h b/src/corelib/thread/qmutex.h
index 837355a602..c693ff65d8 100644
--- a/src/corelib/thread/qmutex.h
+++ b/src/corelib/thread/qmutex.h
@@ -57,11 +57,13 @@ QT_BEGIN_NAMESPACE
#if QT_CONFIG(thread) || defined(Q_CLANG_QDOC)
#ifdef Q_OS_LINUX
-# define QT_MUTEX_LOCK_NOEXCEPT Q_DECL_NOTHROW
+# define QT_MUTEX_LOCK_NOEXCEPT noexcept
#else
# define QT_MUTEX_LOCK_NOEXCEPT
#endif
+class QMutex;
+class QRecursiveMutex;
class QMutexData;
class Q_CORE_EXPORT QBasicMutex
@@ -80,39 +82,39 @@ public:
}
// BasicLockable concept
- inline void unlock() Q_DECL_NOTHROW {
- Q_ASSERT(d_ptr.load()); //mutex must be locked
+ inline void unlock() noexcept {
+ Q_ASSERT(d_ptr.loadRelaxed()); //mutex must be locked
if (!fastTryUnlock())
unlockInternal();
}
- bool tryLock() Q_DECL_NOTHROW {
+ bool tryLock() noexcept {
return fastTryLock();
}
// Lockable concept
- bool try_lock() Q_DECL_NOTHROW { return tryLock(); }
+ bool try_lock() noexcept { return tryLock(); }
- bool isRecursive() Q_DECL_NOTHROW; //### Qt6: remove me
- bool isRecursive() const Q_DECL_NOTHROW;
+ bool isRecursive() noexcept; //### Qt6: remove me
+ bool isRecursive() const noexcept;
private:
- inline bool fastTryLock() Q_DECL_NOTHROW {
+ inline bool fastTryLock() noexcept {
return d_ptr.testAndSetAcquire(nullptr, dummyLocked());
}
- inline bool fastTryUnlock() Q_DECL_NOTHROW {
+ inline bool fastTryUnlock() noexcept {
return d_ptr.testAndSetRelease(dummyLocked(), nullptr);
}
- inline bool fastTryLock(QMutexData *&current) Q_DECL_NOTHROW {
+ inline bool fastTryLock(QMutexData *&current) noexcept {
return d_ptr.testAndSetAcquire(nullptr, dummyLocked(), current);
}
- inline bool fastTryUnlock(QMutexData *&current) Q_DECL_NOTHROW {
+ inline bool fastTryUnlock(QMutexData *&current) noexcept {
return d_ptr.testAndSetRelease(dummyLocked(), nullptr, current);
}
void lockInternal() QT_MUTEX_LOCK_NOEXCEPT;
bool lockInternal(int timeout) QT_MUTEX_LOCK_NOEXCEPT;
- void unlockInternal() Q_DECL_NOTHROW;
+ void unlockInternal() noexcept;
QBasicAtomicPointer<QMutexData> d_ptr;
static inline QMutexData *dummyLocked() {
@@ -120,21 +122,27 @@ private:
}
friend class QMutex;
+ friend class QRecursiveMutex;
friend class QMutexData;
};
class Q_CORE_EXPORT QMutex : public QBasicMutex
{
public:
+#if defined(Q_COMPILER_CONSTEXPR)
+ constexpr QMutex() = default;
+#else
+ QMutex() { d_ptr.storeRelaxed(nullptr); }
+#endif
enum RecursionMode { NonRecursive, Recursive };
- explicit QMutex(RecursionMode mode = NonRecursive);
+ explicit QMutex(RecursionMode mode);
~QMutex();
// BasicLockable concept
void lock() QT_MUTEX_LOCK_NOEXCEPT;
bool tryLock(int timeout = 0) QT_MUTEX_LOCK_NOEXCEPT;
// BasicLockable concept
- void unlock() Q_DECL_NOTHROW;
+ void unlock() noexcept;
// Lockable concept
bool try_lock() QT_MUTEX_LOCK_NOEXCEPT { return tryLock(); }
@@ -158,12 +166,13 @@ public:
}
#endif
- bool isRecursive() const Q_DECL_NOTHROW
+ bool isRecursive() const noexcept
{ return QBasicMutex::isRecursive(); }
private:
Q_DISABLE_COPY(QMutex)
friend class QMutexLocker;
+ friend class QRecursiveMutex;
friend class ::tst_QMutex;
#if QT_HAS_INCLUDE(<chrono>)
@@ -192,6 +201,24 @@ private:
#endif
};
+class QRecursiveMutex : private QMutex
+{
+ // ### Qt 6: make it independent of QMutex
+ friend class QMutexLocker;
+public:
+ Q_CORE_EXPORT QRecursiveMutex();
+ Q_CORE_EXPORT ~QRecursiveMutex();
+
+ using QMutex::lock;
+ using QMutex::tryLock;
+ using QMutex::unlock;
+ using QMutex::try_lock;
+#if QT_HAS_INCLUDE(<chrono>)
+ using QMutex::try_lock_for;
+ using QMutex::try_lock_until;
+#endif
+};
+
class Q_CORE_EXPORT QMutexLocker
{
public:
@@ -207,12 +234,15 @@ public:
val |= 1;
}
}
+ explicit QMutexLocker(QRecursiveMutex *m) QT_MUTEX_LOCK_NOEXCEPT
+ : QMutexLocker{static_cast<QBasicMutex*>(m)} {}
#else
QMutexLocker(QMutex *) { }
+ QMutexLocker(QRecursiveMutex *) {}
#endif
inline ~QMutexLocker() { unlock(); }
- inline void unlock() Q_DECL_NOTHROW
+ inline void unlock() noexcept
{
if ((val & quintptr(1u)) == quintptr(1u)) {
val &= ~quintptr(1u);
@@ -257,24 +287,24 @@ class Q_CORE_EXPORT QMutex
public:
enum RecursionMode { NonRecursive, Recursive };
- inline Q_DECL_CONSTEXPR explicit QMutex(RecursionMode = NonRecursive) Q_DECL_NOTHROW { }
+ inline Q_DECL_CONSTEXPR explicit QMutex(RecursionMode = NonRecursive) noexcept { }
- inline void lock() Q_DECL_NOTHROW {}
- inline bool tryLock(int timeout = 0) Q_DECL_NOTHROW { Q_UNUSED(timeout); return true; }
- inline bool try_lock() Q_DECL_NOTHROW { return true; }
- inline void unlock() Q_DECL_NOTHROW {}
- inline bool isRecursive() const Q_DECL_NOTHROW { return true; }
+ inline void lock() noexcept {}
+ inline bool tryLock(int timeout = 0) noexcept { Q_UNUSED(timeout); return true; }
+ inline bool try_lock() noexcept { return true; }
+ inline void unlock() noexcept {}
+ inline bool isRecursive() const noexcept { return true; }
#if QT_HAS_INCLUDE(<chrono>)
template <class Rep, class Period>
- inline bool try_lock_for(std::chrono::duration<Rep, Period> duration) Q_DECL_NOTHROW
+ inline bool try_lock_for(std::chrono::duration<Rep, Period> duration) noexcept
{
Q_UNUSED(duration);
return true;
}
template<class Clock, class Duration>
- inline bool try_lock_until(std::chrono::time_point<Clock, Duration> timePoint) Q_DECL_NOTHROW
+ inline bool try_lock_until(std::chrono::time_point<Clock, Duration> timePoint) noexcept
{
Q_UNUSED(timePoint);
return true;
@@ -285,15 +315,17 @@ private:
Q_DISABLE_COPY(QMutex)
};
+class QRecursiveMutex : public QMutex {};
+
class Q_CORE_EXPORT QMutexLocker
{
public:
- inline explicit QMutexLocker(QMutex *) Q_DECL_NOTHROW {}
- inline ~QMutexLocker() Q_DECL_NOTHROW {}
+ inline explicit QMutexLocker(QMutex *) noexcept {}
+ inline ~QMutexLocker() noexcept {}
- inline void unlock() Q_DECL_NOTHROW {}
- void relock() Q_DECL_NOTHROW {}
- inline QMutex *mutex() const Q_DECL_NOTHROW { return nullptr; }
+ inline void unlock() noexcept {}
+ void relock() noexcept {}
+ inline QMutex *mutex() const noexcept { return nullptr; }
private:
Q_DISABLE_COPY(QMutexLocker)
diff --git a/src/corelib/thread/qmutex_linux.cpp b/src/corelib/thread/qmutex_linux.cpp
index 507e72cb76..3270875471 100644
--- a/src/corelib/thread/qmutex_linux.cpp
+++ b/src/corelib/thread/qmutex_linux.cpp
@@ -106,7 +106,7 @@ static inline QMutexData *dummyFutexValue()
}
template <bool IsTimed> static inline
-bool lockInternal_helper(QBasicAtomicPointer<QMutexData> &d_ptr, int timeout = -1, QElapsedTimer *elapsedTimer = 0) Q_DECL_NOTHROW
+bool lockInternal_helper(QBasicAtomicPointer<QMutexData> &d_ptr, int timeout = -1, QElapsedTimer *elapsedTimer = 0) noexcept
{
if (!IsTimed)
timeout = -1;
@@ -149,17 +149,17 @@ bool lockInternal_helper(QBasicAtomicPointer<QMutexData> &d_ptr, int timeout = -
}
}
- Q_ASSERT(d_ptr.load());
+ Q_ASSERT(d_ptr.loadRelaxed());
return true;
}
-void QBasicMutex::lockInternal() Q_DECL_NOTHROW
+void QBasicMutex::lockInternal() noexcept
{
Q_ASSERT(!isRecursive());
lockInternal_helper<false>(d_ptr);
}
-bool QBasicMutex::lockInternal(int timeout) Q_DECL_NOTHROW
+bool QBasicMutex::lockInternal(int timeout) noexcept
{
Q_ASSERT(!isRecursive());
QElapsedTimer elapsedTimer;
@@ -167,9 +167,9 @@ bool QBasicMutex::lockInternal(int timeout) Q_DECL_NOTHROW
return lockInternal_helper<true>(d_ptr, timeout, &elapsedTimer);
}
-void QBasicMutex::unlockInternal() Q_DECL_NOTHROW
+void QBasicMutex::unlockInternal() noexcept
{
- QMutexData *d = d_ptr.load();
+ QMutexData *d = d_ptr.loadRelaxed();
Q_ASSERT(d); //we must be locked
Q_ASSERT(d != dummyLocked()); // testAndSetRelease(dummyLocked(), 0) failed
Q_UNUSED(d);
diff --git a/src/corelib/thread/qmutex_mac.cpp b/src/corelib/thread/qmutex_mac.cpp
index 9a8d9bc750..923f89f697 100644
--- a/src/corelib/thread/qmutex_mac.cpp
+++ b/src/corelib/thread/qmutex_mac.cpp
@@ -79,7 +79,7 @@ bool QMutexPrivate::wait(int timeout)
return (r == KERN_SUCCESS);
}
-void QMutexPrivate::wakeUp() Q_DECL_NOTHROW
+void QMutexPrivate::wakeUp() noexcept
{
semaphore_signal(mach_semaphore);
}
diff --git a/src/corelib/thread/qmutex_p.h b/src/corelib/thread/qmutex_p.h
index ec9bfc1152..048d8707c4 100644
--- a/src/corelib/thread/qmutex_p.h
+++ b/src/corelib/thread/qmutex_p.h
@@ -92,28 +92,28 @@ public:
QMutexPrivate();
bool wait(int timeout = -1);
- void wakeUp() Q_DECL_NOTHROW;
+ void wakeUp() noexcept;
// Control the lifetime of the privates
QAtomicInt refCount;
int id;
bool ref() {
- Q_ASSERT(refCount.load() >= 0);
+ Q_ASSERT(refCount.loadRelaxed() >= 0);
int c;
do {
- c = refCount.load();
+ c = refCount.loadRelaxed();
if (c == 0)
return false;
} while (!refCount.testAndSetRelaxed(c, c + 1));
- Q_ASSERT(refCount.load() >= 0);
+ Q_ASSERT(refCount.loadRelaxed() >= 0);
return true;
}
void deref() {
- Q_ASSERT(refCount.load() >= 0);
+ Q_ASSERT(refCount.loadRelaxed() >= 0);
if (!refCount.deref())
release();
- Q_ASSERT(refCount.load() >= 0);
+ Q_ASSERT(refCount.loadRelaxed() >= 0);
}
void release();
static QMutexPrivate *allocate();
@@ -125,7 +125,7 @@ public:
when the mutex is unlocked.
*/
enum { BigNumber = 0x100000 }; //Must be bigger than the possible number of waiters (number of threads)
- void derefWaiters(int value) Q_DECL_NOTHROW;
+ void derefWaiters(int value) noexcept;
//platform specific stuff
#if defined(Q_OS_MAC)
diff --git a/src/corelib/thread/qmutex_unix.cpp b/src/corelib/thread/qmutex_unix.cpp
index 3ee24a292c..df2f606a23 100644
--- a/src/corelib/thread/qmutex_unix.cpp
+++ b/src/corelib/thread/qmutex_unix.cpp
@@ -58,7 +58,7 @@ QT_BEGIN_NAMESPACE
static void report_error(int code, const char *where, const char *what)
{
if (code != 0)
- qWarning("%s: %s failure: %s", where, what, qPrintable(qt_error_string(code)));
+ qErrnoWarning(code, "%s: %s failure", where, what);
}
#ifdef QT_UNIX_SEMAPHORE
@@ -99,7 +99,7 @@ bool QMutexPrivate::wait(int timeout)
return true;
}
-void QMutexPrivate::wakeUp() Q_DECL_NOTHROW
+void QMutexPrivate::wakeUp() noexcept
{
report_error(sem_post(&semaphore), "QMutex::unlock", "sem_post");
}
@@ -146,7 +146,7 @@ bool QMutexPrivate::wait(int timeout)
return ret;
}
-void QMutexPrivate::wakeUp() Q_DECL_NOTHROW
+void QMutexPrivate::wakeUp() noexcept
{
report_error(pthread_mutex_lock(&mutex), "QMutex::unlock", "mutex lock");
wakeup = true;
diff --git a/src/corelib/thread/qmutex_win.cpp b/src/corelib/thread/qmutex_win.cpp
index 3c314a4c0c..e221bc89cb 100644
--- a/src/corelib/thread/qmutex_win.cpp
+++ b/src/corelib/thread/qmutex_win.cpp
@@ -64,7 +64,7 @@ bool QMutexPrivate::wait(int timeout)
return (WaitForSingleObjectEx(event, timeout < 0 ? INFINITE : timeout, FALSE) == WAIT_OBJECT_0);
}
-void QMutexPrivate::wakeUp() Q_DECL_NOTHROW
+void QMutexPrivate::wakeUp() noexcept
{ SetEvent(event); }
QT_END_NAMESPACE
diff --git a/src/corelib/thread/qmutexpool.cpp b/src/corelib/thread/qmutexpool.cpp
deleted file mode 100644
index bb063b8ab6..0000000000
--- a/src/corelib/thread/qmutexpool.cpp
+++ /dev/null
@@ -1,151 +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 "qatomic.h"
-#include "qmutexpool_p.h"
-
-QT_BEGIN_NAMESPACE
-
-Q_GLOBAL_STATIC_WITH_ARGS(QMutexPool, globalMutexPool, (QMutex::Recursive))
-
-/*!
- \class QMutexPool
- \inmodule QtCore
- \brief The QMutexPool class provides a pool of QMutex objects.
-
- \internal
-
- \ingroup thread
-
- QMutexPool is a convenience class that provides access to a fixed
- number of QMutex objects.
-
- Typical use of a QMutexPool is in situations where it is not
- possible or feasible to use one QMutex for every protected object.
- The mutex pool will return a mutex based on the address of the
- object that needs protection.
-
- For example, consider this simple class:
-
- \snippet code/src_corelib_thread_qmutexpool.cpp 0
-
- Adding a QMutex member to the Number class does not make sense,
- because it is so small. However, in order to ensure that access to
- each Number is protected, you need to use a mutex. In this case, a
- QMutexPool would be ideal.
-
- Code to calculate the square of a number would then look something
- like this:
-
- \snippet code/src_corelib_thread_qmutexpool.cpp 1
-
- This function will safely calculate the square of a number, since
- it uses a mutex from a QMutexPool. The mutex is locked and
- unlocked automatically by the QMutexLocker class. See the
- QMutexLocker documentation for more details.
-*/
-
-/*!
- Constructs a QMutexPool, reserving space for \a size QMutexes. All
- mutexes in the pool are created with \a recursionMode. By default,
- all mutexes are non-recursive.
-
- The QMutexes are created when needed, and deleted when the
- QMutexPool is destructed.
-*/
-QMutexPool::QMutexPool(QMutex::RecursionMode recursionMode, int size)
- : mutexes(size), recursionMode(recursionMode)
-{
- for (int index = 0; index < mutexes.count(); ++index) {
- mutexes[index].store(0);
- }
-}
-
-/*!
- Destructs a QMutexPool. All QMutexes that were created by the pool
- are deleted.
-*/
-QMutexPool::~QMutexPool()
-{
- for (int index = 0; index < mutexes.count(); ++index)
- delete mutexes[index].loadAcquire();
-}
-
-/*!
- Returns the global QMutexPool instance.
-*/
-QMutexPool *QMutexPool::instance()
-{
- return globalMutexPool();
-}
-
-/*!
- \fn QMutexPool::get(const void *address)
- Returns a QMutex from the pool. QMutexPool uses the value \a address
- to determine which mutex is returned from the pool.
-*/
-
-/*!
- \internal
- create the mutex for the given index
- */
-QMutex *QMutexPool::createMutex(int index)
-{
- // mutex not created, create one
- QMutex *newMutex = new QMutex(recursionMode);
- if (!mutexes[index].testAndSetRelease(nullptr, newMutex)) {
- delete newMutex;
- return mutexes[index].loadAcquire();
- } else {
- return newMutex;
- }
-}
-
-/*!
- Returns a QMutex from the global mutex pool.
-*/
-QMutex *QMutexPool::globalInstanceGet(const void *address)
-{
- QMutexPool * const globalInstance = globalMutexPool();
- if (globalInstance == 0)
- return 0;
- return globalInstance->get(address);
-}
-
-QT_END_NAMESPACE
diff --git a/src/corelib/thread/qmutexpool_p.h b/src/corelib/thread/qmutexpool_p.h
deleted file mode 100644
index 00710199b8..0000000000
--- a/src/corelib/thread/qmutexpool_p.h
+++ /dev/null
@@ -1,88 +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$
-**
-****************************************************************************/
-
-#ifndef QMUTEXPOOL_P_H
-#define QMUTEXPOOL_P_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/private/qglobal_p.h>
-#include "QtCore/qatomic.h"
-#include "QtCore/qmutex.h"
-#include "QtCore/qvarlengtharray.h"
-
-QT_REQUIRE_CONFIG(thread);
-
-QT_BEGIN_NAMESPACE
-
-class Q_CORE_EXPORT QMutexPool
-{
-public:
- explicit QMutexPool(QMutex::RecursionMode recursionMode = QMutex::NonRecursive, int size = 131);
- ~QMutexPool();
-
- inline QMutex *get(const void *address) {
- int index = uint(quintptr(address)) % mutexes.count();
- QMutex *m = mutexes[index].loadAcquire();
- if (m)
- return m;
- else
- return createMutex(index);
- }
- static QMutexPool *instance();
- static QMutex *globalInstanceGet(const void *address);
-
-private:
- QMutex *createMutex(int index);
- QVarLengthArray<QAtomicPointer<QMutex>, 131> mutexes;
- QMutex::RecursionMode recursionMode;
-};
-
-QT_END_NAMESPACE
-
-#endif // QMUTEXPOOL_P_H
diff --git a/src/corelib/thread/qorderedmutexlocker_p.h b/src/corelib/thread/qorderedmutexlocker_p.h
index ded102d32d..570c526225 100644
--- a/src/corelib/thread/qorderedmutexlocker_p.h
+++ b/src/corelib/thread/qorderedmutexlocker_p.h
@@ -58,6 +58,8 @@
QT_BEGIN_NAMESPACE
+#if QT_CONFIG(thread)
+
/*
Locks 2 mutexes in a defined order, avoiding a recursive lock if
we're trying to lock the same mutex twice.
@@ -65,9 +67,9 @@ QT_BEGIN_NAMESPACE
class QOrderedMutexLocker
{
public:
- QOrderedMutexLocker(QMutex *m1, QMutex *m2)
- : mtx1((m1 == m2) ? m1 : (std::less<QMutex *>()(m1, m2) ? m1 : m2)),
- mtx2((m1 == m2) ? 0 : (std::less<QMutex *>()(m1, m2) ? m2 : m1)),
+ QOrderedMutexLocker(QBasicMutex *m1, QBasicMutex *m2)
+ : mtx1((m1 == m2) ? m1 : (std::less<QBasicMutex *>()(m1, m2) ? m1 : m2)),
+ mtx2((m1 == m2) ? 0 : (std::less<QBasicMutex *>()(m1, m2) ? m2 : m1)),
locked(false)
{
relock();
@@ -95,12 +97,12 @@ public:
}
}
- static bool relock(QMutex *mtx1, QMutex *mtx2)
+ static bool relock(QBasicMutex *mtx1, QBasicMutex *mtx2)
{
// mtx1 is already locked, mtx2 not... do we need to unlock and relock?
if (mtx1 == mtx2)
return false;
- if (std::less<QMutex *>()(mtx1, mtx2)) {
+ if (std::less<QBasicMutex *>()(mtx1, mtx2)) {
mtx2->lock();
return true;
}
@@ -113,10 +115,58 @@ public:
}
private:
- QMutex *mtx1, *mtx2;
+ QBasicMutex *mtx1, *mtx2;
bool locked;
};
+class QBasicMutexLocker
+{
+public:
+ inline explicit QBasicMutexLocker(QBasicMutex *m) QT_MUTEX_LOCK_NOEXCEPT
+ : m(m), isLocked(true)
+ {
+ m->lock();
+ }
+ inline ~QBasicMutexLocker() { if (isLocked) unlock(); }
+
+ inline void unlock() noexcept
+ {
+ isLocked = false;
+ m->unlock();
+ }
+
+ inline void relock() QT_MUTEX_LOCK_NOEXCEPT
+ {
+ isLocked = true;
+ m->lock();
+ }
+
+private:
+ Q_DISABLE_COPY(QBasicMutexLocker)
+
+ QBasicMutex *m;
+ bool isLocked;
+};
+
+#else
+
+class QOrderedMutexLocker
+{
+public:
+ QOrderedMutexLocker(QBasicMutex *, QBasicMutex *) {}
+ ~QOrderedMutexLocker() {}
+
+ void relock() {}
+ void unlock() {}
+
+ static bool relock(QBasicMutex *, QBasicMutex *) { return false; }
+};
+
+using QBasicMutexLocker = QMutexLocker;
+
+#endif
+
+
QT_END_NAMESPACE
#endif
diff --git a/src/corelib/thread/qreadwritelock.cpp b/src/corelib/thread/qreadwritelock.cpp
index d7cf7a7284..14654986a0 100644
--- a/src/corelib/thread/qreadwritelock.cpp
+++ b/src/corelib/thread/qreadwritelock.cpp
@@ -48,6 +48,7 @@
#include "qreadwritelock_p.h"
#include "qelapsedtimer.h"
#include "private/qfreelist_p.h"
+#include "private/qlocking_p.h"
QT_BEGIN_NAMESPACE
@@ -143,7 +144,7 @@ inline bool isUncontendedLocked(const QReadWriteLockPrivate *d)
QReadWriteLock::QReadWriteLock(RecursionMode recursionMode)
: d_ptr(recursionMode == Recursive ? new QReadWriteLockPrivate(true) : nullptr)
{
- Q_ASSERT_X(!(quintptr(d_ptr.load()) & StateMask), "QReadWriteLock::QReadWriteLock", "bad d_ptr alignment");
+ Q_ASSERT_X(!(quintptr(d_ptr.loadRelaxed()) & StateMask), "QReadWriteLock::QReadWriteLock", "bad d_ptr alignment");
}
/*!
@@ -154,7 +155,7 @@ QReadWriteLock::QReadWriteLock(RecursionMode recursionMode)
*/
QReadWriteLock::~QReadWriteLock()
{
- auto d = d_ptr.load();
+ auto d = d_ptr.loadRelaxed();
if (isUncontendedLocked(d)) {
qWarning("QReadWriteLock: destroying locked QReadWriteLock");
return;
@@ -262,8 +263,8 @@ bool QReadWriteLock::tryLockForRead(int timeout)
if (d->recursive)
return d->recursiveLockForRead(timeout);
- QMutexLocker lock(&d->mutex);
- if (d != d_ptr.load()) {
+ auto lock = qt_unique_lock(d->mutex);
+ if (d != d_ptr.loadRelaxed()) {
// d_ptr has changed: this QReadWriteLock was unlocked before we had
// time to lock d->mutex.
// We are holding a lock to a mutex within a QReadWriteLockPrivate
@@ -369,8 +370,8 @@ bool QReadWriteLock::tryLockForWrite(int timeout)
if (d->recursive)
return d->recursiveLockForWrite(timeout);
- QMutexLocker lock(&d->mutex);
- if (d != d_ptr.load()) {
+ auto lock = qt_unique_lock(d->mutex);
+ if (d != d_ptr.loadRelaxed()) {
// The mutex was unlocked before we had time to lock the mutex.
// We are holding to a mutex within a QReadWriteLockPrivate that is already released
// (or even is already re-used) but that's ok because the QFreeList never frees them.
@@ -418,7 +419,7 @@ void QReadWriteLock::unlock()
return;
}
- QMutexLocker locker(&d->mutex);
+ const auto lock = qt_scoped_lock(d->mutex);
if (d->writerCount) {
Q_ASSERT(d->writerCount == 1);
Q_ASSERT(d->readerCount == 0);
@@ -433,7 +434,7 @@ void QReadWriteLock::unlock()
if (d->waitingReaders || d->waitingWriters) {
d->unlock();
} else {
- Q_ASSERT(d_ptr.load() == d); // should not change when we still hold the mutex
+ Q_ASSERT(d_ptr.loadRelaxed() == d); // should not change when we still hold the mutex
d_ptr.storeRelease(nullptr);
d->release();
}
@@ -444,7 +445,7 @@ void QReadWriteLock::unlock()
/*! \internal Helper for QWaitCondition::wait */
QReadWriteLock::StateForWaitCondition QReadWriteLock::stateForWaitCondition() const
{
- QReadWriteLockPrivate *d = d_ptr.load();
+ QReadWriteLockPrivate *d = d_ptr.loadRelaxed();
switch (quintptr(d) & StateMask) {
case StateLockedForRead: return LockedForRead;
case StateLockedForWrite: return LockedForWrite;
@@ -536,7 +537,7 @@ void QReadWriteLockPrivate::unlock()
bool QReadWriteLockPrivate::recursiveLockForRead(int timeout)
{
Q_ASSERT(recursive);
- QMutexLocker lock(&mutex);
+ auto lock = qt_unique_lock(mutex);
Qt::HANDLE self = QThread::currentThreadId();
@@ -556,7 +557,7 @@ bool QReadWriteLockPrivate::recursiveLockForRead(int timeout)
bool QReadWriteLockPrivate::recursiveLockForWrite(int timeout)
{
Q_ASSERT(recursive);
- QMutexLocker lock(&mutex);
+ auto lock = qt_unique_lock(mutex);
Qt::HANDLE self = QThread::currentThreadId();
if (currentWriter == self) {
@@ -574,7 +575,7 @@ bool QReadWriteLockPrivate::recursiveLockForWrite(int timeout)
void QReadWriteLockPrivate::recursiveUnlock()
{
Q_ASSERT(recursive);
- QMutexLocker lock(&mutex);
+ auto lock = qt_unique_lock(mutex);
Qt::HANDLE self = QThread::currentThreadId();
if (self == currentWriter) {
diff --git a/src/corelib/thread/qreadwritelock.h b/src/corelib/thread/qreadwritelock.h
index 65fa76fd6d..3c1ed91b94 100644
--- a/src/corelib/thread/qreadwritelock.h
+++ b/src/corelib/thread/qreadwritelock.h
@@ -180,18 +180,18 @@ class Q_CORE_EXPORT QReadWriteLock
{
public:
enum RecursionMode { NonRecursive, Recursive };
- inline explicit QReadWriteLock(RecursionMode = NonRecursive) Q_DECL_NOTHROW { }
+ inline explicit QReadWriteLock(RecursionMode = NonRecursive) noexcept { }
inline ~QReadWriteLock() { }
- static inline void lockForRead() Q_DECL_NOTHROW { }
- static inline bool tryLockForRead() Q_DECL_NOTHROW { return true; }
- static inline bool tryLockForRead(int timeout) Q_DECL_NOTHROW { Q_UNUSED(timeout); return true; }
+ void lockForRead() noexcept { }
+ bool tryLockForRead() noexcept { return true; }
+ bool tryLockForRead(int timeout) noexcept { Q_UNUSED(timeout); return true; }
- static inline void lockForWrite() Q_DECL_NOTHROW { }
- static inline bool tryLockForWrite() Q_DECL_NOTHROW { return true; }
- static inline bool tryLockForWrite(int timeout) Q_DECL_NOTHROW { Q_UNUSED(timeout); return true; }
+ void lockForWrite() noexcept { }
+ bool tryLockForWrite() noexcept { return true; }
+ bool tryLockForWrite(int timeout) noexcept { Q_UNUSED(timeout); return true; }
- static inline void unlock() Q_DECL_NOTHROW { }
+ void unlock() noexcept { }
private:
Q_DISABLE_COPY(QReadWriteLock)
@@ -200,12 +200,12 @@ private:
class Q_CORE_EXPORT QReadLocker
{
public:
- inline QReadLocker(QReadWriteLock *) Q_DECL_NOTHROW { }
- inline ~QReadLocker() Q_DECL_NOTHROW { }
+ inline explicit QReadLocker(QReadWriteLock *) noexcept { }
+ inline ~QReadLocker() noexcept { }
- static inline void unlock() Q_DECL_NOTHROW { }
- static inline void relock() Q_DECL_NOTHROW { }
- static inline QReadWriteLock *readWriteLock() Q_DECL_NOTHROW { return nullptr; }
+ void unlock() noexcept { }
+ void relock() noexcept { }
+ QReadWriteLock *readWriteLock() noexcept { return nullptr; }
private:
Q_DISABLE_COPY(QReadLocker)
@@ -214,12 +214,12 @@ private:
class Q_CORE_EXPORT QWriteLocker
{
public:
- inline explicit QWriteLocker(QReadWriteLock *) Q_DECL_NOTHROW { }
- inline ~QWriteLocker() Q_DECL_NOTHROW { }
+ inline explicit QWriteLocker(QReadWriteLock *) noexcept { }
+ inline ~QWriteLocker() noexcept { }
- static inline void unlock() Q_DECL_NOTHROW { }
- static inline void relock() Q_DECL_NOTHROW { }
- static inline QReadWriteLock *readWriteLock() Q_DECL_NOTHROW { return nullptr; }
+ void unlock() noexcept { }
+ void relock() noexcept { }
+ QReadWriteLock *readWriteLock() noexcept { return nullptr; }
private:
Q_DISABLE_COPY(QWriteLocker)
diff --git a/src/corelib/thread/qreadwritelock_p.h b/src/corelib/thread/qreadwritelock_p.h
index 31da2401c0..a4d002b7f2 100644
--- a/src/corelib/thread/qreadwritelock_p.h
+++ b/src/corelib/thread/qreadwritelock_p.h
@@ -63,17 +63,16 @@ QT_BEGIN_NAMESPACE
class QReadWriteLockPrivate
{
public:
- QReadWriteLockPrivate(bool isRecursive = false)
- : readerCount(0), writerCount(0), waitingReaders(0), waitingWriters(0),
- recursive(isRecursive), id(0), currentWriter(nullptr) {}
+ explicit QReadWriteLockPrivate(bool isRecursive = false)
+ : recursive(isRecursive) {}
QMutex mutex;
QWaitCondition writerCond;
QWaitCondition readerCond;
- int readerCount;
- int writerCount;
- int waitingReaders;
- int waitingWriters;
+ int readerCount = 0;
+ int writerCount = 0;
+ int waitingReaders = 0;
+ int waitingWriters = 0;
const bool recursive;
//Called with the mutex locked
@@ -82,19 +81,18 @@ public:
void unlock();
//memory management
- int id;
+ int id = 0;
void release();
static QReadWriteLockPrivate *allocate();
// Recusive mutex handling
- Qt::HANDLE currentWriter;
+ Qt::HANDLE currentWriter = {};
QHash<Qt::HANDLE, int> currentReaders;
// called with the mutex unlocked
bool recursiveLockForWrite(int timeout);
bool recursiveLockForRead(int timeout);
void recursiveUnlock();
-
};
QT_END_NAMESPACE
diff --git a/src/corelib/thread/qresultstore.h b/src/corelib/thread/qresultstore.h
index 1f29e8d187..7a65089396 100644
--- a/src/corelib/thread/qresultstore.h
+++ b/src/corelib/thread/qresultstore.h
@@ -142,7 +142,7 @@ public:
template <typename T>
int addResult(int index, const T *result)
{
- if (result == 0)
+ if (result == nullptr)
return addResult(index, static_cast<void *>(nullptr));
else
return addResult(index, static_cast<void *>(new T(*result)));
@@ -158,7 +158,7 @@ public:
int addResults(int index, const QVector<T> *results, int totalCount)
{
if (m_filterMode == true && results->count() != totalCount && 0 == results->count())
- return addResults(index, 0, 0, totalCount);
+ return addResults(index, nullptr, 0, totalCount);
else
return addResults(index, new QVector<T>(*results), results->count(), totalCount);
}
diff --git a/src/corelib/thread/qsemaphore.cpp b/src/corelib/thread/qsemaphore.cpp
index 2e0b6f2bc0..d4fb756b94 100644
--- a/src/corelib/thread/qsemaphore.cpp
+++ b/src/corelib/thread/qsemaphore.cpp
@@ -264,7 +264,7 @@ template <bool IsTimed> bool futexSemaphoreTryAcquire(QBasicAtomicInteger<quintp
if (futexHasWaiterCount) {
// decrement the number of threads waiting
- Q_ASSERT(futexHigh32(&u)->load() & 0x7fffffffU);
+ Q_ASSERT(futexHigh32(&u)->loadRelaxed() & 0x7fffffffU);
u.fetchAndSubRelaxed(oneWaiter);
}
return false;
@@ -293,7 +293,7 @@ QSemaphore::QSemaphore(int n)
quintptr nn = unsigned(n);
if (futexHasWaiterCount)
nn |= quint64(nn) << 32; // token count replicated in high word
- u.store(nn);
+ u.storeRelaxed(nn);
} else {
d = new QSemaphorePrivate(n);
}
@@ -425,7 +425,7 @@ void QSemaphore::release(int n)
int QSemaphore::available() const
{
if (futexAvailable())
- return futexAvailCounter(u.load());
+ return futexAvailCounter(u.loadRelaxed());
QMutexLocker locker(&d->mutex);
return d->avail;
diff --git a/src/corelib/thread/qsemaphore.h b/src/corelib/thread/qsemaphore.h
index b830ff1bfd..58c12997ad 100644
--- a/src/corelib/thread/qsemaphore.h
+++ b/src/corelib/thread/qsemaphore.h
@@ -75,14 +75,14 @@ class QSemaphoreReleaser
{
public:
QSemaphoreReleaser() = default;
- explicit QSemaphoreReleaser(QSemaphore &sem, int n = 1) Q_DECL_NOTHROW
+ explicit QSemaphoreReleaser(QSemaphore &sem, int n = 1) noexcept
: m_sem(&sem), m_n(n) {}
- explicit QSemaphoreReleaser(QSemaphore *sem, int n = 1) Q_DECL_NOTHROW
+ explicit QSemaphoreReleaser(QSemaphore *sem, int n = 1) noexcept
: m_sem(sem), m_n(n) {}
- QSemaphoreReleaser(QSemaphoreReleaser &&other) Q_DECL_NOTHROW
+ QSemaphoreReleaser(QSemaphoreReleaser &&other) noexcept
: m_sem(other.m_sem), m_n(other.m_n)
{ other.m_sem = nullptr; }
- QSemaphoreReleaser &operator=(QSemaphoreReleaser &&other) Q_DECL_NOTHROW
+ QSemaphoreReleaser &operator=(QSemaphoreReleaser &&other) noexcept
{ QSemaphoreReleaser moved(std::move(other)); swap(moved); return *this; }
~QSemaphoreReleaser()
@@ -91,16 +91,16 @@ public:
m_sem->release(m_n);
}
- void swap(QSemaphoreReleaser &other) Q_DECL_NOTHROW
+ void swap(QSemaphoreReleaser &other) noexcept
{
qSwap(m_sem, other.m_sem);
qSwap(m_n, other.m_n);
}
- QSemaphore *semaphore() const Q_DECL_NOTHROW
+ QSemaphore *semaphore() const noexcept
{ return m_sem; }
- QSemaphore *cancel() Q_DECL_NOTHROW
+ QSemaphore *cancel() noexcept
{
QSemaphore *old = m_sem;
m_sem = nullptr;
diff --git a/src/corelib/thread/qthread.cpp b/src/corelib/thread/qthread.cpp
index 9f60de1f87..880ae9e046 100644
--- a/src/corelib/thread/qthread.cpp
+++ b/src/corelib/thread/qthread.cpp
@@ -65,7 +65,7 @@ QThreadData::QThreadData(int initialRefCount)
QThreadData::~QThreadData()
{
- Q_ASSERT(_ref.load() == 0);
+ Q_ASSERT(_ref.loadRelaxed() == 0);
// In the odd case that Qt is running on a secondary thread, the main
// thread instance will have been dereffed asunder because of the deref in
@@ -73,8 +73,8 @@ QThreadData::~QThreadData()
// crashing during QCoreApplicationData's global static cleanup we need to
// safeguard the main thread here.. This fix is a bit crude, but it solves
// the problem...
- if (this->thread == QCoreApplicationPrivate::theMainThread) {
- QCoreApplicationPrivate::theMainThread = 0;
+ if (this->thread.loadAcquire() == QCoreApplicationPrivate::theMainThread.loadAcquire()) {
+ QCoreApplicationPrivate::theMainThread.storeRelease(nullptr);
QThreadData::clearCurrentThreadData();
}
@@ -85,8 +85,8 @@ QThreadData::~QThreadData()
// because this destructor is still running (the _ref sub-object has not
// been destroyed) and there's no reentrancy. The refcount will become
// negative, but that's acceptable.
- QThread *t = thread;
- thread = 0;
+ QThread *t = thread.loadAcquire();
+ thread.storeRelease(nullptr);
delete t;
for (int i = 0; i < postEventList.size(); ++i) {
@@ -105,7 +105,7 @@ void QThreadData::ref()
{
#if QT_CONFIG(thread)
(void) _ref.ref();
- Q_ASSERT(_ref.load() != 0);
+ Q_ASSERT(_ref.loadRelaxed() != 0);
#endif
}
@@ -171,6 +171,11 @@ QThreadPrivate::QThreadPrivate(QThreadData *d)
// to 128K.
#ifdef Q_OS_INTEGRITY
stackSize = 128 * 1024;
+#elif defined(Q_OS_RTEMS)
+ static bool envStackSizeOk = false;
+ static const int envStackSize = qEnvironmentVariableIntValue("QT_DEFAULT_THREAD_STACK_SIZE", &envStackSizeOk);
+ if (envStackSizeOk)
+ stackSize = envStackSize;
#endif
#if defined (Q_OS_WIN)
@@ -393,7 +398,7 @@ QThread *QThread::currentThread()
{
QThreadData *data = QThreadData::current();
Q_ASSERT(data != 0);
- return data->thread;
+ return data->thread.loadAcquire();
}
/*!
@@ -839,17 +844,17 @@ bool QThread::event(QEvent* event)
return QObject::event(event);
}
-Qt::HANDLE QThread::currentThreadId() Q_DECL_NOTHROW
+Qt::HANDLE QThread::currentThreadId() noexcept
{
return Qt::HANDLE(currentThread());
}
QThread *QThread::currentThread()
{
- return QThreadData::current()->thread;
+ return QThreadData::current()->thread.loadAcquire();
}
-int QThread::idealThreadCount() Q_DECL_NOTHROW
+int QThread::idealThreadCount() noexcept
{
return 1;
}
@@ -878,11 +883,11 @@ QThreadData *QThreadData::current(bool createIfNecessary)
if (!data && createIfNecessary) {
data = new QThreadData;
data->thread = new QAdoptedThread(data);
- data->threadId.store(Qt::HANDLE(data->thread));
+ data->threadId.storeRelaxed(Qt::HANDLE(data->thread.loadAcquire()));
data->deref();
data->isAdopted = true;
- if (!QCoreApplicationPrivate::theMainThread)
- QCoreApplicationPrivate::theMainThread = data->thread.load();
+ if (!QCoreApplicationPrivate::theMainThread.loadAcquire())
+ QCoreApplicationPrivate::theMainThread.storeRelease(data->thread.loadRelaxed());
}
return data;
}
@@ -914,6 +919,16 @@ QThreadPrivate::~QThreadPrivate()
delete data;
}
+void QThread::setStackSize(uint stackSize)
+{
+ Q_UNUSED(stackSize);
+}
+
+uint QThread::stackSize() const
+{
+ return 0;
+}
+
#endif // QT_CONFIG(thread)
/*!
@@ -925,7 +940,7 @@ QThreadPrivate::~QThreadPrivate()
QAbstractEventDispatcher *QThread::eventDispatcher() const
{
Q_D(const QThread);
- return d->data->eventDispatcher.load();
+ return d->data->eventDispatcher.loadRelaxed();
}
/*!
@@ -980,7 +995,7 @@ bool QThread::event(QEvent *event)
void QThread::requestInterruption()
{
- if (this == QCoreApplicationPrivate::theMainThread) {
+ if (this == QCoreApplicationPrivate::theMainThread.loadAcquire()) {
qWarning("QThread::requestInterruption has no effect on the main thread");
return;
}
diff --git a/src/corelib/thread/qthread.h b/src/corelib/thread/qthread.h
index b6c5bf47d0..c7a6dc8f1a 100644
--- a/src/corelib/thread/qthread.h
+++ b/src/corelib/thread/qthread.h
@@ -70,9 +70,9 @@ class Q_CORE_EXPORT QThread : public QObject
{
Q_OBJECT
public:
- static Qt::HANDLE currentThreadId() Q_DECL_NOTHROW Q_DECL_PURE_FUNCTION;
+ static Qt::HANDLE currentThreadId() noexcept Q_DECL_PURE_FUNCTION;
static QThread *currentThread();
- static int idealThreadCount() Q_DECL_NOTHROW;
+ static int idealThreadCount() noexcept;
static void yieldCurrentThread();
explicit QThread(QObject *parent = nullptr);
@@ -209,7 +209,6 @@ struct Callable
{
}
-#if defined(Q_COMPILER_DEFAULT_MEMBERS) && defined(Q_COMPILER_DELETE_MEMBERS)
// Apply the same semantics of a lambda closure type w.r.t. the special
// member functions, if possible: delete the copy assignment operator,
// bring back all the others as per the RO5 (cf. ยง8.1.5.1/11 [expr.prim.lambda.closure])
@@ -218,7 +217,6 @@ struct Callable
Callable(Callable &&) = default;
Callable &operator=(const Callable &) = delete;
Callable &operator=(Callable &&) = default;
-#endif
void operator()()
{
diff --git a/src/corelib/thread/qthread_p.h b/src/corelib/thread/qthread_p.h
index 57e6c995c5..b2d1628e6e 100644
--- a/src/corelib/thread/qthread_p.h
+++ b/src/corelib/thread/qthread_p.h
@@ -89,7 +89,7 @@ public:
QEvent *event;
int priority;
inline QPostEvent()
- : receiver(0), event(0), priority(0)
+ : receiver(nullptr), event(nullptr), priority(0)
{ }
inline QPostEvent(QObject *r, QEvent *e, int p)
: receiver(r), event(e), priority(p)
@@ -148,7 +148,7 @@ private:
class Q_CORE_EXPORT QDaemonThread : public QThread
{
public:
- QDaemonThread(QObject *parent = 0);
+ QDaemonThread(QObject *parent = nullptr);
~QDaemonThread();
};
@@ -157,7 +157,7 @@ class QThreadPrivate : public QObjectPrivate
Q_DECLARE_PUBLIC(QThread)
public:
- QThreadPrivate(QThreadData *d = 0);
+ QThreadPrivate(QThreadData *d = nullptr);
~QThreadPrivate();
void setPriority(QThread::Priority prio);
@@ -187,8 +187,8 @@ public:
#endif // Q_OS_UNIX
#ifdef Q_OS_WIN
- static unsigned int __stdcall start(void *) Q_DECL_NOEXCEPT;
- static void finish(void *, bool lockAnyway=true) Q_DECL_NOEXCEPT;
+ static unsigned int __stdcall start(void *) noexcept;
+ static void finish(void *, bool lockAnyway=true) noexcept;
Qt::HANDLE handle;
unsigned int id;
@@ -251,17 +251,17 @@ public:
#endif
static void clearCurrentThreadData();
static QThreadData *get2(QThread *thread)
- { Q_ASSERT_X(thread != 0, "QThread", "internal error"); return thread->d_func()->data; }
+ { Q_ASSERT_X(thread != nullptr, "QThread", "internal error"); return thread->d_func()->data; }
void ref();
void deref();
inline bool hasEventDispatcher() const
- { return eventDispatcher.load() != nullptr; }
+ { return eventDispatcher.loadRelaxed() != nullptr; }
QAbstractEventDispatcher *createEventDispatcher();
QAbstractEventDispatcher *ensureEventDispatcher()
{
- QAbstractEventDispatcher *ed = eventDispatcher.load();
+ QAbstractEventDispatcher *ed = eventDispatcher.loadRelaxed();
if (Q_LIKELY(ed))
return ed;
return createEventDispatcher();
@@ -284,7 +284,7 @@ public:
public:
FlaggedDebugSignatures() : idx(0)
- { std::fill_n(locations, Count, static_cast<char*>(0)); }
+ { std::fill_n(locations, Count, static_cast<char*>(nullptr)); }
void store(const char* method)
{ locations[idx++ % Count] = method; }
@@ -331,7 +331,7 @@ class QAdoptedThread : public QThread
Q_DECLARE_PRIVATE(QThread)
public:
- QAdoptedThread(QThreadData *data = 0);
+ QAdoptedThread(QThreadData *data = nullptr);
~QAdoptedThread();
void init();
diff --git a/src/corelib/thread/qthread_unix.cpp b/src/corelib/thread/qthread_unix.cpp
index 710528ea41..cb3c0d6bb1 100644
--- a/src/corelib/thread/qthread_unix.cpp
+++ b/src/corelib/thread/qthread_unix.cpp
@@ -108,17 +108,8 @@ Q_STATIC_ASSERT(sizeof(pthread_t) <= sizeof(Qt::HANDLE));
enum { ThreadPriorityResetFlag = 0x80000000 };
-#if defined(Q_OS_LINUX) && defined(__GLIBC__) && (defined(Q_CC_GNU) || defined(Q_CC_INTEL)) && !defined(QT_LINUXBASE)
-/* LSB doesn't have __thread, https://lsbbugs.linuxfoundation.org/show_bug.cgi?id=993 */
-#define HAVE_TLS
-#endif
-#if defined(Q_CC_XLC) || defined (Q_CC_SUN)
-#define HAVE_TLS
-#endif
-#ifdef HAVE_TLS
-static __thread QThreadData *currentThreadData = 0;
-#endif
+static thread_local QThreadData *currentThreadData = 0;
static pthread_once_t current_thread_data_once = PTHREAD_ONCE_INIT;
static pthread_key_t current_thread_data_key;
@@ -138,7 +129,7 @@ static void destroy_current_thread_data(void *p)
pthread_setspecific(current_thread_data_key, p);
QThreadData *data = static_cast<QThreadData *>(p);
if (data->isAdopted) {
- QThread *thread = data->thread;
+ QThread *thread = data->thread.loadAcquire();
Q_ASSERT(thread);
QThreadPrivate *thread_p = static_cast<QThreadPrivate *>(QObjectPrivate::get(thread));
Q_ASSERT(!thread_p->finished);
@@ -179,28 +170,19 @@ Q_DESTRUCTOR_FUNCTION(destroy_current_thread_data_key)
// Utility functions for getting, setting and clearing thread specific data.
static QThreadData *get_thread_data()
{
-#ifdef HAVE_TLS
return currentThreadData;
-#else
- pthread_once(&current_thread_data_once, create_current_thread_data_key);
- return reinterpret_cast<QThreadData *>(pthread_getspecific(current_thread_data_key));
-#endif
}
static void set_thread_data(QThreadData *data)
{
-#ifdef HAVE_TLS
currentThreadData = data;
-#endif
pthread_once(&current_thread_data_once, create_current_thread_data_key);
pthread_setspecific(current_thread_data_key, data);
}
static void clear_thread_data()
{
-#ifdef HAVE_TLS
currentThreadData = 0;
-#endif
pthread_setspecific(current_thread_data_key, 0);
}
@@ -249,9 +231,9 @@ QThreadData *QThreadData::current(bool createIfNecessary)
}
data->deref();
data->isAdopted = true;
- data->threadId.store(to_HANDLE(pthread_self()));
- if (!QCoreApplicationPrivate::theMainThread)
- QCoreApplicationPrivate::theMainThread = data->thread.load();
+ data->threadId.storeRelaxed(to_HANDLE(pthread_self()));
+ if (!QCoreApplicationPrivate::theMainThread.loadAcquire())
+ QCoreApplicationPrivate::theMainThread.storeRelease(data->thread.loadRelaxed());
}
return data;
}
@@ -282,7 +264,7 @@ QAbstractEventDispatcher *QThreadPrivate::createEventDispatcher(QThreadData *dat
else
return new QEventDispatcherUNIX;
#elif !defined(QT_NO_GLIB)
- const bool isQtMainThread = data->thread == QCoreApplicationPrivate::mainThread();
+ const bool isQtMainThread = data->thread.loadAcquire() == QCoreApplicationPrivate::mainThread();
if (qEnvironmentVariableIsEmpty("QT_NO_GLIB")
&& (isQtMainThread || qEnvironmentVariableIsEmpty("QT_NO_THREADED_GLIB"))
&& QEventDispatcherGlib::versionSupported())
@@ -331,7 +313,7 @@ void *QThreadPrivate::start(void *arg)
thr->d_func()->setPriority(QThread::Priority(thr->d_func()->priority & ~ThreadPriorityResetFlag));
}
- data->threadId.store(to_HANDLE(pthread_self()));
+ data->threadId.storeRelaxed(to_HANDLE(pthread_self()));
set_thread_data(data);
data->ref();
@@ -401,7 +383,7 @@ void QThreadPrivate::finish(void *arg)
QThreadStorageData::finish((void **)data);
locker.relock();
- QAbstractEventDispatcher *eventDispatcher = d->data->eventDispatcher.load();
+ QAbstractEventDispatcher *eventDispatcher = d->data->eventDispatcher.loadRelaxed();
if (eventDispatcher) {
d->data->eventDispatcher = 0;
locker.unlock();
@@ -439,7 +421,7 @@ void QThreadPrivate::finish(void *arg)
** QThread
*************************************************************************/
-Qt::HANDLE QThread::currentThreadId() Q_DECL_NOTHROW
+Qt::HANDLE QThread::currentThreadId() noexcept
{
// requires a C cast here otherwise we run into trouble on AIX
return to_HANDLE(pthread_self());
@@ -454,7 +436,7 @@ Qt::HANDLE QThread::currentThreadId() Q_DECL_NOTHROW
int QThreadPrivate::idealThreadCount = 1;
#endif
-int QThread::idealThreadCount() Q_DECL_NOTHROW
+int QThread::idealThreadCount() noexcept
{
int cores = 1;
@@ -714,8 +696,7 @@ void QThread::start(Priority priority)
#endif // _POSIX_THREAD_ATTR_STACKSIZE
if (code) {
- qWarning("QThread::start: Thread stack size error: %s",
- qPrintable(qt_error_string(code)));
+ qErrnoWarning(code, "QThread::start: Thread stack size error");
// we failed to set the stacksize, and as the documentation states,
// the thread will fail to run...
@@ -741,16 +722,16 @@ void QThread::start(Priority priority)
#endif
code = pthread_create(&threadId, &attr, QThreadPrivate::start, this);
}
- d->data->threadId.store(to_HANDLE(threadId));
+ d->data->threadId.storeRelaxed(to_HANDLE(threadId));
pthread_attr_destroy(&attr);
if (code) {
- qWarning("QThread::start: Thread creation error: %s", qPrintable(qt_error_string(code)));
+ qErrnoWarning(code, "QThread::start: Thread creation error");
d->running = false;
d->finished = false;
- d->data->threadId.store(nullptr);
+ d->data->threadId.storeRelaxed(nullptr);
}
}
@@ -760,13 +741,12 @@ void QThread::terminate()
Q_D(QThread);
QMutexLocker locker(&d->mutex);
- if (!d->data->threadId.load())
+ if (!d->data->threadId.loadRelaxed())
return;
- int code = pthread_cancel(from_HANDLE<pthread_t>(d->data->threadId.load()));
+ int code = pthread_cancel(from_HANDLE<pthread_t>(d->data->threadId.loadRelaxed()));
if (code) {
- qWarning("QThread::start: Thread termination error: %s",
- qPrintable(qt_error_string((code))));
+ qErrnoWarning(code, "QThread::start: Thread termination error");
}
#endif
}
@@ -776,7 +756,7 @@ bool QThread::wait(unsigned long time)
Q_D(QThread);
QMutexLocker locker(&d->mutex);
- if (from_HANDLE<pthread_t>(d->data->threadId.load()) == pthread_self()) {
+ if (from_HANDLE<pthread_t>(d->data->threadId.loadRelaxed()) == pthread_self()) {
qWarning("QThread::wait: Thread tried to wait on itself");
return false;
}
@@ -818,7 +798,7 @@ void QThreadPrivate::setPriority(QThread::Priority threadPriority)
int sched_policy;
sched_param param;
- if (pthread_getschedparam(from_HANDLE<pthread_t>(data->threadId.load()), &sched_policy, &param) != 0) {
+ if (pthread_getschedparam(from_HANDLE<pthread_t>(data->threadId.loadRelaxed()), &sched_policy, &param) != 0) {
// failed to get the scheduling policy, don't bother setting
// the priority
qWarning("QThread::setPriority: Cannot get scheduler parameters");
@@ -834,15 +814,15 @@ void QThreadPrivate::setPriority(QThread::Priority threadPriority)
}
param.sched_priority = prio;
- int status = pthread_setschedparam(from_HANDLE<pthread_t>(data->threadId.load()), sched_policy, &param);
+ int status = pthread_setschedparam(from_HANDLE<pthread_t>(data->threadId.loadRelaxed()), sched_policy, &param);
# ifdef SCHED_IDLE
// were we trying to set to idle priority and failed?
if (status == -1 && sched_policy == SCHED_IDLE && errno == EINVAL) {
// reset to lowest priority possible
- pthread_getschedparam(from_HANDLE<pthread_t>(data->threadId.load()), &sched_policy, &param);
+ pthread_getschedparam(from_HANDLE<pthread_t>(data->threadId.loadRelaxed()), &sched_policy, &param);
param.sched_priority = sched_get_priority_min(sched_policy);
- pthread_setschedparam(from_HANDLE<pthread_t>(data->threadId.load()), sched_policy, &param);
+ pthread_setschedparam(from_HANDLE<pthread_t>(data->threadId.loadRelaxed()), sched_policy, &param);
}
# else
Q_UNUSED(status);
diff --git a/src/corelib/thread/qthread_win.cpp b/src/corelib/thread/qthread_win.cpp
index 5c7642c26e..a72df2fc40 100644
--- a/src/corelib/thread/qthread_win.cpp
+++ b/src/corelib/thread/qthread_win.cpp
@@ -140,11 +140,11 @@ QThreadData *QThreadData::current(bool createIfNecessary)
}
threadData->deref();
threadData->isAdopted = true;
- threadData->threadId.store(reinterpret_cast<Qt::HANDLE>(quintptr(GetCurrentThreadId())));
+ threadData->threadId.storeRelaxed(reinterpret_cast<Qt::HANDLE>(quintptr(GetCurrentThreadId())));
#ifndef Q_OS_WINRT
if (!QCoreApplicationPrivate::theMainThread) {
- QCoreApplicationPrivate::theMainThread = threadData->thread.load();
+ QCoreApplicationPrivate::theMainThread = threadData->thread.loadRelaxed();
} else {
#else
// for winrt the main thread is set explicitly in QCoreApplication's constructor as the
@@ -186,9 +186,9 @@ void QThreadData::setMainThread()
}
threadData->deref();
threadData->isAdopted = true;
- threadData->threadId.store(reinterpret_cast<Qt::HANDLE>(quintptr(GetCurrentThreadId())));
+ threadData->threadId.storeRelaxed(reinterpret_cast<Qt::HANDLE>(quintptr(GetCurrentThreadId())));
}
- QCoreApplicationPrivate::theMainThread = threadData->thread.load();
+ QCoreApplicationPrivate::theMainThread = threadData->thread.loadRelaxed();
}
#endif
@@ -374,14 +374,14 @@ QAbstractEventDispatcher *QThreadPrivate::createEventDispatcher(QThreadData *dat
#if QT_CONFIG(thread)
-unsigned int __stdcall QT_ENSURE_STACK_ALIGNED_FOR_SSE QThreadPrivate::start(void *arg) Q_DECL_NOEXCEPT
+unsigned int __stdcall QT_ENSURE_STACK_ALIGNED_FOR_SSE QThreadPrivate::start(void *arg) noexcept
{
QThread *thr = reinterpret_cast<QThread *>(arg);
QThreadData *data = QThreadData::get2(thr);
qt_create_tls();
TlsSetValue(qt_current_thread_data_tls_index, data);
- data->threadId.store(reinterpret_cast<Qt::HANDLE>(quintptr(GetCurrentThreadId())));
+ data->threadId.storeRelaxed(reinterpret_cast<Qt::HANDLE>(quintptr(GetCurrentThreadId())));
QThread::setTerminationEnabled(false);
@@ -408,7 +408,7 @@ unsigned int __stdcall QT_ENSURE_STACK_ALIGNED_FOR_SSE QThreadPrivate::start(voi
return 0;
}
-void QThreadPrivate::finish(void *arg, bool lockAnyway) Q_DECL_NOEXCEPT
+void QThreadPrivate::finish(void *arg, bool lockAnyway) noexcept
{
QThread *thr = reinterpret_cast<QThread *>(arg);
QThreadPrivate *d = thr->d_func();
@@ -423,7 +423,7 @@ void QThreadPrivate::finish(void *arg, bool lockAnyway) Q_DECL_NOEXCEPT
QThreadStorageData::finish(tls_data);
locker.relock();
- QAbstractEventDispatcher *eventDispatcher = d->data->eventDispatcher.load();
+ QAbstractEventDispatcher *eventDispatcher = d->data->eventDispatcher.loadRelaxed();
if (eventDispatcher) {
d->data->eventDispatcher = 0;
locker.unlock();
@@ -449,12 +449,12 @@ void QThreadPrivate::finish(void *arg, bool lockAnyway) Q_DECL_NOEXCEPT
** QThread
*************************************************************************/
-Qt::HANDLE QThread::currentThreadId() Q_DECL_NOTHROW
+Qt::HANDLE QThread::currentThreadId() noexcept
{
return reinterpret_cast<Qt::HANDLE>(quintptr(GetCurrentThreadId()));
}
-int QThread::idealThreadCount() Q_DECL_NOTHROW
+int QThread::idealThreadCount() noexcept
{
SYSTEM_INFO sysinfo;
#ifndef Q_OS_WINRT
diff --git a/src/corelib/thread/qthreadpool_p.h b/src/corelib/thread/qthreadpool_p.h
index 952e02ef20..01852d8366 100644
--- a/src/corelib/thread/qthreadpool_p.h
+++ b/src/corelib/thread/qthreadpool_p.h
@@ -162,7 +162,7 @@ public:
void tryToStartMoreThreads();
bool tooManyThreadsActive() const;
- void startThread(QRunnable *runnable = 0);
+ void startThread(QRunnable *runnable = nullptr);
void reset();
bool waitForDone(int msecs);
bool waitForDone(const QDeadlineTimer &timer);
diff --git a/src/corelib/thread/qthreadstorage.cpp b/src/corelib/thread/qthreadstorage.cpp
index 8b82118a5c..fdc484d2d2 100644
--- a/src/corelib/thread/qthreadstorage.cpp
+++ b/src/corelib/thread/qthreadstorage.cpp
@@ -126,7 +126,7 @@ void **QThreadStorageData::get() const
DEBUG_MSG("QThreadStorageData: Returning storage %d, data %p, for thread %p",
id,
*v,
- data->thread.load());
+ data->thread.loadRelaxed());
return *v ? v : 0;
}
@@ -148,7 +148,7 @@ void **QThreadStorageData::set(void *p)
DEBUG_MSG("QThreadStorageData: Deleting previous storage %d, data %p, for thread %p",
id,
value,
- data->thread.load());
+ data->thread.loadRelaxed());
QMutexLocker locker(&destructorsMutex);
DestructorMap *destr = destructors();
@@ -164,7 +164,7 @@ void **QThreadStorageData::set(void *p)
// store new data
value = p;
- DEBUG_MSG("QThreadStorageData: Set storage %d for thread %p to %p", id, data->thread.load(), p);
+ DEBUG_MSG("QThreadStorageData: Set storage %d for thread %p to %p", id, data->thread.loadRelaxed(), p);
return &value;
}
diff --git a/src/corelib/thread/qthreadstorage.h b/src/corelib/thread/qthreadstorage.h
index 55fc482da3..9eb8672e92 100644
--- a/src/corelib/thread/qthreadstorage.h
+++ b/src/corelib/thread/qthreadstorage.h
@@ -69,7 +69,7 @@ inline
T *&qThreadStorage_localData(QThreadStorageData &d, T **)
{
void **v = d.get();
- if (!v) v = d.set(0);
+ if (!v) v = d.set(nullptr);
return *(reinterpret_cast<T**>(v));
}
@@ -139,7 +139,7 @@ public:
inline ~QThreadStorage() { }
inline bool hasLocalData() const
- { return d.get() != 0; }
+ { return d.get() != nullptr; }
inline T& localData()
{ return qThreadStorage_localData(d, reinterpret_cast<T*>(0)); }
diff --git a/src/corelib/thread/qwaitcondition_unix.cpp b/src/corelib/thread/qwaitcondition_unix.cpp
index 0ba90763cf..dd7475cec5 100644
--- a/src/corelib/thread/qwaitcondition_unix.cpp
+++ b/src/corelib/thread/qwaitcondition_unix.cpp
@@ -72,7 +72,7 @@ __attribute__((weakref("__pthread_cond_timedwait_relative")));
static void report_error(int code, const char *where, const char *what)
{
if (code != 0)
- qWarning("%s: %s failure: %s", where, what, qPrintable(qt_error_string(code)));
+ qErrnoWarning(code, "%s: %s failure", where, what);
}
void qt_initialize_pthread_cond(pthread_cond_t *cond, const char *where)
diff --git a/src/corelib/thread/thread.pri b/src/corelib/thread/thread.pri
index 22f0de0523..9fc9af0e65 100644
--- a/src/corelib/thread/thread.pri
+++ b/src/corelib/thread/thread.pri
@@ -28,7 +28,7 @@ qtConfig(thread) {
thread/qbasicatomic.h \
thread/qfutex_p.h \
thread/qgenericatomic.h \
- thread/qmutexpool_p.h \
+ thread/qlocking_p.h \
thread/qmutex_p.h \
thread/qorderedmutexlocker_p.h \
thread/qreadwritelock_p.h \
@@ -40,7 +40,6 @@ qtConfig(thread) {
SOURCES += \
thread/qatomic.cpp \
thread/qmutex.cpp \
- thread/qmutexpool.cpp \
thread/qreadwritelock.cpp \
thread/qsemaphore.cpp \
thread/qthreadpool.cpp \