diff options
Diffstat (limited to 'src/corelib/thread')
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 *¤t) Q_DECL_NOTHROW { - return d_ptr.testAndSetAcquire(Q_NULLPTR, dummyLocked(), current); + return d_ptr.testAndSetAcquire(nullptr, dummyLocked(), current); } inline bool fastTryUnlock(QMutexData *¤t) 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 \ |