summaryrefslogtreecommitdiffstats
path: root/src/corelib/thread
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/thread')
-rw-r--r--src/corelib/thread/qatomic.cpp182
-rw-r--r--src/corelib/thread/qatomic.h8
-rw-r--r--src/corelib/thread/qbasicatomic.h1
-rw-r--r--src/corelib/thread/qexception.cpp12
-rw-r--r--src/corelib/thread/qexception.h16
-rw-r--r--src/corelib/thread/qfutex_p.h142
-rw-r--r--src/corelib/thread/qfuture.h11
-rw-r--r--src/corelib/thread/qfuture.qdoc124
-rw-r--r--src/corelib/thread/qfutureinterface.cpp5
-rw-r--r--src/corelib/thread/qfutureinterface.h8
-rw-r--r--src/corelib/thread/qfutureinterface_p.h2
-rw-r--r--src/corelib/thread/qfuturesynchronizer.h3
-rw-r--r--src/corelib/thread/qfuturesynchronizer.qdoc20
-rw-r--r--src/corelib/thread/qfuturewatcher.cpp69
-rw-r--r--src/corelib/thread/qfuturewatcher.h24
-rw-r--r--src/corelib/thread/qfuturewatcher_p.h9
-rw-r--r--src/corelib/thread/qmutex.cpp4
-rw-r--r--src/corelib/thread/qmutex.h12
-rw-r--r--src/corelib/thread/qmutex_linux.cpp83
-rw-r--r--src/corelib/thread/qreadwritelock.h4
-rw-r--r--src/corelib/thread/qresultstore.cpp4
-rw-r--r--src/corelib/thread/qresultstore.h12
-rw-r--r--src/corelib/thread/qsemaphore.cpp206
-rw-r--r--src/corelib/thread/qsemaphore.h5
-rw-r--r--src/corelib/thread/qthread.cpp20
-rw-r--r--src/corelib/thread/qthread.h6
-rw-r--r--src/corelib/thread/qthread_p.h5
-rw-r--r--src/corelib/thread/qthread_unix.cpp57
-rw-r--r--src/corelib/thread/qthreadpool.cpp2
-rw-r--r--src/corelib/thread/qthreadpool.h2
-rw-r--r--src/corelib/thread/qthreadstorage.cpp12
-rw-r--r--src/corelib/thread/thread.pri31
32 files changed, 734 insertions, 367 deletions
diff --git a/src/corelib/thread/qatomic.cpp b/src/corelib/thread/qatomic.cpp
index ccb0ee6923..c161bec537 100644
--- a/src/corelib/thread/qatomic.cpp
+++ b/src/corelib/thread/qatomic.cpp
@@ -239,17 +239,17 @@
Constructs a QAtomicInt with the given \a value.
*/
-/*! \fn QAtomicInteger::QAtomicInteger(T value)
+/*! \fn QAtomicInteger<T>::QAtomicInteger(T value)
Constructs a QAtomicInteger with the given \a value.
*/
-/*! \fn QAtomicInteger::QAtomicInteger(const QAtomicInteger &other)
+/*! \fn template <typename T> QAtomicInteger<T>::QAtomicInteger(const QAtomicInteger &other)
Constructs a copy of \a other.
*/
-/*! \fn QAtomicInteger &QAtomicInteger::operator=(const QAtomicInteger &other)
+/*! \fn template <typename T> QAtomicInteger &QAtomicInteger<T>::operator=(const QAtomicInteger &other)
Assigns \a other to this QAtomicInteger and returns a reference to
this QAtomicInteger.
@@ -257,7 +257,7 @@
/*!
- \fn T QAtomicInteger::load() const
+ \fn template <typename T> T QAtomicInteger<T>::load() const
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
@@ -267,7 +267,7 @@
*/
/*!
- \fn T QAtomicInteger::loadAcquire() const
+ \fn template <typename T> T QAtomicInteger<T>::loadAcquire() const
Atomically loads the value of this QAtomicInteger using the "Acquire" memory
ordering. The value is not modified in any way, but note that there's no
@@ -277,7 +277,7 @@
*/
/*!
- \fn void QAtomicInteger::store(T newValue)
+ \fn template <typename T> void QAtomicInteger<T>::store(T newValue)
Atomically stores the \a newValue value into this atomic type, using
relaxed memory ordering.
@@ -286,7 +286,7 @@
*/
/*!
- \fn void QAtomicInteger::storeRelease(T newValue)
+ \fn template <typename T> void QAtomicInteger<T>::storeRelease(T newValue)
Atomically stores the \a newValue value into this atomic type, using
the "Release" memory ordering.
@@ -295,7 +295,7 @@
*/
/*!
- \fn QAtomicInteger::operator T() const
+ \fn template <typename T> QAtomicInteger<T>::operator T() const
\since 5.3
Atomically loads the value of this QAtomicInteger using a sequentially
@@ -307,29 +307,29 @@
*/
/*!
- \fn QAtomicInteger &QAtomicInteger::operator=(T newValue)
+ \fn template <typename T> QAtomicInteger &QAtomicInteger<T>::operator=(T)
\since 5.3
- Atomically stores the \a newValue value into this atomic type using a
+ Atomically stores the other value into this atomic type using a
sequentially consistent memory ordering if possible; or "Release" ordering
if not. This function returns a reference to this object.
\sa store(), storeRelease()
*/
-/*! \fn bool QAtomicInteger::isReferenceCountingNative()
+/*! \fn template <typename T> bool QAtomicInteger<T>::isReferenceCountingNative()
Returns \c true if reference counting is implemented using atomic
processor instructions, false otherwise.
*/
-/*! \fn bool QAtomicInteger::isReferenceCountingWaitFree()
+/*! \fn template <typename T> bool QAtomicInteger<T>::isReferenceCountingWaitFree()
Returns \c true if atomic reference counting is wait-free, false
otherwise.
*/
-/*! \fn bool QAtomicInteger::ref()
+/*! \fn template <typename T> bool QAtomicInteger<T>::ref()
Atomically increments the value of this QAtomicInteger. Returns \c true
if the new value is non-zero, false otherwise.
@@ -342,7 +342,7 @@
*/
/*!
- \fn T QAtomicInteger::operator++()
+ \fn template <typename T> T QAtomicInteger<T>::operator++()
\since 5.3
Atomically pre-increments the value of this QAtomicInteger. Returns the new
@@ -355,7 +355,7 @@
*/
/*!
- \fn T QAtomicInteger::operator++(int)
+ \fn template <typename T> T QAtomicInteger<T>::operator++(int)
\since 5.3
Atomically post-increments the value of this QAtomicInteger. Returns the old
@@ -367,7 +367,7 @@
\sa ref(), operator++(), operator--(int)
*/
-/*! \fn bool QAtomicInteger::deref()
+/*! \fn template <typename T> bool QAtomicInteger<T>::deref()
Atomically decrements the value of this QAtomicInteger. Returns \c true
if the new value is non-zero, false otherwise.
@@ -380,7 +380,7 @@
*/
/*!
- \fn T QAtomicInteger::operator--()
+ \fn template <typename T> T QAtomicInteger<T>::operator--()
\since 5.3
Atomically pre-decrements the value of this QAtomicInteger. Returns the new
@@ -393,7 +393,7 @@
*/
/*!
- \fn T QAtomicInteger::operator--(int)
+ \fn template <typename T> T QAtomicInteger<T>::operator--(int)
\since 5.3
Atomically post-decrements the value of this QAtomicInteger. Returns the old
@@ -405,18 +405,18 @@
\sa deref(), operator--(), operator++(int)
*/
-/*! \fn bool QAtomicInteger::isTestAndSetNative()
+/*! \fn template <typename T> bool QAtomicInteger<T>::isTestAndSetNative()
Returns \c true if test-and-set is implemented using atomic processor
instructions, false otherwise.
*/
-/*! \fn bool QAtomicInteger::isTestAndSetWaitFree()
+/*! \fn template <typename T> bool QAtomicInteger<T>::isTestAndSetWaitFree()
Returns \c true if atomic test-and-set is wait-free, false otherwise.
*/
-/*! \fn bool QAtomicInteger::testAndSetRelaxed(T expectedValue, T newValue)
+/*! \fn template <typename T> bool QAtomicInteger<T>::testAndSetRelaxed(T expectedValue, T newValue)
Atomic test-and-set.
@@ -430,7 +430,7 @@
processor to freely reorder memory accesses.
*/
-/*! \fn bool QAtomicInteger::testAndSetAcquire(T expectedValue, T newValue)
+/*! \fn template <typename T> bool QAtomicInteger<T>::testAndSetAcquire(T expectedValue, T newValue)
Atomic test-and-set.
@@ -445,7 +445,7 @@
be re-ordered before the atomic operation.
*/
-/*! \fn bool QAtomicInteger::testAndSetRelease(T expectedValue, T newValue)
+/*! \fn template <typename T> bool QAtomicInteger<T>::testAndSetRelease(T expectedValue, T newValue)
Atomic test-and-set.
@@ -460,7 +460,7 @@
re-ordered after the atomic operation.
*/
-/*! \fn bool QAtomicInteger::testAndSetOrdered(T expectedValue, T newValue)
+/*! \fn template <typename T> bool QAtomicInteger<T>::testAndSetOrdered(T expectedValue, T newValue)
Atomic test-and-set.
@@ -475,19 +475,19 @@
may not be re-ordered.
*/
-/*! \fn bool QAtomicInteger::isFetchAndStoreNative()
+/*! \fn template <typename T> bool QAtomicInteger<T>::isFetchAndStoreNative()
Returns \c true if fetch-and-store is implemented using atomic
processor instructions, false otherwise.
*/
-/*! \fn bool QAtomicInteger::isFetchAndStoreWaitFree()
+/*! \fn template <typename T> bool QAtomicInteger<T>::isFetchAndStoreWaitFree()
Returns \c true if atomic fetch-and-store is wait-free, false
otherwise.
*/
-/*! \fn T QAtomicInteger::fetchAndStoreRelaxed(T newValue)
+/*! \fn template <typename T> T QAtomicInteger<T>::fetchAndStoreRelaxed(T newValue)
Atomic fetch-and-store.
@@ -499,7 +499,7 @@
processor to freely reorder memory accesses.
*/
-/*! \fn T QAtomicInteger::fetchAndStoreAcquire(T newValue)
+/*! \fn template <typename T> T QAtomicInteger<T>::fetchAndStoreAcquire(T newValue)
Atomic fetch-and-store.
@@ -512,7 +512,7 @@
be re-ordered before the atomic operation.
*/
-/*! \fn T QAtomicInteger::fetchAndStoreRelease(T newValue)
+/*! \fn template <typename T> T QAtomicInteger<T>::fetchAndStoreRelease(T newValue)
Atomic fetch-and-store.
@@ -525,7 +525,7 @@
re-ordered after the atomic operation.
*/
-/*! \fn T QAtomicInteger::fetchAndStoreOrdered(T newValue)
+/*! \fn template <typename T> T QAtomicInteger<T>::fetchAndStoreOrdered(T newValue)
Atomic fetch-and-store.
@@ -538,19 +538,19 @@
may not be re-ordered.
*/
-/*! \fn bool QAtomicInteger::isFetchAndAddNative()
+/*! \fn template <typename T> bool QAtomicInteger<T>::isFetchAndAddNative()
Returns \c true if fetch-and-add is implemented using atomic
processor instructions, false otherwise.
*/
-/*! \fn bool QAtomicInteger::isFetchAndAddWaitFree()
+/*! \fn template <typename T> bool QAtomicInteger<T>::isFetchAndAddWaitFree()
Returns \c true if atomic fetch-and-add is wait-free, false
otherwise.
*/
-/*! \fn T QAtomicInteger::fetchAndAddRelaxed(T valueToAdd)
+/*! \fn template <typename T> T QAtomicInteger<T>::fetchAndAddRelaxed(T valueToAdd)
Atomic fetch-and-add.
@@ -564,7 +564,7 @@
\sa operator+=(), fetchAndSubRelaxed()
*/
-/*! \fn T QAtomicInteger::fetchAndAddAcquire(T valueToAdd)
+/*! \fn template <typename T> T QAtomicInteger<T>::fetchAndAddAcquire(T valueToAdd)
Atomic fetch-and-add.
@@ -579,7 +579,7 @@
\sa operator+=(), fetchAndSubAcquire()
*/
-/*! \fn T QAtomicInteger::fetchAndAddRelease(T valueToAdd)
+/*! \fn template <typename T> T QAtomicInteger<T>::fetchAndAddRelease(T valueToAdd)
Atomic fetch-and-add.
@@ -594,7 +594,7 @@
\sa operator+=(), fetchAndSubRelease()
*/
-/*! \fn T QAtomicInteger::fetchAndAddOrdered(T valueToAdd)
+/*! \fn template <typename T> T QAtomicInteger<T>::fetchAndAddOrdered(T valueToAdd)
Atomic fetch-and-add.
@@ -609,13 +609,13 @@
\sa operator+=(), fetchAndSubOrdered()
*/
-/*! \fn T QAtomicInteger::operator+=(T valueToAdd)
+/*! \fn template <typename T> T QAtomicInteger<T>::operator+=(T value)
\since 5.3
Atomic add-and-fetch.
Reads the current value of this QAtomicInteger and then adds
- \a valueToAdd to the current value, returning the new value value.
+ \a value to the current value, returning the new value.
This function uses a sequentially consistent memory ordering if possible;
or "Ordered" ordering if not.
@@ -623,7 +623,7 @@
\sa fetchAndAddOrdered(), operator-=()
*/
-/*! \fn T QAtomicInteger::fetchAndSubRelaxed(T valueToSub)
+/*! \fn template <typename T> T QAtomicInteger<T>::fetchAndSubRelaxed(T valueToSub)
\since 5.3
Atomic fetch-and-sub.
@@ -638,7 +638,7 @@
\sa operator-=(), fetchAndAddRelaxed()
*/
-/*! \fn T QAtomicInteger::fetchAndSubAcquire(T valueToSub)
+/*! \fn template <typename T> T QAtomicInteger<T>::fetchAndSubAcquire(T valueToSub)
\since 5.3
Atomic fetch-and-sub.
@@ -654,7 +654,7 @@
\sa operator-=(), fetchAndAddAcquire()
*/
-/*! \fn T QAtomicInteger::fetchAndSubRelease(T valueToSub)
+/*! \fn template <typename T> T QAtomicInteger<T>::fetchAndSubRelease(T valueToSub)
\since 5.3
Atomic fetch-and-sub.
@@ -670,7 +670,7 @@
\sa operator-=(), fetchAndAddRelease()
*/
-/*! \fn T QAtomicInteger::fetchAndSubOrdered(T valueToSub)
+/*! \fn template <typename T> T QAtomicInteger<T>::fetchAndSubOrdered(T valueToSub)
\since 5.3
Atomic fetch-and-sub.
@@ -686,13 +686,13 @@
\sa operator-=(), fetchAndAddOrdered()
*/
-/*! \fn T QAtomicInteger::operator-=(T valueToSub)
+/*! \fn template <typename T> T QAtomicInteger<T>::operator-=(T value)
\since 5.3
Atomic sub-and-fetch.
Reads the current value of this QAtomicInteger and then subtracts
- \a valueToSub to the current value, returning the new value value.
+ \a value to the current value, returning the new value.
This function uses a sequentially consistent memory ordering if possible;
or "Ordered" ordering if not.
@@ -700,7 +700,7 @@
\sa fetchAndSubOrdered(), operator+=()
*/
-/*! \fn T QAtomicInteger::fetchAndOrRelaxed(T valueToOr)
+/*! \fn template <typename T> T QAtomicInteger<T>::fetchAndOrRelaxed(T valueToOr)
\since 5.3
Atomic fetch-and-or.
@@ -715,7 +715,7 @@
\sa operator|=()
*/
-/*! \fn T QAtomicInteger::fetchAndOrAcquire(T valueToOr)
+/*! \fn template <typename T> T QAtomicInteger<T>::fetchAndOrAcquire(T valueToOr)
\since 5.3
Atomic fetch-and-or.
@@ -731,7 +731,7 @@
\sa operator|=()
*/
-/*! \fn T QAtomicInteger::fetchAndOrRelease(T valueToOr)
+/*! \fn template <typename T> T QAtomicInteger<T>::fetchAndOrRelease(T valueToOr)
\since 5.3
Atomic fetch-and-or.
@@ -747,7 +747,7 @@
\sa operator|=()
*/
-/*! \fn T QAtomicInteger::fetchAndOrOrdered(T valueToOr)
+/*! \fn template <typename T> T QAtomicInteger<T>::fetchAndOrOrdered(T valueToOr)
\since 5.3
Atomic fetch-and-or.
@@ -763,13 +763,13 @@
\sa operator|=()
*/
-/*! \fn T QAtomicInteger::operator|=(T valueToOr)
+/*! \fn template <typename T> T QAtomicInteger<T>::operator|=(T value)
\since 5.3
Atomic or-and-fetch.
Reads the current value of this QAtomicInteger and then bitwise-ORs
- \a valueToOr to the current value, returning the new value value.
+ \a value to the current value, returning the new value.
This function uses a sequentially consistent memory ordering if possible;
or "Ordered" ordering if not.
@@ -777,7 +777,7 @@
\sa fetchAndOrOrdered()
*/
-/*! \fn T QAtomicInteger::fetchAndXorRelaxed(T valueToXor)
+/*! \fn template <typename T> T QAtomicInteger<T>::fetchAndXorRelaxed(T valueToXor)
\since 5.3
Atomic fetch-and-xor.
@@ -792,7 +792,7 @@
\sa operator^=()
*/
-/*! \fn T QAtomicInteger::fetchAndXorAcquire(T valueToXor)
+/*! \fn template <typename T> T QAtomicInteger<T>::fetchAndXorAcquire(T valueToXor)
\since 5.3
Atomic fetch-and-xor.
@@ -808,7 +808,7 @@
\sa operator^=()
*/
-/*! \fn T QAtomicInteger::fetchAndXorRelease(T valueToXor)
+/*! \fn template <typename T> T QAtomicInteger<T>::fetchAndXorRelease(T valueToXor)
\since 5.3
Atomic fetch-and-xor.
@@ -824,7 +824,7 @@
\sa operator^=()
*/
-/*! \fn T QAtomicInteger::fetchAndXorOrdered(T valueToXor)
+/*! \fn template <typename T> T QAtomicInteger<T>::fetchAndXorOrdered(T valueToXor)
\since 5.3
Atomic fetch-and-xor.
@@ -840,13 +840,13 @@
\sa operator^=()
*/
-/*! \fn T QAtomicInteger::operator^=(T valueToXor)
+/*! \fn template <typename T> T QAtomicInteger<T>::operator^=(T value)
\since 5.3
Atomic xor-and-fetch.
Reads the current value of this QAtomicInteger and then bitwise-XORs
- \a valueToXor to the current value, returning the new value value.
+ \a value to the current value, returning the new value.
This function uses a sequentially consistent memory ordering if possible;
or "Ordered" ordering if not.
@@ -854,7 +854,7 @@
\sa fetchAndXorOrdered()
*/
-/*! \fn T QAtomicInteger::fetchAndAndRelaxed(T valueToAnd)
+/*! \fn template <typename T> T QAtomicInteger<T>::fetchAndAndRelaxed(T valueToAnd)
\since 5.3
Atomic fetch-and-and.
@@ -869,7 +869,7 @@
\sa operator&=()
*/
-/*! \fn T QAtomicInteger::fetchAndAndAcquire(T valueToAnd)
+/*! \fn template <typename T> T QAtomicInteger<T>::fetchAndAndAcquire(T valueToAnd)
\since 5.3
Atomic fetch-and-and.
@@ -885,7 +885,7 @@
\sa operator&=()
*/
-/*! \fn T QAtomicInteger::fetchAndAndRelease(T valueToAnd)
+/*! \fn template <typename T> T QAtomicInteger<T>::fetchAndAndRelease(T valueToAnd)
\since 5.3
Atomic fetch-and-and.
@@ -901,7 +901,7 @@
\sa operator&=()
*/
-/*! \fn T QAtomicInteger::fetchAndAndOrdered(T valueToAnd)
+/*! \fn template <typename T> T QAtomicInteger<T>::fetchAndAndOrdered(T valueToAnd)
\since 5.3
Atomic fetch-and-and.
@@ -917,13 +917,13 @@
\sa operator&=()
*/
-/*! \fn T QAtomicInteger::operator&=(T valueToAnd)
+/*! \fn template <typename T> T QAtomicInteger<T>::operator&=(T value)
\since 5.3
Atomic add-and-fetch.
Reads the current value of this QAtomicInteger and then bitwise-ANDs
- \a valueToAnd to the current value, returning the new value value.
+ \a value to the current value, returning the new value.
This function uses a sequentially consistent memory ordering if possible;
or "Ordered" ordering if not.
@@ -958,7 +958,7 @@
This macro is defined when only certain generations of the
processor support atomic reference counting. Use the
- QAtomicInteger::isReferenceCountingNative() function to check what
+ QAtomicInteger<T>::isReferenceCountingNative() function to check what
your processor supports.
\e{nn} is the size of the integer, in bits (8, 16, 32 or 64).
@@ -1001,7 +1001,7 @@
This macro is defined when only certain generations of the
processor support atomic test-and-set on integers. Use the
- QAtomicInteger::isTestAndSetNative() function to check what your
+ QAtomicInteger<T>::isTestAndSetNative() function to check what your
processor supports.
\e{nn} is the size of the integer, in bits (8, 16, 32 or 64).
@@ -1044,7 +1044,7 @@
This macro is defined when only certain generations of the
processor support atomic fetch-and-store on integers. Use the
- QAtomicInteger::isFetchAndStoreNative() function to check what your
+ QAtomicInteger<T>::isFetchAndStoreNative() function to check what your
processor supports.
\e{nn} is the size of the integer, in bits (8, 16, 32 or 64).
@@ -1087,7 +1087,7 @@
This macro is defined when only certain generations of the
processor support atomic fetch-and-add on integers. Use the
- QAtomicInteger::isFetchAndAddNative() function to check what your
+ QAtomicInteger<T>::isFetchAndAddNative() function to check what your
processor supports.
\e{nn} is the size of the integer, in bits (8, 16, 32 or 64).
@@ -1260,24 +1260,24 @@
\sa QAtomicInteger
*/
-/*! \fn QAtomicPointer::QAtomicPointer(T *value)
+/*! \fn template <typename T> QAtomicPointer<T>::QAtomicPointer(T *value)
Constructs a QAtomicPointer with the given \a value.
*/
-/*! \fn QAtomicPointer::QAtomicPointer(const QAtomicPointer<T> &other)
+/*! \fn template <typename T> QAtomicPointer<T>::QAtomicPointer(const QAtomicPointer<T> &other)
Constructs a copy of \a other.
*/
-/*! \fn QAtomicPointer<T> &QAtomicPointer::operator=(const QAtomicPointer<T> &other)
+/*! \fn template <typename T> QAtomicPointer &QAtomicPointer<T>::operator=(const QAtomicPointer &other)
Assigns \a other to this QAtomicPointer and returns a reference to
this QAtomicPointer.
*/
/*!
- \fn T *QAtomicPointer::load() const
+ \fn template <typename T> T *QAtomicPointer<T>::load() const
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
@@ -1287,7 +1287,7 @@
*/
/*!
- \fn T *QAtomicPointer::loadAcquire() const
+ \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
@@ -1297,7 +1297,7 @@
*/
/*!
- \fn void QAtomicPointer::store(T *newValue)
+ \fn template <typename T> void QAtomicPointer<T>::store(T *newValue)
Atomically stores the \a newValue value into this atomic type, using
relaxed memory ordering.
@@ -1306,7 +1306,7 @@
*/
/*!
- \fn void QAtomicPointer::storeRelease(T *newValue)
+ \fn template <typename T> void QAtomicPointer<T>::storeRelease(T *newValue)
Atomically stores the \a newValue value into this atomic type, using
the "Release" memory ordering.
@@ -1314,18 +1314,18 @@
\sa store(), load()
*/
-/*! \fn bool QAtomicPointer::isTestAndSetNative()
+/*! \fn template <typename T> bool QAtomicPointer<T>::isTestAndSetNative()
Returns \c true if test-and-set is implemented using atomic processor
instructions, false otherwise.
*/
-/*! \fn bool QAtomicPointer::isTestAndSetWaitFree()
+/*! \fn template <typename T> bool QAtomicPointer<T>::isTestAndSetWaitFree()
Returns \c true if atomic test-and-set is wait-free, false otherwise.
*/
-/*! \fn bool QAtomicPointer::testAndSetRelaxed(T *expectedValue, T *newValue)
+/*! \fn template <typename T> bool QAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue)
Atomic test-and-set.
@@ -1339,7 +1339,7 @@
processor to freely reorder memory accesses.
*/
-/*! \fn bool QAtomicPointer::testAndSetAcquire(T *expectedValue, T *newValue)
+/*! \fn template <typename T> bool QAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue)
Atomic test-and-set.
@@ -1354,7 +1354,7 @@
be re-ordered before the atomic operation.
*/
-/*! \fn bool QAtomicPointer::testAndSetRelease(T *expectedValue, T *newValue)
+/*! \fn template <typename T> bool QAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue)
Atomic test-and-set.
@@ -1369,7 +1369,7 @@
re-ordered after the atomic operation.
*/
-/*! \fn bool QAtomicPointer::testAndSetOrdered(T *expectedValue, T *newValue)
+/*! \fn template <typename T> bool QAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue)
Atomic test-and-set.
@@ -1384,19 +1384,19 @@
may not be re-ordered.
*/
-/*! \fn bool QAtomicPointer::isFetchAndStoreNative()
+/*! \fn template <typename T> bool QAtomicPointer<T>::isFetchAndStoreNative()
Returns \c true if fetch-and-store is implemented using atomic
processor instructions, false otherwise.
*/
-/*! \fn bool QAtomicPointer::isFetchAndStoreWaitFree()
+/*! \fn template <typename T> bool QAtomicPointer<T>::isFetchAndStoreWaitFree()
Returns \c true if atomic fetch-and-store is wait-free, false
otherwise.
*/
-/*! \fn T *QAtomicPointer::fetchAndStoreRelaxed(T *newValue)
+/*! \fn template <typename T> T *QAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue)
Atomic fetch-and-store.
@@ -1408,7 +1408,7 @@
processor to freely reorder memory accesses.
*/
-/*! \fn T *QAtomicPointer::fetchAndStoreAcquire(T *newValue)
+/*! \fn template <typename T> T *QAtomicPointer<T>::fetchAndStoreAcquire(T *newValue)
Atomic fetch-and-store.
@@ -1421,7 +1421,7 @@
be re-ordered before the atomic operation.
*/
-/*! \fn T *QAtomicPointer::fetchAndStoreRelease(T *newValue)
+/*! \fn template <typename T> T *QAtomicPointer<T>::fetchAndStoreRelease(T *newValue)
Atomic fetch-and-store.
@@ -1434,7 +1434,7 @@
re-ordered after the atomic operation.
*/
-/*! \fn T *QAtomicPointer::fetchAndStoreOrdered(T *newValue)
+/*! \fn template <typename T> T *QAtomicPointer<T>::fetchAndStoreOrdered(T *newValue)
Atomic fetch-and-store.
@@ -1447,19 +1447,19 @@
may not be re-ordered.
*/
-/*! \fn bool QAtomicPointer::isFetchAndAddNative()
+/*! \fn template <typename T> bool QAtomicPointer<T>::isFetchAndAddNative()
Returns \c true if fetch-and-add is implemented using atomic
processor instructions, false otherwise.
*/
-/*! \fn bool QAtomicPointer::isFetchAndAddWaitFree()
+/*! \fn template <typename T> bool QAtomicPointer<T>::isFetchAndAddWaitFree()
Returns \c true if atomic fetch-and-add is wait-free, false
otherwise.
*/
-/*! \fn T *QAtomicPointer::fetchAndAddRelaxed(qptrdiff valueToAdd)
+/*! \fn template <typename T> T *QAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd)
Atomic fetch-and-add.
@@ -1471,7 +1471,7 @@
processor to freely reorder memory accesses.
*/
-/*! \fn T *QAtomicPointer::fetchAndAddAcquire(qptrdiff valueToAdd)
+/*! \fn template <typename T> T *QAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd)
Atomic fetch-and-add.
@@ -1484,7 +1484,7 @@
be re-ordered before the atomic operation.
*/
-/*! \fn T *QAtomicPointer::fetchAndAddRelease(qptrdiff valueToAdd)
+/*! \fn template <typename T> T *QAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd)
Atomic fetch-and-add.
@@ -1497,7 +1497,7 @@
re-ordered after the atomic operation.
*/
-/*! \fn T *QAtomicPointer::fetchAndAddOrdered(qptrdiff valueToAdd)
+/*! \fn template <typename T> T *QAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd)
Atomic fetch-and-add.
diff --git a/src/corelib/thread/qatomic.h b/src/corelib/thread/qatomic.h
index f9eacbf6f0..f842534c38 100644
--- a/src/corelib/thread/qatomic.h
+++ b/src/corelib/thread/qatomic.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 The Qt Company Ltd.
** Copyright (C) 2016 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
@@ -79,7 +79,7 @@ public:
return *this;
}
-#ifdef Q_QDOC
+#ifdef Q_CLANG_QDOC
T load() const;
T loadAcquire() const;
void store(T newValue);
@@ -168,9 +168,9 @@ class QAtomicPointer : public QBasicAtomicPointer<T>
{
public:
#ifdef QT_BASIC_ATOMIC_HAS_CONSTRUCTORS
- constexpr QAtomicPointer(T *value = 0) Q_DECL_NOTHROW : QBasicAtomicPointer<T>(value) {}
+ constexpr QAtomicPointer(T *value = nullptr) Q_DECL_NOTHROW : QBasicAtomicPointer<T>(value) {}
#else
- inline QAtomicPointer(T *value = 0) Q_DECL_NOTHROW
+ inline QAtomicPointer(T *value = nullptr) Q_DECL_NOTHROW
{
this->store(value);
}
diff --git a/src/corelib/thread/qbasicatomic.h b/src/corelib/thread/qbasicatomic.h
index 24218e833a..92db7a6228 100644
--- a/src/corelib/thread/qbasicatomic.h
+++ b/src/corelib/thread/qbasicatomic.h
@@ -90,6 +90,7 @@ template <typename T>
class QBasicAtomicInteger
{
public:
+ typedef T Type;
typedef QAtomicOps<T> Ops;
// static check that this is a valid integer
Q_STATIC_ASSERT_X(QTypeInfo<T>::isIntegral, "template parameter is not an integral type");
diff --git a/src/corelib/thread/qexception.cpp b/src/corelib/thread/qexception.cpp
index 62c2b608d8..a3e30d5a7a 100644
--- a/src/corelib/thread/qexception.cpp
+++ b/src/corelib/thread/qexception.cpp
@@ -40,8 +40,7 @@
#include "qexception.h"
#include "QtCore/qshareddata.h"
-#ifndef QT_NO_QFUTURE
-#ifndef QT_NO_EXCEPTIONS
+#if !defined(QT_NO_EXCEPTIONS) || defined(Q_CLANG_QDOC)
QT_BEGIN_NAMESPACE
@@ -155,7 +154,7 @@ QUnhandledException *QUnhandledException::clone() const
return new QUnhandledException(*this);
}
-#ifndef Q_QDOC
+#if !defined(Q_CLANG_QDOC)
namespace QtPrivate {
@@ -171,7 +170,7 @@ public:
};
ExceptionHolder::ExceptionHolder(QException *exception)
-: base(exception ? new Base(exception) : Q_NULLPTR) {}
+: base(exception ? new Base(exception) : nullptr) {}
ExceptionHolder::ExceptionHolder(const ExceptionHolder &other)
: base(other.base)
@@ -188,7 +187,7 @@ ExceptionHolder::~ExceptionHolder()
QException *ExceptionHolder::exception() const
{
if (!base)
- return Q_NULLPTR;
+ return nullptr;
return base->exception;
}
@@ -220,9 +219,8 @@ bool ExceptionStore::hasThrown() const { return exceptionHolder.base->hasThrown;
} // namespace QtPrivate
-#endif //Q_QDOC
+#endif //Q_CLANG_QDOC
QT_END_NAMESPACE
#endif // QT_NO_EXCEPTIONS
-#endif // QT_NO_QFUTURE
diff --git a/src/corelib/thread/qexception.h b/src/corelib/thread/qexception.h
index b14d386c69..d33904c1f2 100644
--- a/src/corelib/thread/qexception.h
+++ b/src/corelib/thread/qexception.h
@@ -40,10 +40,6 @@
#ifndef QTCORE_QEXCEPTION_H
#define QTCORE_QEXCEPTION_H
-#include <QtCore/qglobal.h>
-
-#ifndef QT_NO_QFUTURE
-
#include <QtCore/qatomic.h>
#include <QtCore/qshareddata.h>
@@ -51,10 +47,12 @@
# include <exception>
#endif
+QT_REQUIRE_CONFIG(future);
+
QT_BEGIN_NAMESPACE
-#ifndef QT_NO_EXCEPTIONS
+#if !defined(QT_NO_EXCEPTIONS) || defined(Q_CLANG_QDOC)
class Q_CORE_EXPORT QException : public std::exception
{
@@ -80,8 +78,8 @@ public:
throw()
#endif
;
- void raise() const Q_DECL_OVERRIDE;
- QUnhandledException *clone() const Q_DECL_OVERRIDE;
+ void raise() const override;
+ QUnhandledException *clone() const override;
};
namespace QtPrivate {
@@ -90,7 +88,7 @@ class Base;
class Q_CORE_EXPORT ExceptionHolder
{
public:
- ExceptionHolder(QException *exception = Q_NULLPTR);
+ ExceptionHolder(QException *exception = nullptr);
ExceptionHolder(const ExceptionHolder &other);
void operator=(const ExceptionHolder &other); // ### Qt6: copy-assign operator shouldn't return void. Remove this method and the copy-ctor, they are unneeded.
~ExceptionHolder();
@@ -128,6 +126,4 @@ public:
QT_END_NAMESPACE
-#endif // QT_NO_QFUTURE
-
#endif
diff --git a/src/corelib/thread/qfutex_p.h b/src/corelib/thread/qfutex_p.h
new file mode 100644
index 0000000000..483664c783
--- /dev/null
+++ b/src/corelib/thread/qfutex_p.h
@@ -0,0 +1,142 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Intel Corporation.
+** 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 QFUTEX_P_H
+#define QFUTEX_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 <qglobal.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace QtDummyFutex {
+ Q_DECL_CONSTEXPR inline bool futexAvailable() { return false; }
+ template <typename Atomic>
+ inline bool futexWait(Atomic &, typename Atomic::Type, int = 0)
+ { Q_UNREACHABLE(); return false; }
+ template <typename Atomic> inline void futexWakeOne(Atomic &)
+ { Q_UNREACHABLE(); }
+ template <typename Atomic> inline void futexWakeAll(Atomic &)
+ { Q_UNREACHABLE(); }
+}
+
+QT_END_NAMESPACE
+
+#if defined(Q_OS_LINUX) && !defined(QT_LINUXBASE)
+// use Linux mutexes everywhere except for LSB builds
+# include <sys/syscall.h>
+# include <errno.h>
+# include <limits.h>
+# include <unistd.h>
+# include <asm/unistd.h>
+# include <linux/futex.h>
+# define QT_ALWAYS_USE_FUTEX
+
+// if not defined in linux/futex.h
+# define FUTEX_PRIVATE_FLAG 128 // added in v2.6.22
+
+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
+ {
+ // 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);
+ }
+ template <typename T> int *addr(T *ptr)
+ {
+ int *int_addr = reinterpret_cast<int *>(ptr);
+#if Q_BYTE_ORDER == Q_BIG_ENDIAN
+ if (sizeof(T) > sizeof(int))
+ int_addr++; //We want a pointer to the least significant half
+#endif
+ return int_addr;
+ }
+
+ template <typename Atomic>
+ inline void futexWait(Atomic &futex, typename Atomic::Type expectedValue)
+ {
+ _q_futex(addr(&futex), FUTEX_WAIT, qintptr(expectedValue));
+ }
+ template <typename Atomic>
+ inline bool futexWait(Atomic &futex, typename Atomic::Type expectedValue, qint64 nstimeout)
+ {
+ struct timespec ts;
+ ts.tv_sec = nstimeout / 1000 / 1000 / 1000;
+ ts.tv_nsec = nstimeout % (1000 * 1000 * 1000);
+ int r = _q_futex(addr(&futex), FUTEX_WAIT, qintptr(expectedValue), quintptr(&ts));
+ return r == 0 || errno != ETIMEDOUT;
+ }
+ template <typename Atomic> inline void futexWakeOne(Atomic &futex)
+ {
+ _q_futex(addr(&futex), FUTEX_WAKE, 1);
+ }
+ template <typename Atomic> inline void futexWakeAll(Atomic &futex)
+ {
+ _q_futex(addr(&futex), FUTEX_WAKE, INT_MAX);
+ }
+ template <typename Atomic> inline
+ void futexWakeOp(Atomic &futex1, int wake1, int wake2, Atomic &futex2, quint32 op)
+ {
+ _q_futex(addr(&futex1), FUTEX_WAKE_OP, wake1, wake2, addr(&futex2), op);
+ }
+}
+namespace QtFutex = QtLinuxFutex;
+QT_END_NAMESPACE
+
+#else
+
+QT_BEGIN_NAMESPACE
+namespace QtFutex = QtDummyFutex;
+QT_END_NAMESPACE
+#endif
+
+#endif // QFUTEX_P_H
diff --git a/src/corelib/thread/qfuture.h b/src/corelib/thread/qfuture.h
index 1f0c747f40..af599c26db 100644
--- a/src/corelib/thread/qfuture.h
+++ b/src/corelib/thread/qfuture.h
@@ -42,11 +42,11 @@
#include <QtCore/qglobal.h>
-#ifndef QT_NO_QFUTURE
-
#include <QtCore/qfutureinterface.h>
#include <QtCore/qstring.h>
+QT_REQUIRE_CONFIG(future);
+
QT_BEGIN_NAMESPACE
@@ -65,6 +65,11 @@ public:
explicit QFuture(QFutureInterface<T> *p) // internal
: d(*p)
{ }
+#if defined(Q_CLANG_QDOC)
+ ~QFuture() { }
+ QFuture(const QFuture<T> &) { }
+ QFuture<T> & operator=(const QFuture<T> &) { }
+#endif
bool operator==(const QFuture &other) const { return (d == other.d); }
bool operator!=(const QFuture &other) const { return (d != other.d); }
@@ -242,6 +247,4 @@ QFuture<void> qToVoidFuture(const QFuture<T> &future)
QT_END_NAMESPACE
-#endif // QT_NO_QFUTURE
-
#endif // QFUTURE_H
diff --git a/src/corelib/thread/qfuture.qdoc b/src/corelib/thread/qfuture.qdoc
index 25306d5564..8d5b7c776c 100644
--- a/src/corelib/thread/qfuture.qdoc
+++ b/src/corelib/thread/qfuture.qdoc
@@ -93,23 +93,23 @@
\sa QFutureWatcher, {Qt Concurrent}
*/
-/*! \fn QFuture::QFuture()
+/*! \fn template <typename T> QFuture<T>::QFuture()
Constructs an empty, canceled future.
*/
-/*! \fn QFuture::QFuture(const QFuture &other)
+/*! \fn template <typename T> QFuture<T>::QFuture(const QFuture<T> &other)
Constructs a copy of \a other.
\sa operator=()
*/
-/*! \fn QFuture::QFuture(QFutureInterface<T> *resultHolder)
+/*! \fn template <typename T> QFuture<T>::QFuture(QFutureInterface<T> *resultHolder)
\internal
*/
-/*! \fn QFuture::~QFuture()
+/*! \fn template <typename T> QFuture<T>::~QFuture()
Destroys the future.
@@ -118,23 +118,23 @@
computation is completed before the future is destroyed.
*/
-/*! \fn QFuture &QFuture::operator=(const QFuture &other)
+/*! \fn template <typename T> QFuture<T> &QFuture<T>::operator=(const QFuture<T> &other)
Assigns \a other to this future and returns a reference to this future.
*/
-/*! \fn bool QFuture::operator==(const QFuture &other) const
+/*! \fn template <typename T> bool QFuture<T>::operator==(const QFuture &other) const
Returns \c true if \a other is a copy of this future; otherwise returns \c false.
*/
-/*! \fn bool QFuture::operator!=(const QFuture &other) const
+/*! \fn template <typename T> bool QFuture<T>::operator!=(const QFuture &other) const
Returns \c true if \a other is \e not a copy of this future; otherwise returns
false.
*/
-/*! \fn void QFuture::cancel()
+/*! \fn template <typename T> void QFuture<T>::cancel()
Cancels the asynchronous computation represented by this future. Note that
the cancelation is asynchronous. Use waitForFinished() after calling
@@ -150,7 +150,7 @@
but the future returned by QtConcurrent::mappedReduced() can.
*/
-/*! \fn bool QFuture::isCanceled() const
+/*! \fn template <typename T> bool QFuture<T>::isCanceled() const
Returns \c true if the asynchronous computation has been canceled with the
cancel() function; otherwise returns \c false.
@@ -159,7 +159,7 @@
function returns \c true. See cancel() for more details.
*/
-/*! \fn void QFuture::setPaused(bool paused)
+/*! \fn template <typename T> void QFuture<T>::setPaused(bool paused)
If \a paused is true, this function pauses the asynchronous computation
represented by the future. If the computation is already paused, this
@@ -178,7 +178,7 @@
\sa pause(), resume(), togglePaused()
*/
-/*! \fn bool QFuture::isPaused() const
+/*! \fn template <typename T> bool QFuture<T>::isPaused() const
Returns \c true if the asynchronous computation has been paused with the
pause() function; otherwise returns \c false.
@@ -189,7 +189,7 @@
\sa setPaused(), togglePaused()
*/
-/*! \fn void QFuture::pause()
+/*! \fn template <typename T> void QFuture<T>::pause()
Pauses the asynchronous computation represented by this future. This is a
convenience method that simply calls setPaused(true).
@@ -197,7 +197,7 @@
\sa resume()
*/
-/*! \fn void QFuture::resume()
+/*! \fn template <typename T> void QFuture<T>::resume()
Resumes the asynchronous computation represented by this future. This is a
convenience method that simply calls setPaused(false).
@@ -205,7 +205,7 @@
\sa pause()
*/
-/*! \fn void QFuture::togglePaused()
+/*! \fn template <typename T> void QFuture<T>::togglePaused()
Toggles the paused state of the asynchronous computation. In other words,
if the computation is currently paused, calling this function resumes it;
@@ -215,25 +215,25 @@
\sa setPaused(), pause(), resume()
*/
-/*! \fn bool QFuture::isStarted() const
+/*! \fn template <typename T> bool QFuture<T>::isStarted() const
Returns \c true if the asynchronous computation represented by this future
has been started; otherwise returns \c false.
*/
-/*! \fn bool QFuture::isFinished() const
+/*! \fn template <typename T> bool QFuture<T>::isFinished() const
Returns \c true if the asynchronous computation represented by this future
has finished; otherwise returns \c false.
*/
-/*! \fn bool QFuture::isRunning() const
+/*! \fn template <typename T> bool QFuture<T>::isRunning() const
Returns \c true if the asynchronous computation represented by this future is
currently running; otherwise returns \c false.
*/
-/*! \fn int QFuture::resultCount() const
+/*! \fn template <typename T> int QFuture<T>::resultCount() const
Returns the number of continuous results available in this future. The real
number of results stored might be different from this value, due to gaps
@@ -242,7 +242,7 @@
\sa result(), resultAt(), results()
*/
-/*! \fn int QFuture::progressValue() const
+/*! \fn template <typename T> int QFuture<T>::progressValue() const
Returns the current progress value, which is between the progressMinimum()
and progressMaximum().
@@ -250,21 +250,21 @@
\sa progressMinimum(), progressMaximum()
*/
-/*! \fn int QFuture::progressMinimum() const
+/*! \fn template <typename T> int QFuture<T>::progressMinimum() const
Returns the minimum progressValue().
\sa progressValue(), progressMaximum()
*/
-/*! \fn int QFuture::progressMaximum() const
+/*! \fn template <typename T> int QFuture<T>::progressMaximum() const
Returns the maximum progressValue().
\sa progressValue(), progressMinimum()
*/
-/*! \fn QString QFuture::progressText() const
+/*! \fn template <typename T> QString QFuture<T>::progressText() const
Returns the (optional) textual representation of the progress as reported
by the asynchronous computation.
@@ -273,13 +273,13 @@
progress, and as such, this function may return an empty string.
*/
-/*! \fn void QFuture::waitForFinished()
+/*! \fn template <typename T> void QFuture<T>::waitForFinished()
Waits for the asynchronous computation to finish (including cancel()ed
computations).
*/
-/*! \fn T QFuture::result() const
+/*! \fn template <typename T> T QFuture<T>::result() const
Returns the first result in the future. If the result is not immediately
available, this function will block and wait for the result to become
@@ -288,7 +288,7 @@
\sa resultAt(), results()
*/
-/*! \fn T QFuture::resultAt(int index) const
+/*! \fn template <typename T> T QFuture<T>::resultAt(int index) const
Returns the result at \a index in the future. If the result is not
immediately available, this function will block and wait for the result to
@@ -297,7 +297,7 @@
\sa result(), results(), resultCount()
*/
-/*! \fn bool QFuture::isResultReadyAt(int index) const
+/*! \fn template <typename T> bool QFuture<T>::isResultReadyAt(int index) const
Returns \c true if the result at \a index is immediately available; otherwise
returns \c false.
@@ -305,7 +305,7 @@
\sa resultAt(), resultCount()
*/
-/*! \fn QFuture::operator T() const
+/*! \fn template <typename T> QFuture<T>::operator T() const
Returns the first result in the future. If the result is not immediately
available, this function will block and wait for the result to become
@@ -315,7 +315,7 @@
\sa result(), resultAt(), results()
*/
-/*! \fn QList<T> QFuture::results() const
+/*! \fn template <typename T> QList<T> QFuture<T>::results() const
Returns all results from the future. If the results are not immediately
available, this function will block and wait for them to become available.
@@ -323,7 +323,7 @@
\sa result(), resultAt(), resultCount()
*/
-/*! \fn QFuture::const_iterator QFuture::begin() const
+/*! \fn template <typename T> QFuture<T>::const_iterator QFuture<T>::begin() const
Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first result in the
future.
@@ -331,7 +331,7 @@
\sa constBegin(), end()
*/
-/*! \fn QFuture::const_iterator QFuture::end() const
+/*! \fn template <typename T> QFuture<T>::const_iterator QFuture<T>::end() const
Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary result
after the last result in the future.
@@ -339,7 +339,7 @@
\sa begin(), constEnd()
*/
-/*! \fn QFuture::const_iterator QFuture::constBegin() const
+/*! \fn template <typename T> QFuture<T>::const_iterator QFuture<T>::constBegin() const
Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first result in the
future.
@@ -347,7 +347,7 @@
\sa begin(), constEnd()
*/
-/*! \fn QFuture::const_iterator QFuture::constEnd() const
+/*! \fn template <typename T> QFuture<T>::const_iterator QFuture<T>::constEnd() const
Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary result
after the last result in the future.
@@ -403,7 +403,7 @@
Typedef for const T &. Provided for STL compatibility.
*/
-/*! \fn QFuture::const_iterator::const_iterator()
+/*! \fn template <typename T> QFuture<T>::const_iterator::const_iterator()
Constructs an uninitialized iterator.
@@ -414,31 +414,31 @@
\sa QFuture::constBegin(), QFuture::constEnd()
*/
-/*! \fn QFuture::const_iterator::const_iterator(QFuture const * const future, int index)
+/*! \fn template <typename T> QFuture<T>::const_iterator::const_iterator(QFuture const * const future, int index)
\internal
*/
-/*! \fn QFuture::const_iterator::const_iterator(const const_iterator &other)
+/*! \fn template <typename T> QFuture<T>::const_iterator::const_iterator(const const_iterator &other)
Constructs a copy of \a other.
*/
-/*! \fn QFuture::const_iterator &QFuture::const_iterator::operator=(const const_iterator &other)
+/*! \fn template <typename T> QFuture<T>::const_iterator &QFuture<T>::const_iterator::operator=(const const_iterator &other)
Assigns \a other to this iterator.
*/
-/*! \fn const T &QFuture::const_iterator::operator*() const
+/*! \fn template <typename T> const T &QFuture<T>::const_iterator::operator*() const
Returns the current result.
*/
-/*! \fn const T *QFuture::const_iterator::operator->() const
+/*! \fn template <typename T> const T *QFuture<T>::const_iterator::operator->() const
Returns a pointer to the current result.
*/
-/*! \fn bool QFuture::const_iterator::operator!=(const const_iterator &other) const
+/*! \fn template <typename T> bool QFuture<T>::const_iterator::operator!=(const const_iterator &other) const
Returns \c true if \a other points to a different result than this iterator;
otherwise returns \c false.
@@ -446,7 +446,7 @@
\sa operator==()
*/
-/*! \fn bool QFuture::const_iterator::operator==(const const_iterator &other) const
+/*! \fn template <typename T> bool QFuture<T>::const_iterator::operator==(const const_iterator &other) const
Returns \c true if \a other points to the same result as this iterator;
otherwise returns \c false.
@@ -454,17 +454,17 @@
\sa operator!=()
*/
-/*! \fn QFuture::const_iterator &QFuture::const_iterator::operator++()
+/*! \fn template <typename T> QFuture<T>::const_iterator &QFuture<T>::const_iterator::operator++()
The prefix ++ operator (\c{++it}) advances the iterator to the next result
in the future and returns an iterator to the new current result.
- Calling this function on QFuture::constEnd() leads to undefined results.
+ Calling this function on QFuture<T>::constEnd() leads to undefined results.
\sa operator--()
*/
-/*! \fn QFuture::const_iterator QFuture::const_iterator::operator++(int)
+/*! \fn template <typename T> QFuture<T>::const_iterator QFuture<T>::const_iterator::operator++(int)
\overload
@@ -473,17 +473,17 @@
result.
*/
-/*! \fn QFuture::const_iterator &QFuture::const_iterator::operator--()
+/*! \fn template <typename T> QFuture<T>::const_iterator &QFuture<T>::const_iterator::operator--()
The prefix -- operator (\c{--it}) makes the preceding result current and
returns an iterator to the new current result.
- Calling this function on QFuture::constBegin() leads to undefined results.
+ Calling this function on QFuture<T>::constBegin() leads to undefined results.
\sa operator++()
*/
-/*! \fn QFuture::const_iterator QFuture::const_iterator::operator--(int)
+/*! \fn template <typename T> QFuture<T>::const_iterator QFuture<T>::const_iterator::operator--(int)
\overload
@@ -491,7 +491,7 @@
returns an iterator to the previously current result.
*/
-/*! \fn QFuture::const_iterator &QFuture::const_iterator::operator+=(int j)
+/*! \fn template <typename T> QFuture<T>::const_iterator &QFuture<T>::const_iterator::operator+=(int j)
Advances the iterator by \a j results. (If \a j is negative, the iterator
goes backward.)
@@ -499,7 +499,7 @@
\sa operator-=(), operator+()
*/
-/*! \fn QFuture::const_iterator &QFuture::const_iterator::operator-=(int j)
+/*! \fn template <typename T> QFuture<T>::const_iterator &QFuture<T>::const_iterator::operator-=(int j)
Makes the iterator go back by \a j results. (If \a j is negative, the
iterator goes forward.)
@@ -507,7 +507,7 @@
\sa operator+=(), operator-()
*/
-/*! \fn QFuture::const_iterator QFuture::const_iterator::operator+(int j) const
+/*! \fn template <typename T> QFuture<T>::const_iterator QFuture<T>::const_iterator::operator+(int j) const
Returns an iterator to the results at \a j positions forward from this
iterator. (If \a j is negative, the iterator goes backward.)
@@ -515,7 +515,7 @@
\sa operator-(), operator+=()
*/
-/*! \fn QFuture::const_iterator QFuture::const_iterator::operator-(int j) const
+/*! \fn template <typename T> QFuture<T>::const_iterator QFuture<T>::const_iterator::operator-(int j) const
Returns an iterator to the result at \a j positions backward from this
iterator. (If \a j is negative, the iterator goes forward.)
@@ -582,7 +582,7 @@
*/
/*!
- \fn QFutureIterator::QFutureIterator(const QFuture<T> &future)
+ \fn template <typename T> QFutureIterator<T>::QFutureIterator(const QFuture<T> &future)
Constructs an iterator for traversing \a future. The iterator is set to be
at the front of the result list (before the first result).
@@ -590,7 +590,7 @@
\sa operator=()
*/
-/*! \fn QFutureIterator &QFutureIterator::operator=(const QFuture<T> &future)
+/*! \fn template <typename T> QFutureIterator &QFutureIterator<T>::operator=(const QFuture<T> &future)
Makes the iterator operate on \a future. The iterator is set to be at the
front of the result list (before the first result).
@@ -598,7 +598,7 @@
\sa toFront(), toBack()
*/
-/*! \fn void QFutureIterator::toFront()
+/*! \fn template <typename T> void QFutureIterator<T>::toFront()
Moves the iterator to the front of the result list (before the first
result).
@@ -606,14 +606,14 @@
\sa toBack(), next()
*/
-/*! \fn void QFutureIterator::toBack()
+/*! \fn template <typename T> void QFutureIterator<T>::toBack()
Moves the iterator to the back of the result list (after the last result).
\sa toFront(), previous()
*/
-/*! \fn bool QFutureIterator::hasNext() const
+/*! \fn template <typename T> bool QFutureIterator<T>::hasNext() const
Returns \c true if there is at least one result ahead of the iterator, e.g.,
the iterator is \e not at the back of the result list; otherwise returns
@@ -622,7 +622,7 @@
\sa hasPrevious(), next()
*/
-/*! \fn const T &QFutureIterator::next()
+/*! \fn template <typename T> const T &QFutureIterator<T>::next()
Returns the next result and advances the iterator by one position.
@@ -632,7 +632,7 @@
\sa hasNext(), peekNext(), previous()
*/
-/*! \fn const T &QFutureIterator::peekNext() const
+/*! \fn template <typename T> const T &QFutureIterator<T>::peekNext() const
Returns the next result without moving the iterator.
@@ -642,7 +642,7 @@
\sa hasNext(), next(), peekPrevious()
*/
-/*! \fn bool QFutureIterator::hasPrevious() const
+/*! \fn template <typename T> bool QFutureIterator<T>::hasPrevious() const
Returns \c true if there is at least one result ahead of the iterator, e.g.,
the iterator is \e not at the front of the result list; otherwise returns
@@ -651,7 +651,7 @@
\sa hasNext(), previous()
*/
-/*! \fn const T &QFutureIterator::previous()
+/*! \fn template <typename T> const T &QFutureIterator<T>::previous()
Returns the previous result and moves the iterator back by one position.
@@ -661,7 +661,7 @@
\sa hasPrevious(), peekPrevious(), next()
*/
-/*! \fn const T &QFutureIterator::peekPrevious() const
+/*! \fn template <typename T> const T &QFutureIterator<T>::peekPrevious() const
Returns the previous result without moving the iterator.
@@ -671,7 +671,7 @@
\sa hasPrevious(), previous(), peekNext()
*/
-/*! \fn bool QFutureIterator::findNext(const T &value)
+/*! \fn template <typename T> bool QFutureIterator<T>::findNext(const T &value)
Searches for \a value starting from the current iterator position forward.
Returns \c true if \a value is found; otherwise returns \c false.
@@ -683,7 +683,7 @@
\sa findPrevious()
*/
-/*! \fn bool QFutureIterator::findPrevious(const T &value)
+/*! \fn template <typename T> bool QFutureIterator<T>::findPrevious(const T &value)
Searches for \a value starting from the current iterator position
backward. Returns \c true if \a value is found; otherwise returns \c false.
diff --git a/src/corelib/thread/qfutureinterface.cpp b/src/corelib/thread/qfutureinterface.cpp
index c62b8fd36b..8bf74ca288 100644
--- a/src/corelib/thread/qfutureinterface.cpp
+++ b/src/corelib/thread/qfutureinterface.cpp
@@ -39,9 +39,6 @@
// qfutureinterface.h included from qfuture.h
#include "qfuture.h"
-
-#ifndef QT_NO_QFUTURE
-
#include "qfutureinterface_p.h"
#include <QtCore/qatomic.h>
@@ -604,5 +601,3 @@ void QFutureInterfaceBasePrivate::setState(QFutureInterfaceBase::State newState)
}
QT_END_NAMESPACE
-
-#endif // QT_NO_QFUTURE
diff --git a/src/corelib/thread/qfutureinterface.h b/src/corelib/thread/qfutureinterface.h
index 7b12f51e3e..3dd236752c 100644
--- a/src/corelib/thread/qfutureinterface.h
+++ b/src/corelib/thread/qfutureinterface.h
@@ -41,13 +41,12 @@
#define QFUTUREINTERFACE_H
#include <QtCore/qrunnable.h>
-
-#ifndef QT_NO_QFUTURE
-
#include <QtCore/qmutex.h>
#include <QtCore/qexception.h>
#include <QtCore/qresultstore.h>
+QT_REQUIRE_CONFIG(future);
+
QT_BEGIN_NAMESPACE
@@ -291,10 +290,9 @@ public:
void reportResult(const void *, int) { }
void reportResults(const QVector<void> &, int) { }
- void reportFinished(const void * = Q_NULLPTR) { QFutureInterfaceBase::reportFinished(); }
+ void reportFinished(const void * = nullptr) { QFutureInterfaceBase::reportFinished(); }
};
QT_END_NAMESPACE
-#endif // QT_NO_QFUTURE
#endif // QFUTUREINTERFACE_H
diff --git a/src/corelib/thread/qfutureinterface_p.h b/src/corelib/thread/qfutureinterface_p.h
index cf882dd9b4..63e534464f 100644
--- a/src/corelib/thread/qfutureinterface_p.h
+++ b/src/corelib/thread/qfutureinterface_p.h
@@ -59,6 +59,8 @@
#include <QtCore/qrunnable.h>
#include <QtCore/qthreadpool.h>
+QT_REQUIRE_CONFIG(future);
+
QT_BEGIN_NAMESPACE
class QFutureCallOutEvent : public QEvent
diff --git a/src/corelib/thread/qfuturesynchronizer.h b/src/corelib/thread/qfuturesynchronizer.h
index 6bc2725024..5006ebb9cf 100644
--- a/src/corelib/thread/qfuturesynchronizer.h
+++ b/src/corelib/thread/qfuturesynchronizer.h
@@ -42,7 +42,7 @@
#include <QtCore/qfuture.h>
-#ifndef QT_NO_QFUTURE
+QT_REQUIRE_CONFIG(future);
QT_BEGIN_NAMESPACE
@@ -110,6 +110,5 @@ protected:
};
QT_END_NAMESPACE
-#endif // QT_NO_QFUTURE
#endif // QFUTURESYNCHRONIZER_H
diff --git a/src/corelib/thread/qfuturesynchronizer.qdoc b/src/corelib/thread/qfuturesynchronizer.qdoc
index 580eae6982..c9c402ff87 100644
--- a/src/corelib/thread/qfuturesynchronizer.qdoc
+++ b/src/corelib/thread/qfuturesynchronizer.qdoc
@@ -68,13 +68,13 @@
*/
/*!
- \fn QFutureSynchronizer::QFutureSynchronizer()
+ \fn template <typename T> QFutureSynchronizer<T>::QFutureSynchronizer()
Constructs a QFutureSynchronizer.
*/
/*!
- \fn QFutureSynchronizer::QFutureSynchronizer(const QFuture<T> &future)
+ \fn template <typename T> QFutureSynchronizer<T>::QFutureSynchronizer(const QFuture<T> &future)
Constructs a QFutureSynchronizer and begins watching \a future by calling
addFuture().
@@ -83,7 +83,7 @@
*/
/*!
- \fn QFutureSynchronizer::~QFutureSynchronizer()
+ \fn template <typename T> QFutureSynchronizer<T>::~QFutureSynchronizer()
Calls waitForFinished() function to ensure that all futures have finished
before destroying this QFutureSynchronizer.
@@ -92,7 +92,7 @@
*/
/*!
- \fn void QFutureSynchronizer::setFuture(const QFuture<T> &future)
+ \fn template <typename T> void QFutureSynchronizer<T>::setFuture(const QFuture<T> &future)
Sets \a future to be the only future managed by this QFutureSynchronizer.
This is a convenience function that calls waitForFinished(),
@@ -102,7 +102,7 @@
*/
/*!
- \fn void QFutureSynchronizer::addFuture(const QFuture<T> &future)
+ \fn template <typename T> void QFutureSynchronizer<T>::addFuture(const QFuture<T> &future)
Adds \a future to the list of managed futures.
@@ -110,7 +110,7 @@
*/
/*!
- \fn void QFutureSynchronizer::waitForFinished()
+ \fn template <typename T> void QFutureSynchronizer<T>::waitForFinished()
Waits for all futures to finish. If cancelOnWait() returns \c true, each
future is canceled before waiting for them to finish.
@@ -119,7 +119,7 @@
*/
/*!
- \fn void QFutureSynchronizer::clearFutures()
+ \fn template <typename T> void QFutureSynchronizer<T>::clearFutures()
Removes all managed futures from this QFutureSynchronizer.
@@ -127,7 +127,7 @@
*/
/*!
- \fn QList<QFuture<T> > QFutureSynchronizer::futures() const
+ \fn template <typename T> QList<QFuture<T> > QFutureSynchronizer<T>::futures() const
Returns a list of all managed futures.
@@ -135,7 +135,7 @@
*/
/*!
- \fn void QFutureSynchronizer::setCancelOnWait(bool enabled)
+ \fn template <typename T> void QFutureSynchronizer<T>::setCancelOnWait(bool enabled)
Enables or disables the cancel-on-wait feature based on the \a enabled
argument. If \a enabled is true, the waitForFinished() function will cancel
@@ -145,7 +145,7 @@
*/
/*!
- \fn bool QFutureSynchronizer::cancelOnWait() const
+ \fn template <typename T> bool QFutureSynchronizer<T>::cancelOnWait() const
Returns \c true if the cancel-on-wait feature is enabled; otherwise returns
false. If cancel-on-wait is enabled, the waitForFinished() function will
diff --git a/src/corelib/thread/qfuturewatcher.cpp b/src/corelib/thread/qfuturewatcher.cpp
index d2ec18850f..8c4cb9a5a2 100644
--- a/src/corelib/thread/qfuturewatcher.cpp
+++ b/src/corelib/thread/qfuturewatcher.cpp
@@ -38,9 +38,6 @@
****************************************************************************/
#include "qfuturewatcher.h"
-
-#ifndef QT_NO_QFUTURE
-
#include "qfuturewatcher_p.h"
#include <QtCore/qcoreevent.h>
@@ -99,7 +96,7 @@ QT_BEGIN_NAMESPACE
\sa QFuture, {Qt Concurrent}
*/
-/*! \fn QFutureWatcher::QFutureWatcher(QObject *parent)
+/*! \fn template <typename T> QFutureWatcher<T>::QFutureWatcher(QObject *parent)
Constructs a new QFutureWatcher with the given \a parent.
*/
@@ -107,12 +104,12 @@ QFutureWatcherBase::QFutureWatcherBase(QObject *parent)
:QObject(*new QFutureWatcherBasePrivate, parent)
{ }
-/*! \fn QFutureWatcher::~QFutureWatcher()
+/*! \fn template <typename T> QFutureWatcher<T>::~QFutureWatcher()
Destroys the QFutureWatcher.
*/
-/*! \fn void QFutureWatcher::cancel()
+/*! \fn template <typename T> void QFutureWatcher<T>::cancel()
Cancels the asynchronous computation represented by the future(). Note that
the cancelation is asynchronous. Use waitForFinished() after calling
@@ -134,7 +131,7 @@ void QFutureWatcherBase::cancel()
futureInterface().cancel();
}
-/*! \fn void QFutureWatcher::setPaused(bool paused)
+/*! \fn template <typename T> void QFutureWatcher<T>::setPaused(bool paused)
If \a paused is true, this function pauses the asynchronous computation
represented by the future(). If the computation is already paused, this
@@ -156,7 +153,7 @@ void QFutureWatcherBase::setPaused(bool paused)
futureInterface().setPaused(paused);
}
-/*! \fn void QFutureWatcher::pause()
+/*! \fn template <typename T> void QFutureWatcher<T>::pause()
Pauses the asynchronous computation represented by the future(). This is a
convenience method that simply calls setPaused(true).
@@ -168,7 +165,7 @@ void QFutureWatcherBase::pause()
futureInterface().setPaused(true);
}
-/*! \fn void QFutureWatcher::resume()
+/*! \fn template <typename T> void QFutureWatcher<T>::resume()
Resumes the asynchronous computation represented by the future(). This is
a convenience method that simply calls setPaused(false).
@@ -180,7 +177,7 @@ void QFutureWatcherBase::resume()
futureInterface().setPaused(false);
}
-/*! \fn void QFutureWatcher::togglePaused()
+/*! \fn template <typename T> void QFutureWatcher<T>::togglePaused()
Toggles the paused state of the asynchronous computation. In other words,
if the computation is currently paused, calling this function resumes it;
@@ -194,7 +191,7 @@ void QFutureWatcherBase::togglePaused()
futureInterface().togglePaused();
}
-/*! \fn int QFutureWatcher::progressValue() const
+/*! \fn template <typename T> int QFutureWatcher<T>::progressValue() const
Returns the current progress value, which is between the progressMinimum()
and progressMaximum().
@@ -206,7 +203,7 @@ int QFutureWatcherBase::progressValue() const
return futureInterface().progressValue();
}
-/*! \fn int QFutureWatcher::progressMinimum() const
+/*! \fn template <typename T> int QFutureWatcher<T>::progressMinimum() const
Returns the minimum progressValue().
@@ -217,7 +214,7 @@ int QFutureWatcherBase::progressMinimum() const
return futureInterface().progressMinimum();
}
-/*! \fn int QFutureWatcher::progressMaximum() const
+/*! \fn template <typename T> int QFutureWatcher<T>::progressMaximum() const
Returns the maximum progressValue().
@@ -228,7 +225,7 @@ int QFutureWatcherBase::progressMaximum() const
return futureInterface().progressMaximum();
}
-/*! \fn QString QFutureWatcher::progressText() const
+/*! \fn template <typename T> QString QFutureWatcher<T>::progressText() const
Returns the (optional) textual representation of the progress as reported
by the asynchronous computation.
@@ -241,7 +238,7 @@ QString QFutureWatcherBase::progressText() const
return futureInterface().progressText();
}
-/*! \fn bool QFutureWatcher::isStarted() const
+/*! \fn template <typename T> bool QFutureWatcher<T>::isStarted() const
Returns \c true if the asynchronous computation represented by the future()
has been started; otherwise returns \c false.
@@ -251,7 +248,7 @@ bool QFutureWatcherBase::isStarted() const
return futureInterface().queryState(QFutureInterfaceBase::Started);
}
-/*! \fn bool QFutureWatcher::isFinished() const
+/*! \fn template <typename T> bool QFutureWatcher<T>::isFinished() const
Returns \c true if the asynchronous computation represented by the future()
has finished, or if no future has been set; otherwise returns \c false.
@@ -262,7 +259,7 @@ bool QFutureWatcherBase::isFinished() const
return d->finished;
}
-/*! \fn bool QFutureWatcher::isRunning() const
+/*! \fn template <typename T> bool QFutureWatcher<T>::isRunning() const
Returns \c true if the asynchronous computation represented by the future()
is currently running; otherwise returns \c false.
@@ -272,7 +269,7 @@ bool QFutureWatcherBase::isRunning() const
return futureInterface().queryState(QFutureInterfaceBase::Running);
}
-/*! \fn bool QFutureWatcher::isCanceled() const
+/*! \fn template <typename T> bool QFutureWatcher<T>::isCanceled() const
Returns \c true if the asynchronous computation has been canceled with the
cancel() function; otherwise returns \c false.
@@ -285,7 +282,7 @@ bool QFutureWatcherBase::isCanceled() const
return futureInterface().queryState(QFutureInterfaceBase::Canceled);
}
-/*! \fn bool QFutureWatcher::isPaused() const
+/*! \fn template <typename T> bool QFutureWatcher<T>::isPaused() const
Returns \c true if the asynchronous computation has been paused with the
pause() function; otherwise returns \c false.
@@ -300,7 +297,7 @@ bool QFutureWatcherBase::isPaused() const
return futureInterface().queryState(QFutureInterfaceBase::Paused);
}
-/*! \fn void QFutureWatcher::waitForFinished()
+/*! \fn template <typename T> void QFutureWatcher<T>::waitForFinished()
Waits for the asynchronous computation to finish (including cancel()ed
computations).
@@ -339,7 +336,7 @@ bool QFutureWatcherBase::event(QEvent *event)
return QObject::event(event);
}
-/*! \fn void QFutureWatcher::setPendingResultsLimit(int limit)
+/*! \fn template <typename T> void QFutureWatcher<T>::setPendingResultsLimit(int limit)
The setPendingResultsLimit() provides throttling control. When the number
of pending resultReadyAt() or resultsReadyAt() signals exceeds the
@@ -490,7 +487,7 @@ void QFutureWatcherBasePrivate::sendCallOutEvent(QFutureCallOutEvent *event)
}
-/*! \fn const T &QFutureWatcher::result() const
+/*! \fn template <typename T> const T &QFutureWatcher<T>::result() const
Returns the first result in the future(). If the result is not immediately
available, this function will block and wait for the result to become
@@ -499,7 +496,7 @@ void QFutureWatcherBasePrivate::sendCallOutEvent(QFutureCallOutEvent *event)
\sa resultAt()
*/
-/*! \fn const T &QFutureWatcher::resultAt(int index) const
+/*! \fn template <typename T> const T &QFutureWatcher<T>::resultAt(int index) const
Returns the result at \a index in the future(). If the result is not
immediately available, this function will block and wait for the result to
@@ -508,7 +505,7 @@ void QFutureWatcherBasePrivate::sendCallOutEvent(QFutureCallOutEvent *event)
\sa result()
*/
-/*! \fn void QFutureWatcher::setFuture(const QFuture<T> &future)
+/*! \fn template <typename T> void QFutureWatcher<T>::setFuture(const QFuture<T> &future)
Starts watching the given \a future.
@@ -520,44 +517,44 @@ void QFutureWatcherBasePrivate::sendCallOutEvent(QFutureCallOutEvent *event)
\e after doing the connections.
*/
-/*! \fn QFuture<T> QFutureWatcher::future() const
+/*! \fn template <typename T> QFuture<T> QFutureWatcher<T>::future() const
Returns the watched future.
*/
-/*! \fn void QFutureWatcher::started()
+/*! \fn template <typename T> void QFutureWatcher<T>::started()
This signal is emitted when this QFutureWatcher starts watching the future
set with setFuture().
*/
/*!
- \fn void QFutureWatcher::finished()
+ \fn template <typename T> void QFutureWatcher<T>::finished()
This signal is emitted when the watched future finishes.
*/
/*!
- \fn void QFutureWatcher::canceled()
+ \fn template <typename T> void QFutureWatcher<T>::canceled()
This signal is emitted if the watched future is canceled.
*/
-/*! \fn void QFutureWatcher::paused()
+/*! \fn template <typename T> void QFutureWatcher<T>::paused()
This signal is emitted when the watched future is paused.
*/
-/*! \fn void QFutureWatcher::resumed()
+/*! \fn template <typename T> void QFutureWatcher<T>::resumed()
This signal is emitted when the watched future is resumed.
*/
/*!
- \fn void QFutureWatcher::progressRangeChanged(int minimum, int maximum)
+ \fn template <typename T> void QFutureWatcher<T>::progressRangeChanged(int minimum, int maximum)
The progress range for the watched future has changed to \a minimum and
\a maximum
*/
/*!
- \fn void QFutureWatcher::progressValueChanged(int progressValue)
+ \fn template <typename T> void QFutureWatcher<T>::progressValueChanged(int progressValue)
This signal is emitted when the watched future reports progress,
\a progressValue gives the current progress. In order to avoid overloading
@@ -567,14 +564,14 @@ void QFutureWatcherBasePrivate::sendCallOutEvent(QFutureCallOutEvent *event)
\a progressValue equals the maximum value) will always be delivered.
*/
-/*! \fn void QFutureWatcher::progressTextChanged(const QString &progressText)
+/*! \fn template <typename T> void QFutureWatcher<T>::progressTextChanged(const QString &progressText)
This signal is emitted when the watched future reports textual progress
information, \a progressText.
*/
/*!
- \fn void QFutureWatcher::resultReadyAt(int index)
+ \fn template <typename T> void QFutureWatcher<T>::resultReadyAt(int index)
This signal is emitted when the watched future reports a ready result at
\a index. If the future reports multiple results, the index will indicate
@@ -583,7 +580,7 @@ void QFutureWatcherBasePrivate::sendCallOutEvent(QFutureCallOutEvent *event)
*/
/*!
- \fn void QFutureWatcher::resultsReadyAt(int beginIndex, int endIndex);
+ \fn template <typename T> void QFutureWatcher<T>::resultsReadyAt(int beginIndex, int endIndex);
This signal is emitted when the watched future reports ready results.
The results are indexed from \a beginIndex to \a endIndex.
@@ -593,5 +590,3 @@ void QFutureWatcherBasePrivate::sendCallOutEvent(QFutureCallOutEvent *event)
QT_END_NAMESPACE
#include "moc_qfuturewatcher.cpp"
-
-#endif // QT_NO_QFUTURE
diff --git a/src/corelib/thread/qfuturewatcher.h b/src/corelib/thread/qfuturewatcher.h
index 8a6716a8f7..fb7dd30499 100644
--- a/src/corelib/thread/qfuturewatcher.h
+++ b/src/corelib/thread/qfuturewatcher.h
@@ -41,11 +41,10 @@
#define QFUTUREWATCHER_H
#include <QtCore/qfuture.h>
-
-#ifndef QT_NO_QFUTURE
-
#include <QtCore/qobject.h>
+QT_REQUIRE_CONFIG(future);
+
QT_BEGIN_NAMESPACE
@@ -58,7 +57,7 @@ class Q_CORE_EXPORT QFutureWatcherBase : public QObject
Q_DECLARE_PRIVATE(QFutureWatcherBase)
public:
- explicit QFutureWatcherBase(QObject *parent = Q_NULLPTR);
+ explicit QFutureWatcherBase(QObject *parent = nullptr);
// de-inline dtor
int progressValue() const;
@@ -76,7 +75,7 @@ public:
void setPendingResultsLimit(int limit);
- bool event(QEvent *event) Q_DECL_OVERRIDE;
+ bool event(QEvent *event) override;
Q_SIGNALS:
void started();
@@ -98,8 +97,8 @@ public Q_SLOTS:
void togglePaused();
protected:
- void connectNotify (const QMetaMethod &signal) Q_DECL_OVERRIDE;
- void disconnectNotify (const QMetaMethod &signal) Q_DECL_OVERRIDE;
+ void connectNotify (const QMetaMethod &signal) override;
+ void disconnectNotify (const QMetaMethod &signal) override;
// called from setFuture() implemented in template sub-classes
void connectOutputInterface();
@@ -166,8 +165,8 @@ public Q_SLOTS:
private:
QFuture<T> m_future;
- const QFutureInterfaceBase &futureInterface() const Q_DECL_OVERRIDE { return m_future.d; }
- QFutureInterfaceBase &futureInterface() Q_DECL_OVERRIDE { return m_future.d; }
+ const QFutureInterfaceBase &futureInterface() const override { return m_future.d; }
+ QFutureInterfaceBase &futureInterface() override { return m_future.d; }
};
template <typename T>
@@ -185,7 +184,7 @@ template <>
class QFutureWatcher<void> : public QFutureWatcherBase
{
public:
- explicit QFutureWatcher(QObject *_parent = Q_NULLPTR)
+ explicit QFutureWatcher(QObject *_parent = nullptr)
: QFutureWatcherBase(_parent)
{ }
~QFutureWatcher()
@@ -197,8 +196,8 @@ public:
private:
QFuture<void> m_future;
- const QFutureInterfaceBase &futureInterface() const Q_DECL_OVERRIDE { return m_future.d; }
- QFutureInterfaceBase &futureInterface() Q_DECL_OVERRIDE { return m_future.d; }
+ const QFutureInterfaceBase &futureInterface() const override { return m_future.d; }
+ QFutureInterfaceBase &futureInterface() override { return m_future.d; }
};
Q_INLINE_TEMPLATE void QFutureWatcher<void>::setFuture(const QFuture<void> &_future)
@@ -212,6 +211,5 @@ Q_INLINE_TEMPLATE void QFutureWatcher<void>::setFuture(const QFuture<void> &_fut
}
QT_END_NAMESPACE
-#endif // QT_NO_QFUTURE
#endif // QFUTUREWATCHER_H
diff --git a/src/corelib/thread/qfuturewatcher_p.h b/src/corelib/thread/qfuturewatcher_p.h
index e83bdaf45a..ead247b040 100644
--- a/src/corelib/thread/qfuturewatcher_p.h
+++ b/src/corelib/thread/qfuturewatcher_p.h
@@ -54,10 +54,10 @@
#include "qfutureinterface_p.h"
#include <qlist.h>
-#ifndef QT_NO_QFUTURE
-
#include <private/qobject_p.h>
+QT_REQUIRE_CONFIG(future);
+
QT_BEGIN_NAMESPACE
class QFutureWatcherBase;
@@ -69,8 +69,8 @@ class QFutureWatcherBasePrivate : public QObjectPrivate,
public:
QFutureWatcherBasePrivate();
- void postCallOutEvent(const QFutureCallOutEvent &callOutEvent) Q_DECL_OVERRIDE;
- void callOutInterfaceDisconnected() Q_DECL_OVERRIDE;
+ void postCallOutEvent(const QFutureCallOutEvent &callOutEvent) override;
+ void callOutInterfaceDisconnected() override;
void sendCallOutEvent(QFutureCallOutEvent *event);
@@ -84,5 +84,4 @@ public:
QT_END_NAMESPACE
-#endif // QT_NO_QFUTURE
#endif
diff --git a/src/corelib/thread/qmutex.cpp b/src/corelib/thread/qmutex.cpp
index 3e7033451e..63fb6f3efb 100644
--- a/src/corelib/thread/qmutex.cpp
+++ b/src/corelib/thread/qmutex.cpp
@@ -276,7 +276,7 @@ bool QMutex::tryLock(int timeout) QT_MUTEX_LOCK_NOEXCEPT
returns \c false
*/
-/*! \fn bool QMutex::try_lock_for(std::chrono::duration<Rep, Period> duration)
+/*! \fn template <class Rep, class Period> bool QMutex::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
@@ -300,7 +300,7 @@ bool QMutex::tryLock(int timeout) QT_MUTEX_LOCK_NOEXCEPT
\sa lock(), unlock()
*/
-/*! \fn bool QMutex::try_lock_until(std::chrono::time_point<Clock, Duration> timePoint)
+/*! \fn template<class Clock, class Duration> bool QMutex::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
diff --git a/src/corelib/thread/qmutex.h b/src/corelib/thread/qmutex.h
index 3d24379fa9..7cda53db5f 100644
--- a/src/corelib/thread/qmutex.h
+++ b/src/corelib/thread/qmutex.h
@@ -98,16 +98,16 @@ public:
private:
inline bool fastTryLock() Q_DECL_NOTHROW {
- return d_ptr.testAndSetAcquire(Q_NULLPTR, dummyLocked());
+ return d_ptr.testAndSetAcquire(nullptr, dummyLocked());
}
inline bool fastTryUnlock() Q_DECL_NOTHROW {
- return d_ptr.testAndSetRelease(dummyLocked(), Q_NULLPTR);
+ return d_ptr.testAndSetRelease(dummyLocked(), nullptr);
}
inline bool fastTryLock(QMutexData *&current) Q_DECL_NOTHROW {
- return d_ptr.testAndSetAcquire(Q_NULLPTR, dummyLocked(), current);
+ return d_ptr.testAndSetAcquire(nullptr, dummyLocked(), current);
}
inline bool fastTryUnlock(QMutexData *&current) Q_DECL_NOTHROW {
- return d_ptr.testAndSetRelease(dummyLocked(), Q_NULLPTR, current);
+ return d_ptr.testAndSetRelease(dummyLocked(), nullptr, current);
}
void lockInternal() QT_MUTEX_LOCK_NOEXCEPT;
@@ -139,7 +139,7 @@ public:
// Lockable concept
bool try_lock() QT_MUTEX_LOCK_NOEXCEPT { return tryLock(); }
-#if QT_HAS_INCLUDE(<chrono>)
+#if QT_HAS_INCLUDE(<chrono>) || defined(Q_CLANG_QDOC)
// TimedLockable concept
template <class Rep, class Period>
bool try_lock_for(std::chrono::duration<Rep, Period> duration)
@@ -293,7 +293,7 @@ public:
inline void unlock() Q_DECL_NOTHROW {}
void relock() Q_DECL_NOTHROW {}
- inline QMutex *mutex() const Q_DECL_NOTHROW { return Q_NULLPTR; }
+ inline QMutex *mutex() const Q_DECL_NOTHROW { return nullptr; }
private:
Q_DISABLE_COPY(QMutexLocker)
diff --git a/src/corelib/thread/qmutex_linux.cpp b/src/corelib/thread/qmutex_linux.cpp
index 5f6e74ac6f..d3d97ea108 100644
--- a/src/corelib/thread/qmutex_linux.cpp
+++ b/src/corelib/thread/qmutex_linux.cpp
@@ -44,15 +44,9 @@
#ifndef QT_NO_THREAD
#include "qatomic.h"
#include "qmutex_p.h"
-#include "qelapsedtimer.h"
+#include "qfutex_p.h"
-#include <linux/futex.h>
-#include <sys/syscall.h>
-#include <unistd.h>
-#include <errno.h>
-#include <asm/unistd.h>
-
-#ifndef QT_LINUX_FUTEX
+#ifndef QT_ALWAYS_USE_FUTEX
# error "Qt build is broken: qmutex_linux.cpp is being built but futex support is not wanted"
#endif
@@ -63,6 +57,8 @@
QT_BEGIN_NAMESPACE
+using namespace QtFutex;
+
/*
* QBasicMutex implementation on Linux with futexes
*
@@ -107,20 +103,6 @@ QT_BEGIN_NAMESPACE
* waiting in the past. We then set the mutex to 0x0 and perform a FUTEX_WAKE.
*/
-static inline int _q_futex(void *addr, int op, int val, const struct timespec *timeout) Q_DECL_NOTHROW
-{
- volatile int *int_addr = reinterpret_cast<volatile int *>(addr);
-#if Q_BYTE_ORDER == Q_BIG_ENDIAN && QT_POINTER_SIZE == 8
- int_addr++; //We want a pointer to the 32 least significant bit of QMutex::d
-#endif
- int *addr2 = 0;
- int val2 = 0;
-
- // we use __NR_futex because some libcs (like Android's bionic) don't
- // provide SYS_futex etc.
- return syscall(__NR_futex, int_addr, op | FUTEX_PRIVATE_FLAG, val, timeout, addr2, val2);
-}
-
static inline QMutexData *dummyFutexValue()
{
return reinterpret_cast<QMutexData *>(quintptr(3));
@@ -136,36 +118,38 @@ bool lockInternal_helper(QBasicAtomicPointer<QMutexData> &d_ptr, int timeout = -
if (timeout == 0)
return false;
- struct timespec ts, *pts = 0;
- if (IsTimed && timeout > 0) {
- ts.tv_sec = timeout / 1000;
- ts.tv_nsec = (timeout % 1000) * 1000 * 1000;
- }
-
// the mutex is locked already, set a bit indicating we're waiting
- while (d_ptr.fetchAndStoreAcquire(dummyFutexValue()) != 0) {
- if (IsTimed && pts == &ts) {
- // recalculate the timeout
- qint64 xtimeout = qint64(timeout) * 1000 * 1000;
- xtimeout -= elapsedTimer->nsecsElapsed();
- if (xtimeout <= 0) {
- // timer expired after we returned
- return false;
- }
- ts.tv_sec = xtimeout / Q_INT64_C(1000) / 1000 / 1000;
- ts.tv_nsec = xtimeout % (Q_INT64_C(1000) * 1000 * 1000);
- }
- if (IsTimed && timeout > 0)
- pts = &ts;
+ if (d_ptr.fetchAndStoreAcquire(dummyFutexValue()) == nullptr)
+ return true;
+ qint64 nstimeout = timeout * Q_INT64_C(1000) * 1000;
+ qint64 remainingTime = nstimeout;
+ forever {
// successfully set the waiting bit, now sleep
- int r = _q_futex(&d_ptr, FUTEX_WAIT, quintptr(dummyFutexValue()), pts);
- if (IsTimed && r != 0 && errno == ETIMEDOUT)
- return false;
+ if (IsTimed && nstimeout >= 0) {
+ bool r = futexWait(d_ptr, dummyFutexValue(), remainingTime);
+ if (!r)
+ return false;
+
+ // we got woken up, so try to acquire the mutex
+ // note we must set to dummyFutexValue because there could be other threads
+ // also waiting
+ if (d_ptr.fetchAndStoreAcquire(dummyFutexValue()) == nullptr)
+ return true;
- // we got woken up, so try to acquire the mutex
- // note we must set to dummyFutexValue because there could be other threads
- // also waiting
+ // recalculate the timeout
+ remainingTime = nstimeout - elapsedTimer->nsecsElapsed();
+ if (remainingTime <= 0)
+ return false;
+ } else {
+ futexWait(d_ptr, dummyFutexValue());
+
+ // we got woken up, so try to acquire the mutex
+ // note we must set to dummyFutexValue because there could be other threads
+ // also waiting
+ if (d_ptr.fetchAndStoreAcquire(dummyFutexValue()) == nullptr)
+ return true;
+ }
}
Q_ASSERT(d_ptr.load());
@@ -195,10 +179,9 @@ void QBasicMutex::unlockInternal() Q_DECL_NOTHROW
Q_ASSERT(!isRecursive());
d_ptr.storeRelease(0);
- _q_futex(&d_ptr, FUTEX_WAKE, 1, 0);
+ futexWakeOne(d_ptr);
}
-
QT_END_NAMESPACE
#endif // QT_NO_THREAD
diff --git a/src/corelib/thread/qreadwritelock.h b/src/corelib/thread/qreadwritelock.h
index 777efdb3bf..ecdb98f2f5 100644
--- a/src/corelib/thread/qreadwritelock.h
+++ b/src/corelib/thread/qreadwritelock.h
@@ -205,7 +205,7 @@ public:
static inline void unlock() Q_DECL_NOTHROW { }
static inline void relock() Q_DECL_NOTHROW { }
- static inline QReadWriteLock *readWriteLock() Q_DECL_NOTHROW { return Q_NULLPTR; }
+ static inline QReadWriteLock *readWriteLock() Q_DECL_NOTHROW { return nullptr; }
private:
Q_DISABLE_COPY(QReadLocker)
@@ -219,7 +219,7 @@ public:
static inline void unlock() Q_DECL_NOTHROW { }
static inline void relock() Q_DECL_NOTHROW { }
- static inline QReadWriteLock *readWriteLock() Q_DECL_NOTHROW { return Q_NULLPTR; }
+ static inline QReadWriteLock *readWriteLock() Q_DECL_NOTHROW { return nullptr; }
private:
Q_DISABLE_COPY(QWriteLocker)
diff --git a/src/corelib/thread/qresultstore.cpp b/src/corelib/thread/qresultstore.cpp
index 9a6fcec678..e0ce1b4b78 100644
--- a/src/corelib/thread/qresultstore.cpp
+++ b/src/corelib/thread/qresultstore.cpp
@@ -39,8 +39,6 @@
#include "qresultstore.h"
-#ifndef QT_NO_QFUTURE
-
QT_BEGIN_NAMESPACE
namespace QtPrivate {
@@ -256,5 +254,3 @@ int ResultStoreBase::updateInsertIndex(int index, int _count)
} // namespace QtPrivate
QT_END_NAMESPACE
-
-#endif // QT_NO_QFUTURE
diff --git a/src/corelib/thread/qresultstore.h b/src/corelib/thread/qresultstore.h
index 6c814ef854..39f0a6d1bb 100644
--- a/src/corelib/thread/qresultstore.h
+++ b/src/corelib/thread/qresultstore.h
@@ -40,13 +40,11 @@
#ifndef QTCORE_RESULTSTORE_H
#define QTCORE_RESULTSTORE_H
-#include <QtCore/qglobal.h>
-
-#ifndef QT_NO_QFUTURE
-
#include <QtCore/qmap.h>
#include <QtCore/qdebug.h>
+QT_REQUIRE_CONFIG(future);
+
QT_BEGIN_NAMESPACE
@@ -67,8 +65,8 @@ class ResultItem
public:
ResultItem(const void *_result, int _count) : m_count(_count), result(_result) { } // contruct with vector of results
ResultItem(const void *_result) : m_count(0), result(_result) { } // construct with result
- ResultItem() : m_count(0), result(Q_NULLPTR) { }
- bool isValid() const { return result != Q_NULLPTR; }
+ ResultItem() : m_count(0), result(nullptr) { }
+ bool isValid() const { return result != nullptr; }
bool isVector() const { return m_count != 0; }
int count() const { return (m_count == 0) ? 1 : m_count; }
int m_count; // result is either a pointer to a result or to a vector of results,
@@ -202,6 +200,4 @@ Q_DECLARE_TYPEINFO(QtPrivate::ResultItem, Q_PRIMITIVE_TYPE);
QT_END_NAMESPACE
-#endif // QT_NO_QFUTURE
-
#endif
diff --git a/src/corelib/thread/qsemaphore.cpp b/src/corelib/thread/qsemaphore.cpp
index 37736b3960..012628ef63 100644
--- a/src/corelib/thread/qsemaphore.cpp
+++ b/src/corelib/thread/qsemaphore.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2017 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -41,12 +42,15 @@
#ifndef QT_NO_THREAD
#include "qmutex.h"
+#include "qfutex_p.h"
#include "qwaitcondition.h"
#include "qdeadlinetimer.h"
#include "qdatetime.h"
QT_BEGIN_NAMESPACE
+using namespace QtFutex;
+
/*!
\class QSemaphore
\inmodule QtCore
@@ -97,6 +101,117 @@ QT_BEGIN_NAMESPACE
\sa QSemaphoreReleaser, QMutex, QWaitCondition, QThread, {Semaphores Example}
*/
+/*
+ QSemaphore futex operation
+
+ QSemaphore stores a 32-bit integer with the counter of currently available
+ tokens (value between 0 and INT_MAX). When a thread attempts to acquire n
+ tokens and the counter is larger than that, we perform a compare-and-swap
+ with the new count. If that succeeds, the acquisition worked; if not, we
+ loop again because the counter changed. If there were not enough tokens,
+ we'll perform a futex-wait.
+
+ Before we do, we set the high bit in the futex to indicate that semaphore
+ is contended: that is, there's a thread waiting for more tokens. On
+ release() for n tokens, we perform a fetch-and-add of n and then check if
+ that high bit was set. If it was, then we clear that bit and perform a
+ futex-wake on the semaphore to indicate the waiting threads can wake up and
+ acquire tokens. Which ones get woken up is unspecified.
+
+ If the system has the ability to wake up a precise number of threads, has
+ Linux's FUTEX_WAKE_OP functionality, and is 64-bit, we'll use the high word
+ as a copy of the low word, but the sign bit indicating the presence of a
+ thread waiting for multiple tokens. So when releasing n tokens on those
+ systems, we tell the kernel to wake up n single-token threads and all of
+ the multi-token ones, then clear that wait bit. Which threads get woken up
+ is unspecified, but it's likely single-token threads will get woken up
+ first.
+ */
+static const quint32 futexContendedBit = 1U << 31;
+
+static int futexAvailCounter(quintptr v)
+{
+ // the low 31 bits
+ return int(v & (futexContendedBit - 1));
+}
+
+static quintptr futexCounterParcel(int n)
+{
+ // replicate the 31 bits if we're on 64-bit
+ quint64 nn = quint32(n);
+ nn |= (nn << 32);
+ return quintptr(nn);
+}
+
+static QBasicAtomicInteger<quint32> *futexLow32(QBasicAtomicInteger<quintptr> *ptr)
+{
+ auto result = reinterpret_cast<QBasicAtomicInteger<quint32> *>(ptr);
+#if Q_BYTE_ORDER == Q_BIG_ENDIAN && QT_POINTER_SIZE > 4
+ ++result;
+#endif
+ return result;
+}
+
+#ifdef FUTEX_OP
+// quintptr might be 32bit, in which case we want this to be 0, without implicitly casting.
+static const quintptr futexMultiWaiterBit = static_cast<quintptr>(Q_UINT64_C(1) << 63);
+static QBasicAtomicInteger<quint32> *futexHigh32(QBasicAtomicInteger<quintptr> *ptr)
+{
+ auto result = reinterpret_cast<QBasicAtomicInteger<quint32> *>(ptr);
+#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN && QT_POINTER_SIZE > 4
+ ++result;
+#endif
+ return result;
+}
+#endif
+
+template <bool IsTimed> bool futexSemaphoreTryAcquire(QBasicAtomicInteger<quintptr> &u, int n, int timeout)
+{
+ QDeadlineTimer timer(IsTimed ? QDeadlineTimer(timeout) : QDeadlineTimer());
+ quintptr curValue = u.loadAcquire();
+ qint64 remainingTime = timeout * Q_INT64_C(1000) * 1000;
+ forever {
+ int available = futexAvailCounter(curValue);
+ if (available >= n) {
+ // try to acquire
+ quintptr newValue = curValue - futexCounterParcel(n);
+ if (u.testAndSetOrdered(curValue, newValue, curValue))
+ return true; // succeeded!
+ continue;
+ }
+
+ // not enough tokens available, put us to wait
+ if (remainingTime == 0)
+ return false;
+
+ // set the contended and multi-wait bits
+ quintptr bitsToSet = futexContendedBit;
+ auto ptr = futexLow32(&u);
+#ifdef FUTEX_OP
+ if (n > 1 && sizeof(curValue) >= sizeof(int)) {
+ bitsToSet |= futexMultiWaiterBit;
+ ptr = futexHigh32(&u);
+ }
+#endif
+
+ // the value is the same for either branch
+ u.fetchAndOrRelaxed(bitsToSet);
+ curValue |= bitsToSet;
+
+ if (IsTimed && remainingTime > 0) {
+ bool timedout = !futexWait(*ptr, curValue, remainingTime);
+ if (timedout)
+ return false;
+ } else {
+ futexWait(*ptr, curValue);
+ }
+
+ curValue = u.loadAcquire();
+ if (IsTimed)
+ remainingTime = timer.remainingTimeNSecs();
+ }
+}
+
class QSemaphorePrivate {
public:
inline QSemaphorePrivate(int n) : avail(n) { }
@@ -116,7 +231,10 @@ public:
QSemaphore::QSemaphore(int n)
{
Q_ASSERT_X(n >= 0, "QSemaphore", "parameter 'n' must be non-negative");
- d = new QSemaphorePrivate(n);
+ if (futexAvailable())
+ u.store(n);
+ else
+ d = new QSemaphorePrivate(n);
}
/*!
@@ -126,7 +244,10 @@ QSemaphore::QSemaphore(int n)
undefined behavior.
*/
QSemaphore::~QSemaphore()
-{ delete d; }
+{
+ if (!futexAvailable())
+ delete d;
+}
/*!
Tries to acquire \c n resources guarded by the semaphore. If \a n
@@ -138,6 +259,12 @@ QSemaphore::~QSemaphore()
void QSemaphore::acquire(int n)
{
Q_ASSERT_X(n >= 0, "QSemaphore::acquire", "parameter 'n' must be non-negative");
+
+ if (futexAvailable()) {
+ futexSemaphoreTryAcquire<false>(u, n, -1);
+ return;
+ }
+
QMutexLocker locker(&d->mutex);
while (n > d->avail)
d->cond.wait(locker.mutex());
@@ -160,6 +287,69 @@ void QSemaphore::acquire(int n)
void QSemaphore::release(int n)
{
Q_ASSERT_X(n >= 0, "QSemaphore::release", "parameter 'n' must be non-negative");
+
+ if (futexAvailable()) {
+ quintptr prevValue = u.fetchAndAddRelease(futexCounterParcel(n));
+ if (prevValue & futexContendedBit) {
+#ifdef FUTEX_OP
+ if (sizeof(u) == sizeof(int)) {
+ /*
+ On 32-bit systems, all waiters are waiting on the same address,
+ so we'll wake them all and ask the kernel to clear the high bit.
+
+ atomic {
+ int oldval = u;
+ u = oldval & ~(1 << 31);
+ futexWake(u, INT_MAX);
+ if (oldval == 0) // impossible condition
+ futexWake(u, INT_MAX);
+ }
+ */
+ quint32 op = FUTEX_OP_ANDN | FUTEX_OP_OPARG_SHIFT;
+ quint32 oparg = 31;
+ quint32 cmp = FUTEX_OP_CMP_EQ;
+ quint32 cmparg = 0;
+ futexWakeOp(u, INT_MAX, INT_MAX, u, FUTEX_OP(op, oparg, cmp, cmparg));
+ } else {
+ /*
+ On 64-bit systems, the single-token waiters wait on the low half
+ and the multi-token waiters wait on the upper half. So we ask
+ the kernel to wake up n single-token waiters and all multi-token
+ waiters (if any), then clear the multi-token wait bit.
+
+ That means we must clear the contention bit ourselves. See
+ below for handling the race.
+
+ atomic {
+ int oldval = *upper;
+ *upper = oldval & ~(1 << 31);
+ futexWake(lower, n);
+ if (oldval < 0) // sign bit set
+ futexWake(upper, INT_MAX);
+ }
+ */
+ quint32 op = FUTEX_OP_ANDN | FUTEX_OP_OPARG_SHIFT;
+ quint32 oparg = 31;
+ quint32 cmp = FUTEX_OP_CMP_LT;
+ quint32 cmparg = 0;
+ futexLow32(&u)->fetchAndAndRelease(futexContendedBit - 1);
+ futexWakeOp(*futexLow32(&u), n, INT_MAX, *futexHigh32(&u), FUTEX_OP(op, oparg, cmp, cmparg));
+ }
+#else
+ // Unset the bit and wake everyone. There are two possibibilies
+ // under which a thread can set the bit between the AND and the
+ // futexWake:
+ // 1) it did see the new counter value, but it wasn't enough for
+ // its acquisition anyway, so it has to wait;
+ // 2) it did not see the new counter value, in which case its
+ // futexWait will fail.
+ u.fetchAndAndRelease(futexContendedBit - 1);
+ futexWakeAll(u);
+#endif
+ }
+ return;
+ }
+
QMutexLocker locker(&d->mutex);
d->avail += n;
d->cond.wakeAll();
@@ -173,6 +363,9 @@ void QSemaphore::release(int n)
*/
int QSemaphore::available() const
{
+ if (futexAvailable())
+ return futexAvailCounter(u.load());
+
QMutexLocker locker(&d->mutex);
return d->avail;
}
@@ -191,6 +384,10 @@ int QSemaphore::available() const
bool QSemaphore::tryAcquire(int n)
{
Q_ASSERT_X(n >= 0, "QSemaphore::tryAcquire", "parameter 'n' must be non-negative");
+
+ if (futexAvailable())
+ return futexSemaphoreTryAcquire<false>(u, n, 0);
+
QMutexLocker locker(&d->mutex);
if (n > d->avail)
return false;
@@ -222,6 +419,9 @@ bool QSemaphore::tryAcquire(int n, int timeout)
// but QDeadlineTimer only accepts -1.
timeout = qMax(timeout, -1);
+ if (futexAvailable())
+ return futexSemaphoreTryAcquire<true>(u, n, timeout);
+
QDeadlineTimer timer(timeout);
QMutexLocker locker(&d->mutex);
qint64 remainingTime = timer.remainingTime();
diff --git a/src/corelib/thread/qsemaphore.h b/src/corelib/thread/qsemaphore.h
index 9de23173e8..2639085e99 100644
--- a/src/corelib/thread/qsemaphore.h
+++ b/src/corelib/thread/qsemaphore.h
@@ -66,7 +66,10 @@ public:
private:
Q_DISABLE_COPY(QSemaphore)
- QSemaphorePrivate *d;
+ union {
+ QSemaphorePrivate *d;
+ QBasicAtomicInteger<quintptr> u; // ### Qt6: make 64-bit
+ };
};
class QSemaphoreReleaser
diff --git a/src/corelib/thread/qthread.cpp b/src/corelib/thread/qthread.cpp
index cad7a14017..adff853669 100644
--- a/src/corelib/thread/qthread.cpp
+++ b/src/corelib/thread/qthread.cpp
@@ -844,15 +844,17 @@ bool QThread::event(QEvent *event)
void QThread::requestInterruption()
{
- Q_D(QThread);
- QMutexLocker locker(&d->mutex);
- if (!d->running || d->finished || d->isInFinish)
- return;
if (this == QCoreApplicationPrivate::theMainThread) {
qWarning("QThread::requestInterruption has no effect on the main thread");
return;
}
- d->interruptionRequested = true;
+ Q_D(QThread);
+ // ### Qt 6: use std::atomic_flag, and document that
+ // requestInterruption/isInterruptionRequested do not synchronize with each other
+ QMutexLocker locker(&d->mutex);
+ if (!d->running || d->finished || d->isInFinish)
+ return;
+ d->interruptionRequested.store(true, std::memory_order_relaxed);
}
/*!
@@ -881,10 +883,12 @@ void QThread::requestInterruption()
bool QThread::isInterruptionRequested() const
{
Q_D(const QThread);
- QMutexLocker locker(&d->mutex);
- if (!d->running || d->finished || d->isInFinish)
+ // fast path: check that the flag is not set:
+ if (!d->interruptionRequested.load(std::memory_order_relaxed))
return false;
- return d->interruptionRequested;
+ // slow path: if the flag is set, take into account run status:
+ QMutexLocker locker(&d->mutex);
+ return d->running && !d->finished && !d->isInFinish;
}
/*
diff --git a/src/corelib/thread/qthread.h b/src/corelib/thread/qthread.h
index 03b5424bb6..1f98cb59af 100644
--- a/src/corelib/thread/qthread.h
+++ b/src/corelib/thread/qthread.h
@@ -76,7 +76,7 @@ public:
static int idealThreadCount() Q_DECL_NOTHROW;
static void yieldCurrentThread();
- explicit QThread(QObject *parent = Q_NULLPTR);
+ explicit QThread(QObject *parent = nullptr);
~QThread();
enum Priority {
@@ -110,7 +110,7 @@ public:
QAbstractEventDispatcher *eventDispatcher() const;
void setEventDispatcher(QAbstractEventDispatcher *eventDispatcher);
- bool event(QEvent *event) Q_DECL_OVERRIDE;
+ bool event(QEvent *event) override;
int loopLevel() const;
#ifdef Q_QDOC
@@ -154,7 +154,7 @@ protected:
static void setTerminationEnabled(bool enabled = true);
protected:
- QThread(QThreadPrivate &dd, QObject *parent = Q_NULLPTR);
+ QThread(QThreadPrivate &dd, QObject *parent = nullptr);
private:
Q_DECLARE_PRIVATE(QThread)
diff --git a/src/corelib/thread/qthread_p.h b/src/corelib/thread/qthread_p.h
index f3d4750177..baeefd87ff 100644
--- a/src/corelib/thread/qthread_p.h
+++ b/src/corelib/thread/qthread_p.h
@@ -63,6 +63,7 @@
#include "private/qobject_p.h"
#include <algorithm>
+#include <atomic>
#ifdef Q_OS_WINRT
namespace ABI {
@@ -165,7 +166,7 @@ public:
bool running;
bool finished;
bool isInFinish; //when in QThreadPrivate::finish
- bool interruptionRequested;
+ std::atomic<bool> interruptionRequested;
bool exited;
int returnCode;
@@ -317,7 +318,7 @@ public:
void init();
private:
- void run() Q_DECL_OVERRIDE;
+ void run() override;
};
QT_END_NAMESPACE
diff --git a/src/corelib/thread/qthread_unix.cpp b/src/corelib/thread/qthread_unix.cpp
index 6540f02f34..fb5c9fd770 100644
--- a/src/corelib/thread/qthread_unix.cpp
+++ b/src/corelib/thread/qthread_unix.cpp
@@ -109,6 +109,10 @@
#define QT_HAS_THREAD_PRIORITY_SCHEDULING
#endif
+#if defined(Q_OS_QNX)
+#include <sys/neutrino.h>
+#endif
+
QT_BEGIN_NAMESPACE
@@ -487,9 +491,6 @@ int QThread::idealThreadCount() Q_DECL_NOTHROW
if (sysctl(mib, 2, &cores, &len, NULL, 0) != 0) {
perror("sysctl");
}
-#elif defined(Q_OS_IRIX)
- // IRIX
- cores = (int)sysconf(_SC_NPROC_ONLN);
#elif defined(Q_OS_INTEGRITY)
#if (__INTEGRITY_MAJOR_VERSION >= 10)
// Integrity V10+ does support multicore CPUs
@@ -555,6 +556,55 @@ void QThread::usleep(unsigned long usecs)
}
#ifdef QT_HAS_THREAD_PRIORITY_SCHEDULING
+#if defined(Q_OS_QNX)
+static bool calculateUnixPriority(int priority, int *sched_policy, int *sched_priority)
+{
+ // On QNX, NormalPriority is mapped to 10. A QNX system could use a value different
+ // than 10 for the "normal" priority but it's difficult to achieve this so we'll
+ // assume that no one has ever created such a system. This makes the mapping from
+ // Qt priorities to QNX priorities lopsided. There's usually more space available
+ // to map into above the "normal" priority than below it. QNX also has a privileged
+ // priority range (for threads that assist the kernel). We'll assume that no Qt
+ // thread needs to use priorities in that range.
+ int priority_norm = 10;
+ // _sched_info::priority_priv isn't documented. You'd think that it's the start of the
+ // privileged priority range but it's actually the end of the unpriviledged range.
+ struct _sched_info info;
+ if (SchedInfo_r(0, *sched_policy, &info) != EOK)
+ return false;
+
+ if (priority == QThread::IdlePriority) {
+ *sched_priority = info.priority_min;
+ return true;
+ }
+
+ if (priority_norm < info.priority_min)
+ priority_norm = info.priority_min;
+ if (priority_norm > info.priority_priv)
+ priority_norm = info.priority_priv;
+
+ int to_min, to_max;
+ int from_min, from_max;
+ int prio;
+ if (priority < QThread::NormalPriority) {
+ to_min = info.priority_min;
+ to_max = priority_norm;
+ from_min = QThread::LowestPriority;
+ from_max = QThread::NormalPriority;
+ } else {
+ to_min = priority_norm;
+ to_max = info.priority_priv;
+ from_min = QThread::NormalPriority;
+ from_max = QThread::TimeCriticalPriority;
+ }
+
+ prio = ((priority - from_min) * (to_max - to_min)) / (from_max - from_min) + to_min;
+ prio = qBound(to_min, prio, to_max);
+
+ *sched_priority = prio;
+ return true;
+}
+#else
// Does some magic and calculate the Unix scheduler priorities
// sched_policy is IN/OUT: it must be set to a valid policy before calling this function
// sched_priority is OUT only
@@ -598,6 +648,7 @@ static bool calculateUnixPriority(int priority, int *sched_policy, int *sched_pr
return true;
}
#endif
+#endif
void QThread::start(Priority priority)
{
diff --git a/src/corelib/thread/qthreadpool.cpp b/src/corelib/thread/qthreadpool.cpp
index 8eca3b56e4..157cbeaf4d 100644
--- a/src/corelib/thread/qthreadpool.cpp
+++ b/src/corelib/thread/qthreadpool.cpp
@@ -56,7 +56,7 @@ class QThreadPoolThread : public QThread
{
public:
QThreadPoolThread(QThreadPoolPrivate *manager);
- void run() Q_DECL_OVERRIDE;
+ void run() override;
void registerThreadInactive();
QWaitCondition runnableReady;
diff --git a/src/corelib/thread/qthreadpool.h b/src/corelib/thread/qthreadpool.h
index a65eacc996..606e192768 100644
--- a/src/corelib/thread/qthreadpool.h
+++ b/src/corelib/thread/qthreadpool.h
@@ -62,7 +62,7 @@ class Q_CORE_EXPORT QThreadPool : public QObject
friend class QFutureInterfaceBase;
public:
- QThreadPool(QObject *parent = Q_NULLPTR);
+ QThreadPool(QObject *parent = nullptr);
~QThreadPool();
static QThreadPool *globalInstance();
diff --git a/src/corelib/thread/qthreadstorage.cpp b/src/corelib/thread/qthreadstorage.cpp
index 2f77a9ce26..c0b523a431 100644
--- a/src/corelib/thread/qthreadstorage.cpp
+++ b/src/corelib/thread/qthreadstorage.cpp
@@ -260,13 +260,13 @@ void QThreadStorageData::finish(void **p)
*/
/*!
- \fn QThreadStorage::QThreadStorage()
+ \fn template <class T> QThreadStorage<T>::QThreadStorage()
Constructs a new per-thread data storage object.
*/
/*!
- \fn QThreadStorage::~QThreadStorage()
+ \fn template <class T> QThreadStorage<T>::~QThreadStorage()
Destroys the per-thread data storage object.
@@ -278,7 +278,7 @@ void QThreadStorageData::finish(void **p)
*/
/*!
- \fn bool QThreadStorage::hasLocalData() const
+ \fn template <class T> bool QThreadStorage<T>::hasLocalData() const
If T is a pointer type, returns \c true if the calling thread has
non-zero data available.
@@ -290,7 +290,7 @@ void QThreadStorageData::finish(void **p)
*/
/*!
- \fn T &QThreadStorage::localData()
+ \fn template <class T> T &QThreadStorage<T>::localData()
Returns a reference to the data that was set by the calling
thread.
@@ -302,7 +302,7 @@ void QThreadStorageData::finish(void **p)
*/
/*!
- \fn const T QThreadStorage::localData() const
+ \fn template <class T> const T QThreadStorage<T>::localData() const
\overload
Returns a copy of the data that was set by the calling thread.
@@ -311,7 +311,7 @@ void QThreadStorageData::finish(void **p)
*/
/*!
- \fn void QThreadStorage::setLocalData(T data)
+ \fn template <class T> void QThreadStorage<T>::setLocalData(T data)
Sets the local data for the calling thread to \a data. It can be
accessed later using the localData() functions.
diff --git a/src/corelib/thread/thread.pri b/src/corelib/thread/thread.pri
index 0a989cfcaf..e4972a57b3 100644
--- a/src/corelib/thread/thread.pri
+++ b/src/corelib/thread/thread.pri
@@ -10,30 +10,19 @@ HEADERS += thread/qmutex.h \
thread/qthreadstorage.h \
thread/qwaitcondition.h \
thread/qatomic.h \
- thread/qexception.h \
- thread/qresultstore.h \
- thread/qfuture.h \
- thread/qfutureinterface.h \
- thread/qfuturesynchronizer.h \
- thread/qfuturewatcher.h \
thread/qbasicatomic.h \
thread/qgenericatomic.h
# private headers
HEADERS += thread/qmutex_p.h \
thread/qmutexpool_p.h \
- thread/qfutureinterface_p.h \
- thread/qfuturewatcher_p.h \
+ thread/qfutex_p.h \
thread/qorderedmutexlocker_p.h \
thread/qreadwritelock_p.h \
thread/qthread_p.h \
thread/qthreadpool_p.h
SOURCES += thread/qatomic.cpp \
- thread/qexception.cpp \
- thread/qresultstore.cpp \
- thread/qfutureinterface.cpp \
- thread/qfuturewatcher.cpp \
thread/qmutex.cpp \
thread/qreadwritelock.cpp \
thread/qrunnable.cpp \
@@ -43,6 +32,24 @@ SOURCES += thread/qatomic.cpp \
thread/qthreadpool.cpp \
thread/qthreadstorage.cpp
+qtConfig(future) {
+ HEADERS += \
+ thread/qexception.h \
+ thread/qfuture.h \
+ thread/qfutureinterface.h \
+ thread/qfutureinterface_p.h \
+ thread/qfuturesynchronizer.h \
+ thread/qfuturewatcher.h \
+ thread/qfuturewatcher_p.h \
+ thread/qresultstore.h
+
+ SOURCES += \
+ thread/qexception.cpp \
+ thread/qfutureinterface.cpp \
+ thread/qfuturewatcher.cpp \
+ thread/qresultstore.cpp
+}
+
win32 {
SOURCES += \
thread/qmutex_win.cpp \