summaryrefslogtreecommitdiffstats
path: root/src/corelib/thread
diff options
context:
space:
mode:
authorOswald Buddenhagen <oswald.buddenhagen@digia.com>2014-02-19 10:06:25 +0100
committerOswald Buddenhagen <oswald.buddenhagen@digia.com>2014-02-19 10:06:25 +0100
commit30fd22b9574def54726e7b193127cc0c901c1b4c (patch)
tree96dfc923044db0515064ba39d052d9ed577e3e40 /src/corelib/thread
parentd7b0581c1c2ef60c08d238dae39298af6904918f (diff)
parent6aa09bbce59828d028f6d1e81d2bfc6ba537aae1 (diff)
Merge remote-tracking branch 'origin/dev' into stable
Diffstat (limited to 'src/corelib/thread')
-rw-r--r--src/corelib/thread/qatomic.cpp811
-rw-r--r--src/corelib/thread/qatomic.h71
-rw-r--r--src/corelib/thread/qbasicatomic.h126
-rw-r--r--src/corelib/thread/qgenericatomic.h160
-rw-r--r--src/corelib/thread/qmutex_win.cpp9
-rw-r--r--src/corelib/thread/qoldbasicatomic.h143
-rw-r--r--src/corelib/thread/qthread.cpp2
-rw-r--r--src/corelib/thread/qthread_p.h9
-rw-r--r--src/corelib/thread/qthread_win.cpp154
-rw-r--r--src/corelib/thread/qthreadpool.cpp28
-rw-r--r--src/corelib/thread/qthreadpool_p.h3
-rw-r--r--src/corelib/thread/qwaitcondition.h6
-rw-r--r--src/corelib/thread/qwaitcondition_win.cpp11
-rw-r--r--src/corelib/thread/thread.pri3
14 files changed, 1193 insertions, 343 deletions
diff --git a/src/corelib/thread/qatomic.cpp b/src/corelib/thread/qatomic.cpp
index 39d136c006..33e85c1505 100644
--- a/src/corelib/thread/qatomic.cpp
+++ b/src/corelib/thread/qatomic.cpp
@@ -39,20 +39,48 @@
**
****************************************************************************/
+#include "qatomic.h"
+
/*!
\class QAtomicInt
\inmodule QtCore
- \brief The QAtomicInt class provides platform-independent atomic operations on integers.
+ \brief The QAtomicInt class provides platform-independent atomic operations on int.
\since 4.4
+ This class is a equivalent to \c{QAtomicInteger<int>}. All other
+ functionality is equivalent. Please see that class for more information.
+
+ \sa QAtomicInteger, QAtomicPointer
+*/
+
+/*!
+ \class QAtomicInteger
+ \inmodule QtCore
+ \brief The QAtomicInteger class provides platform-independent atomic operations on integers.
\ingroup thread
For atomic operations on pointers, see the QAtomicPointer class.
An \e atomic operation is a complex operation that completes without interruption.
- The QAtomicInt class provides atomic reference counting, test-and-set, fetch-and-store,
+ The QAtomicInteger class provides atomic reference counting, test-and-set, fetch-and-store,
and fetch-and-add for integers.
+ The template parameter \c T must be a C++ integer type:
+ \list
+ \li 8-bit: char, signed char, unsigned char, qint8, quint8
+ \li 16-bit: short, unsigned short, qint16, quint16, char16_t (C++11)
+ \li 32-bit: int, unsigned int, qint32, quint32, char32_t (C++11)
+ \li 64-bit: long long, unsigned long long, qint64, quint64
+ \li platform-specific size: long, unsigned long
+ \li pointer size: qintptr, quintptr, qptrdiff
+ \endlist
+
+ Of the list above, only the 32-bit- and pointer-sized instantiations are guaranteed to
+ work on all platforms. Support for other sizes depends on the compiler and
+ processor architecture the code is being compiled for. To test whether the
+ other types are supported, check the macro \c Q_ATOMIC_INT\e{nn}_IS_SUPPORTED,
+ where \c{\e{nn}} is the number of bits desired.
+
\section1 The Atomic API
\section2 Reference counting
@@ -67,7 +95,7 @@
\section2 Memory ordering
- QAtomicInt provides several implementations of the atomic
+ QAtomicInteger provides several implementations of the atomic
test-and-set, fetch-and-store, and fetch-and-add functions. Each
implementation defines a memory ordering semantic that describes
how memory accesses surrounding the atomic instruction are
@@ -93,8 +121,8 @@
\section2 Test-and-set
- If the current value of the QAtomicInt is an expected value, the
- test-and-set functions assign a new value to the QAtomicInt and
+ If the current value of the QAtomicInteger is an expected value, the
+ test-and-set functions assign a new value to the QAtomicInteger and
return true. If values are \a not the same, these functions do
nothing and return false. This operation equates to the following
code:
@@ -109,7 +137,7 @@
\section2 Fetch-and-store
The atomic fetch-and-store functions read the current value of the
- QAtomicInt and then assign a new value, returning the original
+ QAtomicInteger and then assign a new value, returning the original
value. This operation equates to the following code:
\snippet code/src_corelib_thread_qatomic.cpp 2
@@ -122,7 +150,7 @@
\section2 Fetch-and-add
The atomic fetch-and-add functions read the current value of the
- QAtomicInt and then add the given value to the current value,
+ QAtomicInteger and then add the given value to the current value,
returning the original value. This operation equates to the
following code:
@@ -136,34 +164,35 @@
\section1 Feature Tests for the Atomic API
Providing a platform-independent atomic API that works on all
- processors is challenging. The API provided by QAtomicInt is
+ processors is challenging. The API provided by QAtomicInteger is
guaranteed to work atomically on all processors. However, since
not all processors implement support for every operation provided
- by QAtomicInt, it is necessary to expose information about the
+ by QAtomicInteger, it is necessary to expose information about the
processor.
You can check at compile time which features are supported on your
hardware using various macros. These will tell you if your
hardware always, sometimes, or does not support a particular
operation. The macros have the form
- Q_ATOMIC_INT_\e{OPERATION}_IS_\e{HOW}_NATIVE. \e{OPERATION}
+ Q_ATOMIC_INT\e{nn}_\e{OPERATION}_IS_\e{HOW}_NATIVE. \e{nn} is the
+ size of the integer (in bits), \e{OPERATION}
is one of REFERENCE_COUNTING, TEST_AND_SET,
FETCH_AND_STORE, or FETCH_AND_ADD, and \e{HOW} is one of
ALWAYS, SOMETIMES, or NOT. There will always be exactly one
defined macro per operation. For example, if
- Q_ATOMIC_INT_REFERENCE_COUNTING_IS_ALWAYS_NATIVE is defined,
+ Q_ATOMIC_INT32_REFERENCE_COUNTING_IS_ALWAYS_NATIVE is defined,
neither Q_ATOMIC_INT_REFERENCE_COUNTING_IS_SOMETIMES_NATIVE nor
- Q_ATOMIC_INT_REFERENCE_COUNTING_IS_NOT_NATIVE will be defined.
+ Q_ATOMIC_INT32_REFERENCE_COUNTING_IS_NOT_NATIVE will be defined.
An operation that completes in constant time is said to be
wait-free. Such operations are not implemented using locks or
loops of any kind. For atomic operations that are always
supported, and that are wait-free, Qt defines the
- Q_ATOMIC_INT_\e{OPERATION}_IS_WAIT_FREE in addition to the
- Q_ATOMIC_INT_\e{OPERATION}_IS_ALWAYS_NATIVE.
+ Q_ATOMIC_INT\e{nn}_\e{OPERATION}_IS_WAIT_FREE in addition to the
+ Q_ATOMIC_INT\e{nn}_\e{OPERATION}_IS_ALWAYS_NATIVE.
In cases where an atomic operation is only supported in newer
- generations of the processor, QAtomicInt also provides a way to
+ generations of the processor, QAtomicInteger also provides a way to
check at runtime what your hardware supports with the
isReferenceCountingNative(), isTestAndSetNative(),
isFetchAndStoreNative(), and isFetchAndAddNative()
@@ -171,32 +200,37 @@
isReferenceCountingWaitFree(), isTestAndSetWaitFree(),
isFetchAndStoreWaitFree(), and isFetchAndAddWaitFree() functions.
- Below is a complete list of all feature macros for QAtomicInt:
+ Below is a complete list of all feature macros for QAtomicInteger:
\list
- \li Q_ATOMIC_INT_REFERENCE_COUNTING_IS_ALWAYS_NATIVE
- \li Q_ATOMIC_INT_REFERENCE_COUNTING_IS_SOMETIMES_NATIVE
- \li Q_ATOMIC_INT_REFERENCE_COUNTING_IS_NOT_NATIVE
- \li Q_ATOMIC_INT_REFERENCE_COUNTING_IS_WAIT_FREE
+ \li Q_ATOMIC_INT\e{nn}_REFERENCE_COUNTING_IS_ALWAYS_NATIVE
+ \li Q_ATOMIC_INT\e{nn}_REFERENCE_COUNTING_IS_SOMETIMES_NATIVE
+ \li Q_ATOMIC_INT\e{nn}_REFERENCE_COUNTING_IS_NOT_NATIVE
+ \li Q_ATOMIC_INT\e{nn}_REFERENCE_COUNTING_IS_WAIT_FREE
- \li Q_ATOMIC_INT_TEST_AND_SET_IS_ALWAYS_NATIVE
- \li Q_ATOMIC_INT_TEST_AND_SET_IS_SOMETIMES_NATIVE
- \li Q_ATOMIC_INT_TEST_AND_SET_IS_NOT_NATIVE
- \li Q_ATOMIC_INT_TEST_AND_SET_IS_WAIT_FREE
+ \li Q_ATOMIC_INT\e{nn}_TEST_AND_SET_IS_ALWAYS_NATIVE
+ \li Q_ATOMIC_INT\e{nn}_TEST_AND_SET_IS_SOMETIMES_NATIVE
+ \li Q_ATOMIC_INT\e{nn}_TEST_AND_SET_IS_NOT_NATIVE
+ \li Q_ATOMIC_INT\e{nn}_TEST_AND_SET_IS_WAIT_FREE
- \li Q_ATOMIC_INT_FETCH_AND_STORE_IS_ALWAYS_NATIVE
- \li Q_ATOMIC_INT_FETCH_AND_STORE_IS_SOMETIMES_NATIVE
- \li Q_ATOMIC_INT_FETCH_AND_STORE_IS_NOT_NATIVE
- \li Q_ATOMIC_INT_FETCH_AND_STORE_IS_WAIT_FREE
+ \li Q_ATOMIC_INT\e{nn}_FETCH_AND_STORE_IS_ALWAYS_NATIVE
+ \li Q_ATOMIC_INT\e{nn}_FETCH_AND_STORE_IS_SOMETIMES_NATIVE
+ \li Q_ATOMIC_INT\e{nn}_FETCH_AND_STORE_IS_NOT_NATIVE
+ \li Q_ATOMIC_INT\e{nn}_FETCH_AND_STORE_IS_WAIT_FREE
- \li Q_ATOMIC_INT_FETCH_AND_ADD_IS_ALWAYS_NATIVE
- \li Q_ATOMIC_INT_FETCH_AND_ADD_IS_SOMETIMES_NATIVE
- \li Q_ATOMIC_INT_FETCH_AND_ADD_IS_NOT_NATIVE
- \li Q_ATOMIC_INT_FETCH_AND_ADD_IS_WAIT_FREE
+ \li Q_ATOMIC_INT\e{nn}_FETCH_AND_ADD_IS_ALWAYS_NATIVE
+ \li Q_ATOMIC_INT\e{nn}_FETCH_AND_ADD_IS_SOMETIMES_NATIVE
+ \li Q_ATOMIC_INT\e{nn}_FETCH_AND_ADD_IS_NOT_NATIVE
+ \li Q_ATOMIC_INT\e{nn}_FETCH_AND_ADD_IS_WAIT_FREE
\endlist
+ For compatibility with previous versions of Qt, macros with an empty \e{nn}
+ are equivalent to the 32-bit macros. For example,
+ Q_ATOMIC_INT_REFERENCE_COUNTING_IS_WAIT_FREE is the same as
+ Q_ATOMIC_INT32_REFERENCE_COUNTING_IS_WAIT_FREE.
+
\sa QAtomicPointer
*/
@@ -205,21 +239,27 @@
Constructs a QAtomicInt with the given \a value.
*/
-/*! \fn QAtomicInt::QAtomicInt(const QAtomicInt &other)
+/*! \fn QAtomicInteger::QAtomicInteger(T value)
+
+ Constructs a QAtomicInteger with the given \a value.
+*/
+
+/*! \fn QAtomicInteger::QAtomicInteger(const QAtomicInteger &other)
Constructs a copy of \a other.
*/
-/*! \fn QAtomicInt &QAtomicInt::operator=(const QAtomicInt &other)
+/*! \fn QAtomicInteger &QAtomicInteger::operator=(const QAtomicInteger &other)
- Assigns \a other to this QAtomicInt and returns a reference to
- this QAtomicInt.
+ Assigns \a other to this QAtomicInteger and returns a reference to
+ this QAtomicInteger.
*/
+
/*!
- \fn int QAtomicInt::load() const
+ \fn int QAtomicInteger::load() const
- Atomically loads the value of this QAtomicInt using relaxed memory
+ Atomically loads the value of this QAtomicInteger using relaxed memory
ordering. The value is not modified in any way, but note that there's no
guarantee that it remains so.
@@ -227,9 +267,9 @@
*/
/*!
- \fn int QAtomicInt::loadAcquire() const
+ \fn int QAtomicInteger::loadAcquire() const
- Atomically loads the value of this QAtomicInt using the "Acquire" memory
+ 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
guarantee that it remains so.
@@ -237,7 +277,7 @@
*/
/*!
- \fn void QAtomicInt::store(int newValue)
+ \fn void QAtomicInteger::store(int newValue)
Atomically stores the \a newValue value into this atomic type, using
relaxed memory ordering.
@@ -246,7 +286,7 @@
*/
/*!
- \fn void QAtomicInt::storeRelease(int newValue)
+ \fn void QAtomicInteger::storeRelease(int newValue)
Atomically stores the \a newValue value into this atomic type, using
the "Release" memory ordering.
@@ -254,376 +294,824 @@
\sa store(), load()
*/
-/*! \fn bool QAtomicInt::isReferenceCountingNative()
+/*!
+ \fn QAtomicInteger::operator int() const
+ \since 5.3
+
+ Atomically loads the value of this QAtomicInteger using a sequentially
+ consistent memory ordering if possible; or "Acquire" ordering if not. The
+ value is not modified in any way, but note that there's no guarantee that
+ it remains so.
+
+ \sa load(), loadAcquire()
+*/
+
+/*!
+ \fn QAtomicInteger &QAtomicInteger::operator=(int newValue)
+ \since 5.3
+
+ Atomically stores the \a newValue 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()
Returns \c true if reference counting is implemented using atomic
processor instructions, false otherwise.
*/
-/*! \fn bool QAtomicInt::isReferenceCountingWaitFree()
+/*! \fn bool QAtomicInteger::isReferenceCountingWaitFree()
Returns \c true if atomic reference counting is wait-free, false
otherwise.
*/
-/*! \fn bool QAtomicInt::ref()
- Atomically increments the value of this QAtomicInt. Returns \c true
+/*! \fn bool QAtomicInteger::ref()
+ Atomically increments the value of this QAtomicInteger. Returns \c true
if the new value is non-zero, false otherwise.
- This function uses \e ordered \l {QAtomicInt#Memory
+ This function uses \e ordered \l {QAtomicInteger#Memory
ordering}{memory ordering} semantics, which ensures that memory
access before and after the atomic operation (in program order)
may not be re-ordered.
- \sa deref()
+ \sa deref(), operator++()
+*/
+
+/*!
+ \fn int QAtomicInteger::operator++()
+ \since 5.3
+
+ Atomically pre-increments the value of this QAtomicInteger. Returns the new
+ value of this atomic.
+
+ This function uses a sequentially consistent memory ordering if possible;
+ or "Ordered" ordering if not.
+
+ \sa ref(), operator++(int), operator--()
*/
-/*! \fn bool QAtomicInt::deref()
- Atomically decrements the value of this QAtomicInt. Returns \c true
+/*!
+ \fn int QAtomicInteger::operator++(int)
+ \since 5.3
+
+ Atomically post-increments the value of this QAtomicInteger. Returns the old
+ value of this atomic.
+
+ This function uses a sequentially consistent memory ordering if possible;
+ or "Ordered" ordering if not.
+
+ \sa ref(), operator++(), operator--(int)
+*/
+
+/*! \fn bool QAtomicInteger::deref()
+ Atomically decrements the value of this QAtomicInteger. Returns \c true
if the new value is non-zero, false otherwise.
- This function uses \e ordered \l {QAtomicInt#Memory
+ This function uses \e ordered \l {QAtomicInteger#Memory
ordering}{memory ordering} semantics, which ensures that memory
access before and after the atomic operation (in program order)
may not be re-ordered.
- \sa ref()
+ \sa ref(), operator--()
+*/
+
+/*!
+ \fn int QAtomicInteger::operator--()
+ \since 5.3
+
+ Atomically pre-decrements the value of this QAtomicInteger. Returns the new
+ value of this atomic.
+
+ This function uses a sequentially consistent memory ordering if possible;
+ or "Ordered" ordering if not.
+
+ \sa deref(), operator--(int), operator++()
*/
-/*! \fn bool QAtomicInt::isTestAndSetNative()
+/*!
+ \fn int QAtomicInteger::operator--(int)
+ \since 5.3
+
+ Atomically post-decrements the value of this QAtomicInteger. Returns the old
+ value of this atomic.
+
+ This function uses a sequentially consistent memory ordering if possible;
+ or "Ordered" ordering if not.
+
+ \sa deref(), operator--(), operator++(int)
+*/
+
+/*! \fn bool QAtomicInteger::isTestAndSetNative()
Returns \c true if test-and-set is implemented using atomic processor
instructions, false otherwise.
*/
-/*! \fn bool QAtomicInt::isTestAndSetWaitFree()
+/*! \fn bool QAtomicInteger::isTestAndSetWaitFree()
Returns \c true if atomic test-and-set is wait-free, false otherwise.
*/
-/*! \fn bool QAtomicInt::testAndSetRelaxed(int expectedValue, int newValue)
+/*! \fn bool QAtomicInteger::testAndSetRelaxed(int expectedValue, int newValue)
Atomic test-and-set.
- If the current value of this QAtomicInt is the \a expectedValue,
+ If the current value of this QAtomicInteger is the \a expectedValue,
the test-and-set functions assign the \a newValue to this
- QAtomicInt and return true. If the values are \e not the same,
+ QAtomicInteger and return true. If the values are \e not the same,
this function does nothing and returns \c false.
- This function uses \e relaxed \l {QAtomicInt#Memory
+ This function uses \e relaxed \l {QAtomicInteger#Memory
ordering}{memory ordering} semantics, leaving the compiler and
processor to freely reorder memory accesses.
*/
-/*! \fn bool QAtomicInt::testAndSetAcquire(int expectedValue, int newValue)
+/*! \fn bool QAtomicInteger::testAndSetAcquire(int expectedValue, int newValue)
Atomic test-and-set.
- If the current value of this QAtomicInt is the \a expectedValue,
+ If the current value of this QAtomicInteger is the \a expectedValue,
the test-and-set functions assign the \a newValue to this
- QAtomicInt and return true. If the values are \e not the same,
+ QAtomicInteger and return true. If the values are \e not the same,
this function does nothing and returns \c false.
- This function uses \e acquire \l {QAtomicInt#Memory
+ This function uses \e acquire \l {QAtomicInteger#Memory
ordering}{memory ordering} semantics, which ensures that memory
access following the atomic operation (in program order) may not
be re-ordered before the atomic operation.
*/
-/*! \fn bool QAtomicInt::testAndSetRelease(int expectedValue, int newValue)
+/*! \fn bool QAtomicInteger::testAndSetRelease(int expectedValue, int newValue)
Atomic test-and-set.
- If the current value of this QAtomicInt is the \a expectedValue,
+ If the current value of this QAtomicInteger is the \a expectedValue,
the test-and-set functions assign the \a newValue to this
- QAtomicInt and return true. If the values are \e not the same,
+ QAtomicInteger and return true. If the values are \e not the same,
this function does nothing and returns \c false.
- This function uses \e release \l {QAtomicInt#Memory
+ This function uses \e release \l {QAtomicInteger#Memory
ordering}{memory ordering} semantics, which ensures that memory
access before the atomic operation (in program order) may not be
re-ordered after the atomic operation.
*/
-/*! \fn bool QAtomicInt::testAndSetOrdered(int expectedValue, int newValue)
+/*! \fn bool QAtomicInteger::testAndSetOrdered(int expectedValue, int newValue)
Atomic test-and-set.
- If the current value of this QAtomicInt is the \a expectedValue,
+ If the current value of this QAtomicInteger is the \a expectedValue,
the test-and-set functions assign the \a newValue to this
- QAtomicInt and return true. If the values are \e not the same,
+ QAtomicInteger and return true. If the values are \e not the same,
this function does nothing and returns \c false.
- This function uses \e ordered \l {QAtomicInt#Memory
+ This function uses \e ordered \l {QAtomicInteger#Memory
ordering}{memory ordering} semantics, which ensures that memory
access before and after the atomic operation (in program order)
may not be re-ordered.
*/
-/*! \fn bool QAtomicInt::isFetchAndStoreNative()
+/*! \fn bool QAtomicInteger::isFetchAndStoreNative()
Returns \c true if fetch-and-store is implemented using atomic
processor instructions, false otherwise.
*/
-/*! \fn bool QAtomicInt::isFetchAndStoreWaitFree()
+/*! \fn bool QAtomicInteger::isFetchAndStoreWaitFree()
Returns \c true if atomic fetch-and-store is wait-free, false
otherwise.
*/
-/*! \fn int QAtomicInt::fetchAndStoreRelaxed(int newValue)
+/*! \fn int QAtomicInteger::fetchAndStoreRelaxed(int newValue)
Atomic fetch-and-store.
- Reads the current value of this QAtomicInt and then assigns it the
+ Reads the current value of this QAtomicInteger and then assigns it the
\a newValue, returning the original value.
- This function uses \e relaxed \l {QAtomicInt#Memory
+ This function uses \e relaxed \l {QAtomicInteger#Memory
ordering}{memory ordering} semantics, leaving the compiler and
processor to freely reorder memory accesses.
*/
-/*! \fn int QAtomicInt::fetchAndStoreAcquire(int newValue)
+/*! \fn int QAtomicInteger::fetchAndStoreAcquire(int newValue)
Atomic fetch-and-store.
- Reads the current value of this QAtomicInt and then assigns it the
+ Reads the current value of this QAtomicInteger and then assigns it the
\a newValue, returning the original value.
- This function uses \e acquire \l {QAtomicInt#Memory
+ This function uses \e acquire \l {QAtomicInteger#Memory
ordering}{memory ordering} semantics, which ensures that memory
access following the atomic operation (in program order) may not
be re-ordered before the atomic operation.
*/
-/*! \fn int QAtomicInt::fetchAndStoreRelease(int newValue)
+/*! \fn int QAtomicInteger::fetchAndStoreRelease(int newValue)
Atomic fetch-and-store.
- Reads the current value of this QAtomicInt and then assigns it the
+ Reads the current value of this QAtomicInteger and then assigns it the
\a newValue, returning the original value.
- This function uses \e release \l {QAtomicInt#Memory
+ This function uses \e release \l {QAtomicInteger#Memory
ordering}{memory ordering} semantics, which ensures that memory
access before the atomic operation (in program order) may not be
re-ordered after the atomic operation.
*/
-/*! \fn int QAtomicInt::fetchAndStoreOrdered(int newValue)
+/*! \fn int QAtomicInteger::fetchAndStoreOrdered(int newValue)
Atomic fetch-and-store.
- Reads the current value of this QAtomicInt and then assigns it the
+ Reads the current value of this QAtomicInteger and then assigns it the
\a newValue, returning the original value.
- This function uses \e ordered \l {QAtomicInt#Memory
+ This function uses \e ordered \l {QAtomicInteger#Memory
ordering}{memory ordering} semantics, which ensures that memory
access before and after the atomic operation (in program order)
may not be re-ordered.
*/
-/*! \fn bool QAtomicInt::isFetchAndAddNative()
+/*! \fn bool QAtomicInteger::isFetchAndAddNative()
Returns \c true if fetch-and-add is implemented using atomic
processor instructions, false otherwise.
*/
-/*! \fn bool QAtomicInt::isFetchAndAddWaitFree()
+/*! \fn bool QAtomicInteger::isFetchAndAddWaitFree()
Returns \c true if atomic fetch-and-add is wait-free, false
otherwise.
*/
-/*! \fn int QAtomicInt::fetchAndAddRelaxed(int valueToAdd)
+/*! \fn int QAtomicInteger::fetchAndAddRelaxed(int valueToAdd)
Atomic fetch-and-add.
- Reads the current value of this QAtomicInt and then adds
+ Reads the current value of this QAtomicInteger and then adds
\a valueToAdd to the current value, returning the original value.
- This function uses \e relaxed \l {QAtomicInt#Memory
+ This function uses \e relaxed \l {QAtomicInteger#Memory
ordering}{memory ordering} semantics, leaving the compiler and
processor to freely reorder memory accesses.
+
+ \sa operator+=(), fetchAndSubRelaxed()
*/
-/*! \fn int QAtomicInt::fetchAndAddAcquire(int valueToAdd)
+/*! \fn int QAtomicInteger::fetchAndAddAcquire(int valueToAdd)
Atomic fetch-and-add.
- Reads the current value of this QAtomicInt and then adds
+ Reads the current value of this QAtomicInteger and then adds
\a valueToAdd to the current value, returning the original value.
- This function uses \e acquire \l {QAtomicInt#Memory
+ This function uses \e acquire \l {QAtomicInteger#Memory
ordering}{memory ordering} semantics, which ensures that memory
access following the atomic operation (in program order) may not
be re-ordered before the atomic operation.
+
+ \sa operator+=(), fetchAndSubAcquire()
*/
-/*! \fn int QAtomicInt::fetchAndAddRelease(int valueToAdd)
+/*! \fn int QAtomicInteger::fetchAndAddRelease(int valueToAdd)
Atomic fetch-and-add.
- Reads the current value of this QAtomicInt and then adds
+ Reads the current value of this QAtomicInteger and then adds
\a valueToAdd to the current value, returning the original value.
- This function uses \e release \l {QAtomicInt#Memory
+ This function uses \e release \l {QAtomicInteger#Memory
ordering}{memory ordering} semantics, which ensures that memory
access before the atomic operation (in program order) may not be
re-ordered after the atomic operation.
+
+ \sa operator+=(), fetchAndSubRelease()
*/
-/*! \fn int QAtomicInt::fetchAndAddOrdered(int valueToAdd)
+/*! \fn int QAtomicInteger::fetchAndAddOrdered(int valueToAdd)
Atomic fetch-and-add.
- Reads the current value of this QAtomicInt and then adds
+ Reads the current value of this QAtomicInteger and then adds
\a valueToAdd to the current value, returning the original value.
- This function uses \e ordered \l {QAtomicInt#Memory
+ This function uses \e ordered \l {QAtomicInteger#Memory
ordering}{memory ordering} semantics, which ensures that memory
access before and after the atomic operation (in program order)
may not be re-ordered.
+
+ \sa operator+=(), fetchAndSubOrdered()
+*/
+
+/*! \fn int QAtomicInteger::operator+=(int valueToAdd)
+ \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.
+
+ This function uses a sequentially consistent memory ordering if possible;
+ or "Ordered" ordering if not.
+
+ \sa fetchAndAddOrdered(), operator-=()
+*/
+
+/*! \fn int QAtomicInteger::fetchAndSubRelaxed(int valueToSub)
+ \since 5.3
+
+ Atomic fetch-and-sub.
+
+ Reads the current value of this QAtomicInteger and then subtracts
+ \a valueToSub to the current value, returning the original value.
+
+ This function uses \e relaxed \l {QAtomicInteger#Memory
+ ordering}{memory ordering} semantics, leaving the compiler and
+ processor to freely reorder memory accesses.
+
+ \sa operator-=(), fetchAndAddRelaxed()
+*/
+
+/*! \fn int QAtomicInteger::fetchAndSubAcquire(int valueToSub)
+ \since 5.3
+
+ Atomic fetch-and-sub.
+
+ Reads the current value of this QAtomicInteger and then subtracts
+ \a valueToSub to the current value, returning the original value.
+
+ This function uses \e acquire \l {QAtomicInteger#Memory
+ ordering}{memory ordering} semantics, which ensures that memory
+ access following the atomic operation (in program order) may not
+ be re-ordered before the atomic operation.
+
+ \sa operator-=(), fetchAndAddAcquire()
+*/
+
+/*! \fn int QAtomicInteger::fetchAndSubRelease(int valueToSub)
+ \since 5.3
+
+ Atomic fetch-and-sub.
+
+ Reads the current value of this QAtomicInteger and then subtracts
+ \a valueToSub to the current value, returning the original value.
+
+ This function uses \e release \l {QAtomicInteger#Memory
+ ordering}{memory ordering} semantics, which ensures that memory
+ access before the atomic operation (in program order) may not be
+ re-ordered after the atomic operation.
+
+ \sa operator-=(), fetchAndAddRelease()
+*/
+
+/*! \fn int QAtomicInteger::fetchAndSubOrdered(int valueToSub)
+ \since 5.3
+
+ Atomic fetch-and-sub.
+
+ Reads the current value of this QAtomicInteger and then subtracts
+ \a valueToSub to the current value, returning the original value.
+
+ This function uses \e ordered \l {QAtomicInteger#Memory
+ ordering}{memory ordering} semantics, which ensures that memory
+ access before and after the atomic operation (in program order)
+ may not be re-ordered.
+
+ \sa operator-=(), fetchAndAddOrdered()
+*/
+
+/*! \fn int QAtomicInteger::operator-=(int valueToSub)
+ \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.
+
+ This function uses a sequentially consistent memory ordering if possible;
+ or "Ordered" ordering if not.
+
+ \sa fetchAndSubOrdered(), operator+=()
+*/
+
+/*! \fn int QAtomicInteger::fetchAndOrRelaxed(int valueToOr)
+ \since 5.3
+
+ Atomic fetch-and-or.
+
+ Reads the current value of this QAtomicInteger and then bitwise-ORs
+ \a valueToOr to the current value, returning the original value.
+
+ This function uses \e relaxed \l {QAtomicInteger#Memory
+ ordering}{memory ordering} semantics, leaving the compiler and
+ processor to freely reorder memory accesses.
+
+ \sa operator|=()
+*/
+
+/*! \fn int QAtomicInteger::fetchAndOrAcquire(int valueToOr)
+ \since 5.3
+
+ Atomic fetch-and-or.
+
+ Reads the current value of this QAtomicInteger and then bitwise-ORs
+ \a valueToOr to the current value, returning the original value.
+
+ This function uses \e acquire \l {QAtomicInteger#Memory
+ ordering}{memory ordering} semantics, which ensures that memory
+ access following the atomic operation (in program order) may not
+ be re-ordered before the atomic operation.
+
+ \sa operator|=()
+*/
+
+/*! \fn int QAtomicInteger::fetchAndOrRelease(int valueToOr)
+ \since 5.3
+
+ Atomic fetch-and-or.
+
+ Reads the current value of this QAtomicInteger and then bitwise-ORs
+ \a valueToOr to the current value, returning the original value.
+
+ This function uses \e release \l {QAtomicInteger#Memory
+ ordering}{memory ordering} semantics, which ensures that memory
+ access before the atomic operation (in program order) may not be
+ re-ordered after the atomic operation.
+
+ \sa operator|=()
+*/
+
+/*! \fn int QAtomicInteger::fetchAndOrOrdered(int valueToOr)
+ \since 5.3
+
+ Atomic fetch-and-or.
+
+ Reads the current value of this QAtomicInteger and then bitwise-ORs
+ \a valueToOr to the current value, returning the original value.
+
+ This function uses \e ordered \l {QAtomicInteger#Memory
+ ordering}{memory ordering} semantics, which ensures that memory
+ access before and after the atomic operation (in program order)
+ may not be re-ordered.
+
+ \sa operator|=()
+*/
+
+/*! \fn int QAtomicInteger::operator|=(int valueToOr)
+ \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.
+
+ This function uses a sequentially consistent memory ordering if possible;
+ or "Ordered" ordering if not.
+
+ \sa fetchAndOrOrdered()
+*/
+
+/*! \fn int QAtomicInteger::fetchAndXorRelaxed(int valueToXor)
+ \since 5.3
+
+ Atomic fetch-and-xor.
+
+ Reads the current value of this QAtomicInteger and then bitwise-XORs
+ \a valueToXor to the current value, returning the original value.
+
+ This function uses \e relaxed \l {QAtomicInteger#Memory
+ ordering}{memory ordering} semantics, leaving the compiler and
+ processor to freely reorder memory accesses.
+
+ \sa operator^=()
+*/
+
+/*! \fn int QAtomicInteger::fetchAndXorAcquire(int valueToXor)
+ \since 5.3
+
+ Atomic fetch-and-xor.
+
+ Reads the current value of this QAtomicInteger and then bitwise-XORs
+ \a valueToXor to the current value, returning the original value.
+
+ This function uses \e acquire \l {QAtomicInteger#Memory
+ ordering}{memory ordering} semantics, which ensures that memory
+ access following the atomic operation (in program order) may not
+ be re-ordered before the atomic operation.
+
+ \sa operator^=()
+*/
+
+/*! \fn int QAtomicInteger::fetchAndXorRelease(int valueToXor)
+ \since 5.3
+
+ Atomic fetch-and-xor.
+
+ Reads the current value of this QAtomicInteger and then bitwise-XORs
+ \a valueToXor to the current value, returning the original value.
+
+ This function uses \e release \l {QAtomicInteger#Memory
+ ordering}{memory ordering} semantics, which ensures that memory
+ access before the atomic operation (in program order) may not be
+ re-ordered after the atomic operation.
+
+ \sa operator^=()
+*/
+
+/*! \fn int QAtomicInteger::fetchAndXorOrdered(int valueToXor)
+ \since 5.3
+
+ Atomic fetch-and-xor.
+
+ Reads the current value of this QAtomicInteger and then bitwise-XORs
+ \a valueToXor to the current value, returning the original value.
+
+ This function uses \e ordered \l {QAtomicInteger#Memory
+ ordering}{memory ordering} semantics, which ensures that memory
+ access before and after the atomic operation (in program order)
+ may not be re-ordered.
+
+ \sa operator^=()
+*/
+
+/*! \fn int QAtomicInteger::operator^=(int valueToXor)
+ \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.
+
+ This function uses a sequentially consistent memory ordering if possible;
+ or "Ordered" ordering if not.
+
+ \sa fetchAndXorOrdered()
+*/
+
+/*! \fn int QAtomicInteger::fetchAndAndRelaxed(int valueToAnd)
+ \since 5.3
+
+ Atomic fetch-and-and.
+
+ Reads the current value of this QAtomicInteger and then bitwise-ANDs
+ \a valueToAnd to the current value, returning the original value.
+
+ This function uses \e relaxed \l {QAtomicInteger#Memory
+ ordering}{memory ordering} semantics, leaving the compiler and
+ processor to freely reorder memory accesses.
+
+ \sa operator&=()
+*/
+
+/*! \fn int QAtomicInteger::fetchAndAndAcquire(int valueToAnd)
+ \since 5.3
+
+ Atomic fetch-and-and.
+
+ Reads the current value of this QAtomicInteger and then bitwise-ANDs
+ \a valueToAnd to the current value, returning the original value.
+
+ This function uses \e acquire \l {QAtomicInteger#Memory
+ ordering}{memory ordering} semantics, which ensures that memory
+ access following the atomic operation (in program order) may not
+ be re-ordered before the atomic operation.
+
+ \sa operator&=()
+*/
+
+/*! \fn int QAtomicInteger::fetchAndAndRelease(int valueToAnd)
+ \since 5.3
+
+ Atomic fetch-and-and.
+
+ Reads the current value of this QAtomicInteger and then bitwise-ANDs
+ \a valueToAnd to the current value, returning the original value.
+
+ This function uses \e release \l {QAtomicInteger#Memory
+ ordering}{memory ordering} semantics, which ensures that memory
+ access before the atomic operation (in program order) may not be
+ re-ordered after the atomic operation.
+
+ \sa operator&=()
+*/
+
+/*! \fn int QAtomicInteger::fetchAndAndOrdered(int valueToAnd)
+ \since 5.3
+
+ Atomic fetch-and-and.
+
+ Reads the current value of this QAtomicInteger and then bitwise-ANDs
+ \a valueToAnd to the current value, returning the original value.
+
+ This function uses \e ordered \l {QAtomicInteger#Memory
+ ordering}{memory ordering} semantics, which ensures that memory
+ access before and after the atomic operation (in program order)
+ may not be re-ordered.
+
+ \sa operator&=()
+*/
+
+/*! \fn int QAtomicInteger::operator&=(int valueToAnd)
+ \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.
+
+ This function uses a sequentially consistent memory ordering if possible;
+ or "Ordered" ordering if not.
+
+ \sa fetchAndAndOrdered()
*/
/*!
- \macro Q_ATOMIC_INT_REFERENCE_COUNTING_IS_ALWAYS_NATIVE
- \relates QAtomicInt
+ \macro Q_ATOMIC_INTnn_IS_SUPPORTED
+ \relates QAtomicInteger
+
+ This macro is defined if atomic integers of size \e{nn} (in bits) are
+ supported in this compiler / architecture combination.
+ Q_ATOMIC_INT32_IS_SUPPORTED is always defined.
+
+ \e{nn} is the size of the integer, in bits (8, 16, 32 or 64).
+*/
+
+/*!
+ \macro Q_ATOMIC_INTnn_REFERENCE_COUNTING_IS_ALWAYS_NATIVE
+ \relates QAtomicInteger
This macro is defined if and only if all generations of your
processor support atomic reference counting.
+
+ \e{nn} is the size of the integer, in bits (8, 16, 32 or 64).
*/
/*!
- \macro Q_ATOMIC_INT_REFERENCE_COUNTING_IS_SOMETIMES_NATIVE
- \relates QAtomicInt
+ \macro Q_ATOMIC_INTnn_REFERENCE_COUNTING_IS_SOMETIMES_NATIVE
+ \relates QAtomicInteger
This macro is defined when only certain generations of the
processor support atomic reference counting. Use the
- QAtomicInt::isReferenceCountingNative() function to check what
+ QAtomicInteger::isReferenceCountingNative() function to check what
your processor supports.
+
+ \e{nn} is the size of the integer, in bits (8, 16, 32 or 64).
*/
/*!
- \macro Q_ATOMIC_INT_REFERENCE_COUNTING_IS_NOT_NATIVE
- \relates QAtomicInt
+ \macro Q_ATOMIC_INTnn_REFERENCE_COUNTING_IS_NOT_NATIVE
+ \relates QAtomicInteger
This macro is defined when the hardware does not support atomic
reference counting.
+
+ \e{nn} is the size of the integer, in bits (8, 16, 32 or 64).
*/
/*!
- \macro Q_ATOMIC_INT_REFERENCE_COUNTING_IS_WAIT_FREE
- \relates QAtomicInt
+ \macro Q_ATOMIC_INTnn_REFERENCE_COUNTING_IS_WAIT_FREE
+ \relates QAtomicInteger
This macro is defined together with
- Q_ATOMIC_INT_REFERENCE_COUNTING_IS_ALWAYS_NATIVE to indicate that
+ Q_ATOMIC_INTnn_REFERENCE_COUNTING_IS_ALWAYS_NATIVE to indicate that
the reference counting is wait-free.
+
+ \e{nn} is the size of the integer, in bits (8, 16, 32 or 64).
*/
/*!
- \macro Q_ATOMIC_INT_TEST_AND_SET_IS_ALWAYS_NATIVE
- \relates QAtomicInt
+ \macro Q_ATOMIC_INTnn_TEST_AND_SET_IS_ALWAYS_NATIVE
+ \relates QAtomicInteger
This macro is defined if and only if your processor supports
atomic test-and-set on integers.
+
+ \e{nn} is the size of the integer, in bits (8, 16, 32 or 64).
*/
/*!
- \macro Q_ATOMIC_INT_TEST_AND_SET_IS_SOMETIMES_NATIVE
- \relates QAtomicInt
+ \macro Q_ATOMIC_INTnn_TEST_AND_SET_IS_SOMETIMES_NATIVE
+ \relates QAtomicInteger
This macro is defined when only certain generations of the
processor support atomic test-and-set on integers. Use the
- QAtomicInt::isTestAndSetNative() function to check what your
+ QAtomicInteger::isTestAndSetNative() function to check what your
processor supports.
+
+ \e{nn} is the size of the integer, in bits (8, 16, 32 or 64).
*/
/*!
- \macro Q_ATOMIC_INT_TEST_AND_SET_IS_NOT_NATIVE
- \relates QAtomicInt
+ \macro Q_ATOMIC_INTnn_TEST_AND_SET_IS_NOT_NATIVE
+ \relates QAtomicInteger
This macro is defined when the hardware does not support atomic
test-and-set on integers.
+
+ \e{nn} is the size of the integer, in bits (8, 16, 32 or 64).
*/
/*!
- \macro Q_ATOMIC_INT_TEST_AND_SET_IS_WAIT_FREE
- \relates QAtomicInt
+ \macro Q_ATOMIC_INTnn_TEST_AND_SET_IS_WAIT_FREE
+ \relates QAtomicInteger
This macro is defined together with
- Q_ATOMIC_INT_TEST_AND_SET_IS_ALWAYS_NATIVE to indicate that the
+ Q_ATOMIC_INTnn_TEST_AND_SET_IS_ALWAYS_NATIVE to indicate that the
atomic test-and-set on integers is wait-free.
+
+ \e{nn} is the size of the integer, in bits (8, 16, 32 or 64).
*/
/*!
- \macro Q_ATOMIC_INT_FETCH_AND_STORE_IS_ALWAYS_NATIVE
- \relates QAtomicInt
+ \macro Q_ATOMIC_INTnn_FETCH_AND_STORE_IS_ALWAYS_NATIVE
+ \relates QAtomicInteger
This macro is defined if and only if your processor supports
atomic fetch-and-store on integers.
+
+ \e{nn} is the size of the integer, in bits (8, 16, 32 or 64).
*/
/*!
- \macro Q_ATOMIC_INT_FETCH_AND_STORE_IS_SOMETIMES_NATIVE
- \relates QAtomicInt
+ \macro Q_ATOMIC_INTnn_FETCH_AND_STORE_IS_SOMETIMES_NATIVE
+ \relates QAtomicInteger
This macro is defined when only certain generations of the
processor support atomic fetch-and-store on integers. Use the
- QAtomicInt::isFetchAndStoreNative() function to check what your
+ QAtomicInteger::isFetchAndStoreNative() function to check what your
processor supports.
+
+ \e{nn} is the size of the integer, in bits (8, 16, 32 or 64).
*/
/*!
- \macro Q_ATOMIC_INT_FETCH_AND_STORE_IS_NOT_NATIVE
- \relates QAtomicInt
+ \macro Q_ATOMIC_INTnn_FETCH_AND_STORE_IS_NOT_NATIVE
+ \relates QAtomicInteger
This macro is defined when the hardware does not support atomic
fetch-and-store on integers.
+
+ \e{nn} is the size of the integer, in bits (8, 16, 32 or 64).
*/
/*!
- \macro Q_ATOMIC_INT_FETCH_AND_STORE_IS_WAIT_FREE
- \relates QAtomicInt
+ \macro Q_ATOMIC_INTnn_FETCH_AND_STORE_IS_WAIT_FREE
+ \relates QAtomicInteger
This macro is defined together with
- Q_ATOMIC_INT_FETCH_AND_STORE_IS_ALWAYS_NATIVE to indicate that the
+ Q_ATOMIC_INTnn_FETCH_AND_STORE_IS_ALWAYS_NATIVE to indicate that the
atomic fetch-and-store on integers is wait-free.
+
+ \e{nn} is the size of the integer, in bits (8, 16, 32 or 64).
*/
/*!
- \macro Q_ATOMIC_INT_FETCH_AND_ADD_IS_ALWAYS_NATIVE
- \relates QAtomicInt
+ \macro Q_ATOMIC_INTnn_FETCH_AND_ADD_IS_ALWAYS_NATIVE
+ \relates QAtomicInteger
This macro is defined if and only if your processor supports
atomic fetch-and-add on integers.
+
+ \e{nn} is the size of the integer, in bits (8, 16, 32 or 64).
*/
/*!
- \macro Q_ATOMIC_INT_FETCH_AND_ADD_IS_SOMETIMES_NATIVE
- \relates QAtomicInt
+ \macro Q_ATOMIC_INTnn_FETCH_AND_ADD_IS_SOMETIMES_NATIVE
+ \relates QAtomicInteger
This macro is defined when only certain generations of the
processor support atomic fetch-and-add on integers. Use the
- QAtomicInt::isFetchAndAddNative() function to check what your
+ QAtomicInteger::isFetchAndAddNative() function to check what your
processor supports.
+
+ \e{nn} is the size of the integer, in bits (8, 16, 32 or 64).
*/
/*!
- \macro Q_ATOMIC_INT_FETCH_AND_ADD_IS_NOT_NATIVE
- \relates QAtomicInt
+ \macro Q_ATOMIC_INTnn_FETCH_AND_ADD_IS_NOT_NATIVE
+ \relates QAtomicInteger
This macro is defined when the hardware does not support atomic
fetch-and-add on integers.
+
+ \e{nn} is the size of the integer, in bits (8, 16, 32 or 64).
*/
/*!
- \macro Q_ATOMIC_INT_FETCH_AND_ADD_IS_WAIT_FREE
- \relates QAtomicInt
+ \macro Q_ATOMIC_INTnn_FETCH_AND_ADD_IS_WAIT_FREE
+ \relates QAtomicInteger
This macro is defined together with
- Q_ATOMIC_INT_FETCH_AND_ADD_IS_ALWAYS_NATIVE to indicate that the
+ Q_ATOMIC_INTnn_FETCH_AND_ADD_IS_ALWAYS_NATIVE to indicate that the
atomic fetch-and-add on integers is wait-free.
+
+ \e{nn} is the size of the integer, in bits (8, 16, 32 or 64).
*/
@@ -637,7 +1125,7 @@
\ingroup thread
- For atomic operations on integers, see the QAtomicInt class.
+ For atomic operations on integers, see the QAtomicInteger class.
An \e atomic operation is a complex operation that completes without interruption.
The QAtomicPointer class provides atomic test-and-set, fetch-and-store, and fetch-and-add for pointers.
@@ -769,7 +1257,7 @@
\endlist
- \sa QAtomicInt
+ \sa QAtomicInteger
*/
/*! \fn QAtomicPointer::QAtomicPointer(T *value)
@@ -1126,3 +1614,46 @@
Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_ALWAYS_NATIVE to indicate that
the atomic fetch-and-add on pointers is wait-free.
*/
+
+// static checks
+#ifndef Q_ATOMIC_INT32_IS_SUPPORTED
+# error "Q_ATOMIC_INT32_IS_SUPPORTED must be defined"
+#endif
+#if !defined(Q_ATOMIC_INT64_IS_SUPPORTED) && QT_POINTER_SIZE == 8
+// 64-bit platform
+# error "Q_ATOMIC_INT64_IS_SUPPORTED must be defined on a 64-bit platform"
+#endif
+
+QT_BEGIN_NAMESPACE
+
+// The following specializations must always be defined
+Q_STATIC_ASSERT(sizeof(QAtomicInteger<unsigned>));
+Q_STATIC_ASSERT(sizeof(QAtomicInteger<long>));
+Q_STATIC_ASSERT(sizeof(QAtomicInteger<unsigned long>));
+Q_STATIC_ASSERT(sizeof(QAtomicInteger<quintptr>));
+Q_STATIC_ASSERT(sizeof(QAtomicInteger<qptrdiff>));
+#ifdef Q_COMPILER_UNICODE_STRINGS
+Q_STATIC_ASSERT(sizeof(QAtomicInteger<char32_t>));
+#endif
+
+#ifdef Q_ATOMIC_INT16_IS_SUPPORTED
+Q_STATIC_ASSERT(sizeof(QAtomicInteger<short>));
+Q_STATIC_ASSERT(sizeof(QAtomicInteger<unsigned short>));
+# if WCHAR_MAX < 0x10000
+Q_STATIC_ASSERT(sizeof(QAtomicInteger<wchar_t>));
+# endif
+# ifdef Q_COMPILER_UNICODE_STRINGS
+Q_STATIC_ASSERT(sizeof(QAtomicInteger<char16_t>));
+# endif
+#endif
+
+#ifdef Q_ATOMIC_INT64_IS_SUPPORTED
+Q_STATIC_ASSERT(sizeof(QAtomicInteger<qint64>));
+Q_STATIC_ASSERT(sizeof(QAtomicInteger<quint64>));
+#endif
+
+#if WCHAR_MAX == INT_MAX
+Q_STATIC_ASSERT(sizeof(QAtomicInteger<wchar_t>));
+#endif
+
+QT_END_NAMESPACE
diff --git a/src/corelib/thread/qatomic.h b/src/corelib/thread/qatomic.h
index 1ccaecc135..1faaa22d0f 100644
--- a/src/corelib/thread/qatomic.h
+++ b/src/corelib/thread/qatomic.h
@@ -55,27 +55,31 @@ QT_BEGIN_NAMESPACE
#endif
// High-level atomic integer operations
-class QAtomicInt : public QBasicAtomicInt
+template <typename T>
+class QAtomicInteger : public QBasicAtomicInteger<T>
{
public:
// Non-atomic API
-#ifdef Q_BASIC_ATOMIC_HAS_CONSTRUCTORS
- constexpr QAtomicInt(int value = 0) Q_DECL_NOTHROW : QBasicAtomicInt(value) {}
+#ifdef QT_BASIC_ATOMIC_HAS_CONSTRUCTORS
+ constexpr QAtomicInteger(T value = 0) Q_DECL_NOTHROW : QBasicAtomicInteger<T>(value) {}
#else
- inline QAtomicInt(int value = 0) Q_DECL_NOTHROW
+ inline QAtomicInteger(T value = 0) Q_DECL_NOTHROW
{
- _q_value = value;
+ this->_q_value = value;
}
#endif
- inline QAtomicInt(const QAtomicInt &other) Q_DECL_NOTHROW
+ inline QAtomicInteger(const QAtomicInteger &other) Q_DECL_NOTHROW
+#ifdef QT_BASIC_ATOMIC_HAS_CONSTRUCTORS
+ : QBasicAtomicInteger<T>()
+#endif
{
- store(other.load());
+ this->storeRelease(other.loadAcquire());
}
- inline QAtomicInt &operator=(const QAtomicInt &other) Q_DECL_NOTHROW
+ inline QAtomicInteger &operator=(const QAtomicInteger &other) Q_DECL_NOTHROW
{
- this->store(other.load());
+ this->storeRelease(other.loadAcquire());
return *this;
}
@@ -85,6 +89,9 @@ public:
void store(int newValue);
void storeRelease(int newValue);
+ operator int() const;
+ QAtomicInteger &operator=(int);
+
static Q_DECL_CONSTEXPR bool isReferenceCountingNative();
static Q_DECL_CONSTEXPR bool isReferenceCountingWaitFree();
@@ -114,7 +121,49 @@ public:
int fetchAndAddAcquire(int valueToAdd);
int fetchAndAddRelease(int valueToAdd);
int fetchAndAddOrdered(int valueToAdd);
+
+ int fetchAndSubRelaxed(int valueToSub);
+ int fetchAndSubAcquire(int valueToSub);
+ int fetchAndSubRelease(int valueToSub);
+ int fetchAndSubOrdered(int valueToSub);
+
+ int fetchAndOrRelaxed(int valueToOr);
+ int fetchAndOrAcquire(int valueToOr);
+ int fetchAndOrRelease(int valueToOr);
+ int fetchAndOrOrdered(int valueToOr);
+
+ int fetchAndAndRelaxed(int valueToAnd);
+ int fetchAndAndAcquire(int valueToAnd);
+ int fetchAndAndRelease(int valueToAnd);
+ int fetchAndAndOrdered(int valueToAnd);
+
+ int fetchAndXorRelaxed(int valueToXor);
+ int fetchAndXorAcquire(int valueToXor);
+ int fetchAndXorRelease(int valueToXor);
+ int fetchAndXorOrdered(int valueToXor);
+
+ int operator++();
+ int operator++(int);
+ int operator--();
+ int operator--(int);
+ int operator+=(int value);
+ int operator-=(int value);
+ int operator|=(int value);
+ int operator&=(int value);
+ int operator^=(int value);
+#endif
+};
+
+class QAtomicInt : public QAtomicInteger<int>
+{
+public:
+ // Non-atomic API
+ // We could use QT_COMPILER_INHERITING_CONSTRUCTORS, but we need only one;
+ // the implicit definition for all the others is fine.
+#ifdef QT_BASIC_ATOMIC_HAS_CONSTRUCTORS
+ constexpr
#endif
+ QAtomicInt(int value = 0) Q_DECL_NOTHROW : QAtomicInteger<int>(value) {}
};
// High-level atomic pointer operations
@@ -132,12 +181,12 @@ public:
#endif
inline QAtomicPointer(const QAtomicPointer<T> &other) Q_DECL_NOTHROW
{
- this->store(other.load());
+ this->storeRelease(other.loadAcquire());
}
inline QAtomicPointer<T> &operator=(const QAtomicPointer<T> &other) Q_DECL_NOTHROW
{
- this->store(other.load());
+ this->storeRelease(other.loadAcquire());
return *this;
}
diff --git a/src/corelib/thread/qbasicatomic.h b/src/corelib/thread/qbasicatomic.h
index 782ae90698..cf69d34589 100644
--- a/src/corelib/thread/qbasicatomic.h
+++ b/src/corelib/thread/qbasicatomic.h
@@ -51,33 +51,17 @@
#elif defined(Q_CC_MSVC)
# include <QtCore/qatomic_msvc.h>
-// Operating system dependent implementation
-#elif defined(Q_OS_INTEGRITY)
-# include "QtCore/qatomic_integrity.h"
-#elif defined(Q_OS_VXWORKS)
-# include "QtCore/qatomic_vxworks.h"
-
// Processor dependent implementation
-#elif defined(Q_PROCESSOR_ALPHA)
-# include "QtCore/qatomic_alpha.h"
#elif defined(Q_PROCESSOR_ARM_V7) && defined(Q_PROCESSOR_ARM_32)
# include "QtCore/qatomic_armv7.h"
#elif defined(Q_PROCESSOR_ARM_V6) && defined(Q_PROCESSOR_ARM_32)
# include "QtCore/qatomic_armv6.h"
#elif defined(Q_PROCESSOR_ARM_V5) && defined(Q_PROCESSOR_ARM_32)
# include "QtCore/qatomic_armv5.h"
-#elif defined(Q_PROCESSOR_BFIN)
-# include "QtCore/qatomic_bfin.h"
#elif defined(Q_PROCESSOR_IA64)
# include "QtCore/qatomic_ia64.h"
#elif defined(Q_PROCESSOR_MIPS)
# include "QtCore/qatomic_mips.h"
-#elif defined(Q_PROCESSOR_POWER)
-# include "QtCore/qatomic_power.h"
-#elif defined(Q_PROCESSOR_S390)
-# include "QtCore/qatomic_s390.h"
-#elif defined(Q_PROCESSOR_SH4A)
-# include "QtCore/qatomic_sh4a.h"
#elif defined(Q_PROCESSOR_SPARC)
# include "QtCore/qatomic_sparc.h"
#elif defined(Q_PROCESSOR_X86)
@@ -98,9 +82,6 @@
# error "Qt has not been ported to this platform"
#endif
-// Only include if the implementation has been ported to QAtomicOps
-#ifndef QOLDBASICATOMIC_H
-
QT_BEGIN_NAMESPACE
#if 0
@@ -133,7 +114,8 @@ class QBasicAtomicInteger
public:
typedef QAtomicOps<T> Ops;
// static check that this is a valid integer
- typedef char PermittedIntegerType[QAtomicIntegerTraits<T>::IsInteger ? 1 : -1];
+ Q_STATIC_ASSERT_X(QTypeInfo<T>::isIntegral, "template parameter is not an integral type");
+ Q_STATIC_ASSERT_X(QAtomicOpsSupport<sizeof(T)>::IsSupported, "template parameter is an integral of a size not supported on this platform");
typename Ops::Type _q_value;
@@ -144,6 +126,8 @@ public:
T loadAcquire() const Q_DECL_NOTHROW { return Ops::loadAcquire(_q_value); }
void storeRelease(T newValue) Q_DECL_NOTHROW { Ops::storeRelease(_q_value, newValue); }
+ operator T() const Q_DECL_NOTHROW { return loadAcquire(); }
+ T operator=(T newValue) Q_DECL_NOTHROW { storeRelease(newValue); return newValue; }
static Q_DECL_CONSTEXPR bool isReferenceCountingNative() Q_DECL_NOTHROW { return Ops::isReferenceCountingNative(); }
static Q_DECL_CONSTEXPR bool isReferenceCountingWaitFree() Q_DECL_NOTHROW { return Ops::isReferenceCountingWaitFree(); }
@@ -163,6 +147,15 @@ public:
bool testAndSetOrdered(T expectedValue, T newValue) Q_DECL_NOTHROW
{ return Ops::testAndSetOrdered(_q_value, expectedValue, newValue); }
+ bool testAndSetRelaxed(T expectedValue, T newValue, T &currentValue) Q_DECL_NOTHROW
+ { return Ops::testAndSetRelaxed(_q_value, expectedValue, newValue, &currentValue); }
+ bool testAndSetAcquire(T expectedValue, T newValue, T &currentValue) Q_DECL_NOTHROW
+ { return Ops::testAndSetAcquire(_q_value, expectedValue, newValue, &currentValue); }
+ bool testAndSetRelease(T expectedValue, T newValue, T &currentValue) Q_DECL_NOTHROW
+ { return Ops::testAndSetRelease(_q_value, expectedValue, newValue, &currentValue); }
+ bool testAndSetOrdered(T expectedValue, T newValue, T &currentValue) Q_DECL_NOTHROW
+ { return Ops::testAndSetOrdered(_q_value, expectedValue, newValue, &currentValue); }
+
static Q_DECL_CONSTEXPR bool isFetchAndStoreNative() Q_DECL_NOTHROW { return Ops::isFetchAndStoreNative(); }
static Q_DECL_CONSTEXPR bool isFetchAndStoreWaitFree() Q_DECL_NOTHROW { return Ops::isFetchAndStoreWaitFree(); }
@@ -187,6 +180,63 @@ public:
T fetchAndAddOrdered(T valueToAdd) Q_DECL_NOTHROW
{ return Ops::fetchAndAddOrdered(_q_value, valueToAdd); }
+ T fetchAndSubRelaxed(T valueToAdd) Q_DECL_NOTHROW
+ { return Ops::fetchAndSubRelaxed(_q_value, valueToAdd); }
+ T fetchAndSubAcquire(T valueToAdd) Q_DECL_NOTHROW
+ { return Ops::fetchAndSubAcquire(_q_value, valueToAdd); }
+ T fetchAndSubRelease(T valueToAdd) Q_DECL_NOTHROW
+ { return Ops::fetchAndSubRelease(_q_value, valueToAdd); }
+ T fetchAndSubOrdered(T valueToAdd) Q_DECL_NOTHROW
+ { return Ops::fetchAndSubOrdered(_q_value, valueToAdd); }
+
+ T fetchAndAndRelaxed(T valueToAdd) Q_DECL_NOTHROW
+ { return Ops::fetchAndAndRelaxed(_q_value, valueToAdd); }
+ T fetchAndAndAcquire(T valueToAdd) Q_DECL_NOTHROW
+ { return Ops::fetchAndAndAcquire(_q_value, valueToAdd); }
+ T fetchAndAndRelease(T valueToAdd) Q_DECL_NOTHROW
+ { return Ops::fetchAndAndRelease(_q_value, valueToAdd); }
+ T fetchAndAndOrdered(T valueToAdd) Q_DECL_NOTHROW
+ { return Ops::fetchAndAndOrdered(_q_value, valueToAdd); }
+
+ T fetchAndOrRelaxed(T valueToAdd) Q_DECL_NOTHROW
+ { return Ops::fetchAndOrRelaxed(_q_value, valueToAdd); }
+ T fetchAndOrAcquire(T valueToAdd) Q_DECL_NOTHROW
+ { return Ops::fetchAndOrAcquire(_q_value, valueToAdd); }
+ T fetchAndOrRelease(T valueToAdd) Q_DECL_NOTHROW
+ { return Ops::fetchAndOrRelease(_q_value, valueToAdd); }
+ T fetchAndOrOrdered(T valueToAdd) Q_DECL_NOTHROW
+ { return Ops::fetchAndOrOrdered(_q_value, valueToAdd); }
+
+ T fetchAndXorRelaxed(T valueToAdd) Q_DECL_NOTHROW
+ { return Ops::fetchAndXorRelaxed(_q_value, valueToAdd); }
+ T fetchAndXorAcquire(T valueToAdd) Q_DECL_NOTHROW
+ { return Ops::fetchAndXorAcquire(_q_value, valueToAdd); }
+ T fetchAndXorRelease(T valueToAdd) Q_DECL_NOTHROW
+ { return Ops::fetchAndXorRelease(_q_value, valueToAdd); }
+ T fetchAndXorOrdered(T valueToAdd) Q_DECL_NOTHROW
+ { return Ops::fetchAndXorOrdered(_q_value, valueToAdd); }
+
+ T operator++() Q_DECL_NOTHROW
+ { return fetchAndAddOrdered(1) + 1; }
+ T operator++(int) Q_DECL_NOTHROW
+ { return fetchAndAddOrdered(1); }
+ T operator--() Q_DECL_NOTHROW
+ { return fetchAndSubOrdered(1) - 1; }
+ T operator--(int) Q_DECL_NOTHROW
+ { return fetchAndSubOrdered(1); }
+
+ T operator+=(T v) Q_DECL_NOTHROW
+ { return fetchAndAddOrdered(v) + v; }
+ T operator-=(T v) Q_DECL_NOTHROW
+ { return fetchAndSubOrdered(v) - v; }
+ T operator&=(T v) Q_DECL_NOTHROW
+ { return fetchAndAndOrdered(v) & v; }
+ T operator|=(T v) Q_DECL_NOTHROW
+ { return fetchAndOrOrdered(v) | v; }
+ T operator^=(T v) Q_DECL_NOTHROW
+ { return fetchAndXorOrdered(v) ^ v; }
+
+
#ifdef QT_BASIC_ATOMIC_HAS_CONSTRUCTORS
QBasicAtomicInteger() = default;
constexpr QBasicAtomicInteger(T value) Q_DECL_NOTHROW : _q_value(value) {}
@@ -207,9 +257,10 @@ public:
AtomicType _q_value;
- // Non-atomic API
Type load() const Q_DECL_NOTHROW { return _q_value; }
void store(Type newValue) Q_DECL_NOTHROW { _q_value = newValue; }
+ operator Type() const Q_DECL_NOTHROW { return loadAcquire(); }
+ Type operator=(Type newValue) Q_DECL_NOTHROW { storeRelease(newValue); return newValue; }
// Atomic API, implemented in qatomic_XXX.h
Type loadAcquire() const Q_DECL_NOTHROW { return Ops::loadAcquire(_q_value); }
@@ -227,6 +278,15 @@ public:
bool testAndSetOrdered(Type expectedValue, Type newValue) Q_DECL_NOTHROW
{ return Ops::testAndSetOrdered(_q_value, expectedValue, newValue); }
+ bool testAndSetRelaxed(Type expectedValue, Type newValue, Type &currentValue) Q_DECL_NOTHROW
+ { return Ops::testAndSetRelaxed(_q_value, expectedValue, newValue, &currentValue); }
+ bool testAndSetAcquire(Type expectedValue, Type newValue, Type &currentValue) Q_DECL_NOTHROW
+ { return Ops::testAndSetAcquire(_q_value, expectedValue, newValue, &currentValue); }
+ bool testAndSetRelease(Type expectedValue, Type newValue, Type &currentValue) Q_DECL_NOTHROW
+ { return Ops::testAndSetRelease(_q_value, expectedValue, newValue, &currentValue); }
+ bool testAndSetOrdered(Type expectedValue, Type newValue, Type &currentValue) Q_DECL_NOTHROW
+ { return Ops::testAndSetOrdered(_q_value, expectedValue, newValue, &currentValue); }
+
static Q_DECL_CONSTEXPR bool isFetchAndStoreNative() Q_DECL_NOTHROW { return Ops::isFetchAndStoreNative(); }
static Q_DECL_CONSTEXPR bool isFetchAndStoreWaitFree() Q_DECL_NOTHROW { return Ops::isFetchAndStoreWaitFree(); }
@@ -251,6 +311,28 @@ public:
Type fetchAndAddOrdered(qptrdiff valueToAdd) Q_DECL_NOTHROW
{ return Ops::fetchAndAddOrdered(_q_value, valueToAdd); }
+ Type fetchAndSubRelaxed(qptrdiff valueToAdd) Q_DECL_NOTHROW
+ { return Ops::fetchAndSubRelaxed(_q_value, valueToAdd); }
+ Type fetchAndSubAcquire(qptrdiff valueToAdd) Q_DECL_NOTHROW
+ { return Ops::fetchAndSubAcquire(_q_value, valueToAdd); }
+ Type fetchAndSubRelease(qptrdiff valueToAdd) Q_DECL_NOTHROW
+ { return Ops::fetchAndSubRelease(_q_value, valueToAdd); }
+ Type fetchAndSubOrdered(qptrdiff valueToAdd) Q_DECL_NOTHROW
+ { return Ops::fetchAndSubOrdered(_q_value, valueToAdd); }
+
+ Type operator++() Q_DECL_NOTHROW
+ { return fetchAndAddOrdered(1) + 1; }
+ Type operator++(int) Q_DECL_NOTHROW
+ { return fetchAndAddOrdered(1); }
+ Type operator--() Q_DECL_NOTHROW
+ { return fetchAndSubOrdered(1) - 1; }
+ Type operator--(int) Q_DECL_NOTHROW
+ { return fetchAndSubOrdered(1); }
+ Type operator+=(qptrdiff valueToAdd) Q_DECL_NOTHROW
+ { return fetchAndAddOrdered(valueToAdd) + valueToAdd; }
+ Type operator-=(qptrdiff valueToSub) Q_DECL_NOTHROW
+ { return fetchAndSubOrdered(valueToSub) - valueToSub; }
+
#ifdef QT_BASIC_ATOMIC_HAS_CONSTRUCTORS
QBasicAtomicPointer() = default;
constexpr QBasicAtomicPointer(Type value) Q_DECL_NOTHROW : _q_value(value) {}
@@ -266,6 +348,4 @@ public:
QT_END_NAMESPACE
-#endif // QOLDBASICATOMIC_H
-
#endif // QBASICATOMIC_H
diff --git a/src/corelib/thread/qgenericatomic.h b/src/corelib/thread/qgenericatomic.h
index 3a213f6a25..0c66d45855 100644
--- a/src/corelib/thread/qgenericatomic.h
+++ b/src/corelib/thread/qgenericatomic.h
@@ -43,6 +43,7 @@
#define QGENERICATOMIC_H
#include <QtCore/qglobal.h>
+#include <QtCore/qtypeinfo.h>
QT_BEGIN_NAMESPACE
@@ -60,7 +61,8 @@ QT_END_NAMESPACE
#define always_inline
#endif
-template<typename T> struct QAtomicIntegerTraits { enum { IsInteger = 0 }; };
+template<int> struct QAtomicOpsSupport { enum { IsSupported = 0 }; };
+template<> struct QAtomicOpsSupport<4> { enum { IsSupported = 1 }; };
template <typename T> struct QAtomicAdditiveType
{
@@ -140,6 +142,8 @@ template <typename BaseClass> struct QGenericAtomicOps
static inline Q_DECL_CONSTEXPR bool isTestAndSetWaitFree() Q_DECL_NOTHROW;
template <typename T, typename X> static inline
bool testAndSetRelaxed(T &_q_value, X expectedValue, X newValue) Q_DECL_NOTHROW;
+ template <typename T, typename X> static inline
+ bool testAndSetRelaxed(T &_q_value, X expectedValue, X newValue, X *currentValue) Q_DECL_NOTHROW;
#endif
template <typename T, typename X> static inline always_inline
@@ -164,6 +168,28 @@ template <typename BaseClass> struct QGenericAtomicOps
return BaseClass::testAndSetRelaxed(_q_value, expectedValue, newValue);
}
+ template <typename T, typename X> static inline always_inline
+ bool testAndSetAcquire(T &_q_value, X expectedValue, X newValue, X *currentValue) Q_DECL_NOTHROW
+ {
+ bool tmp = BaseClass::testAndSetRelaxed(_q_value, expectedValue, newValue, currentValue);
+ BaseClass::acquireMemoryFence(_q_value);
+ return tmp;
+ }
+
+ template <typename T, typename X> static inline always_inline
+ bool testAndSetRelease(T &_q_value, X expectedValue, X newValue, X *currentValue) Q_DECL_NOTHROW
+ {
+ BaseClass::releaseMemoryFence(_q_value);
+ return BaseClass::testAndSetRelaxed(_q_value, expectedValue, newValue, currentValue);
+ }
+
+ template <typename T, typename X> static inline always_inline
+ bool testAndSetOrdered(T &_q_value, X expectedValue, X newValue, X *currentValue) Q_DECL_NOTHROW
+ {
+ BaseClass::orderedMemoryFence(_q_value);
+ return BaseClass::testAndSetRelaxed(_q_value, expectedValue, newValue, currentValue);
+ }
+
static inline Q_DECL_CONSTEXPR bool isFetchAndStoreNative() Q_DECL_NOTHROW { return false; }
static inline Q_DECL_CONSTEXPR bool isFetchAndStoreWaitFree() Q_DECL_NOTHROW { return false; }
@@ -234,6 +260,138 @@ template <typename BaseClass> struct QGenericAtomicOps
BaseClass::orderedMemoryFence(_q_value);
return BaseClass::fetchAndAddRelaxed(_q_value, valueToAdd);
}
+
+ template <typename T> static inline always_inline
+ T fetchAndSubRelaxed(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT operand) Q_DECL_NOTHROW
+ {
+ // implement fetchAndSub on top of testAndSet
+ Q_FOREVER {
+ T tmp = BaseClass::load(_q_value);
+ if (BaseClass::testAndSetRelaxed(_q_value, tmp, T(tmp - operand)))
+ return tmp;
+ }
+ }
+
+ template <typename T> static inline always_inline
+ T fetchAndSubAcquire(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT operand) Q_DECL_NOTHROW
+ {
+ T tmp = BaseClass::fetchAndSubRelaxed(_q_value, operand);
+ BaseClass::acquireMemoryFence(_q_value);
+ return tmp;
+ }
+
+ template <typename T> static inline always_inline
+ T fetchAndSubRelease(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT operand) Q_DECL_NOTHROW
+ {
+ BaseClass::releaseMemoryFence(_q_value);
+ return BaseClass::fetchAndSubRelaxed(_q_value, operand);
+ }
+
+ template <typename T> static inline always_inline
+ T fetchAndSubOrdered(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT operand) Q_DECL_NOTHROW
+ {
+ BaseClass::orderedMemoryFence(_q_value);
+ return BaseClass::fetchAndSubRelaxed(_q_value, operand);
+ }
+
+ template <typename T> static inline always_inline
+ T fetchAndAndRelaxed(T &_q_value, typename QtPrivate::QEnableIf<QTypeInfo<T>::isIntegral, T>::Type operand) Q_DECL_NOTHROW
+ {
+ // implement fetchAndAnd on top of testAndSet
+ Q_FOREVER {
+ T tmp = BaseClass::load(_q_value);
+ if (BaseClass::testAndSetRelaxed(_q_value, tmp, T(tmp & operand)))
+ return tmp;
+ }
+ }
+
+ template <typename T> static inline always_inline
+ T fetchAndAndAcquire(T &_q_value, typename QtPrivate::QEnableIf<QTypeInfo<T>::isIntegral, T>::Type operand) Q_DECL_NOTHROW
+ {
+ T tmp = BaseClass::fetchAndAndRelaxed(_q_value, operand);
+ BaseClass::acquireMemoryFence(_q_value);
+ return tmp;
+ }
+
+ template <typename T> static inline always_inline
+ T fetchAndAndRelease(T &_q_value, typename QtPrivate::QEnableIf<QTypeInfo<T>::isIntegral, T>::Type operand) Q_DECL_NOTHROW
+ {
+ BaseClass::releaseMemoryFence(_q_value);
+ return BaseClass::fetchAndAndRelaxed(_q_value, operand);
+ }
+
+ template <typename T> static inline always_inline
+ T fetchAndAndOrdered(T &_q_value, typename QtPrivate::QEnableIf<QTypeInfo<T>::isIntegral, T>::Type operand) Q_DECL_NOTHROW
+ {
+ BaseClass::orderedMemoryFence(_q_value);
+ return BaseClass::fetchAndAndRelaxed(_q_value, operand);
+ }
+
+ template <typename T> static inline always_inline
+ T fetchAndOrRelaxed(T &_q_value, typename QtPrivate::QEnableIf<QTypeInfo<T>::isIntegral, T>::Type operand) Q_DECL_NOTHROW
+ {
+ // implement fetchAndOr on top of testAndSet
+ Q_FOREVER {
+ T tmp = BaseClass::load(_q_value);
+ if (BaseClass::testAndSetRelaxed(_q_value, tmp, T(tmp | operand)))
+ return tmp;
+ }
+ }
+
+ template <typename T> static inline always_inline
+ T fetchAndOrAcquire(T &_q_value, typename QtPrivate::QEnableIf<QTypeInfo<T>::isIntegral, T>::Type operand) Q_DECL_NOTHROW
+ {
+ T tmp = BaseClass::fetchAndOrRelaxed(_q_value, operand);
+ BaseClass::acquireMemoryFence(_q_value);
+ return tmp;
+ }
+
+ template <typename T> static inline always_inline
+ T fetchAndOrRelease(T &_q_value, typename QtPrivate::QEnableIf<QTypeInfo<T>::isIntegral, T>::Type operand) Q_DECL_NOTHROW
+ {
+ BaseClass::releaseMemoryFence(_q_value);
+ return BaseClass::fetchAndOrRelaxed(_q_value, operand);
+ }
+
+ template <typename T> static inline always_inline
+ T fetchAndOrOrdered(T &_q_value, typename QtPrivate::QEnableIf<QTypeInfo<T>::isIntegral, T>::Type operand) Q_DECL_NOTHROW
+ {
+ BaseClass::orderedMemoryFence(_q_value);
+ return BaseClass::fetchAndOrRelaxed(_q_value, operand);
+ }
+
+ template <typename T> static inline always_inline
+ T fetchAndXorRelaxed(T &_q_value, typename QtPrivate::QEnableIf<QTypeInfo<T>::isIntegral, T>::Type operand) Q_DECL_NOTHROW
+ {
+ // implement fetchAndXor on top of testAndSet
+ Q_FOREVER {
+ T tmp = BaseClass::load(_q_value);
+ if (BaseClass::testAndSetRelaxed(_q_value, tmp, T(tmp ^ operand)))
+ return tmp;
+ }
+ }
+
+ template <typename T> static inline always_inline
+ T fetchAndXorAcquire(T &_q_value, typename QtPrivate::QEnableIf<QTypeInfo<T>::isIntegral, T>::Type operand) Q_DECL_NOTHROW
+ {
+ T tmp = BaseClass::fetchAndXorRelaxed(_q_value, operand);
+ BaseClass::acquireMemoryFence(_q_value);
+ return tmp;
+ }
+
+ template <typename T> static inline always_inline
+ T fetchAndXorRelease(T &_q_value, typename QtPrivate::QEnableIf<QTypeInfo<T>::isIntegral, T>::Type operand) Q_DECL_NOTHROW
+ {
+ BaseClass::releaseMemoryFence(_q_value);
+ return BaseClass::fetchAndXorRelaxed(_q_value, operand);
+ }
+
+ template <typename T> static inline always_inline
+ T fetchAndXorOrdered(T &_q_value, typename QtPrivate::QEnableIf<QTypeInfo<T>::isIntegral, T>::Type operand) Q_DECL_NOTHROW
+ {
+ BaseClass::orderedMemoryFence(_q_value);
+ return BaseClass::fetchAndXorRelaxed(_q_value, operand);
+ }
};
#undef always_inline
diff --git a/src/corelib/thread/qmutex_win.cpp b/src/corelib/thread/qmutex_win.cpp
index 14b7f34008..a8cdf85fb6 100644
--- a/src/corelib/thread/qmutex_win.cpp
+++ b/src/corelib/thread/qmutex_win.cpp
@@ -48,7 +48,12 @@ QT_BEGIN_NAMESPACE
QMutexPrivate::QMutexPrivate()
{
+#ifndef Q_OS_WINRT
event = CreateEvent(0, FALSE, FALSE, 0);
+#else
+ event = CreateEventEx(0, NULL, 0, EVENT_ALL_ACCESS);
+#endif
+
if (!event)
qWarning("QMutexData::QMutexData: Cannot create event");
}
@@ -58,7 +63,11 @@ QMutexPrivate::~QMutexPrivate()
bool QMutexPrivate::wait(int timeout)
{
+#ifndef Q_OS_WINRT
return (WaitForSingleObject(event, timeout < 0 ? INFINITE : timeout) == WAIT_OBJECT_0);
+#else
+ return (WaitForSingleObjectEx(event, timeout < 0 ? INFINITE : timeout, FALSE) == WAIT_OBJECT_0);
+#endif
}
void QMutexPrivate::wakeUp() Q_DECL_NOTHROW
diff --git a/src/corelib/thread/qoldbasicatomic.h b/src/corelib/thread/qoldbasicatomic.h
deleted file mode 100644
index b755256ff7..0000000000
--- a/src/corelib/thread/qoldbasicatomic.h
+++ /dev/null
@@ -1,143 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** 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 Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QOLDBASICATOMIC_H
-#define QOLDBASICATOMIC_H
-
-#include <QtCore/qglobal.h>
-
-QT_BEGIN_NAMESPACE
-
-
-#if 0
-// silence syncqt warnings
-QT_END_NAMESPACE
-#pragma qt_sync_skip_header_check
-#pragma qt_no_master_include
-#pragma qt_sync_stop_processing
-#endif
-
-class Q_CORE_EXPORT QBasicAtomicInt
-{
-public:
- volatile int _q_value;
-
- // Atomic API, implemented in qatomic_XXX.h
-
- int load() const { return _q_value; }
- int loadAcquire() { return _q_value; }
- void store(int newValue) { _q_value = newValue; }
- void storeRelease(int newValue) { _q_value = newValue; }
-
- static bool isReferenceCountingNative();
- static bool isReferenceCountingWaitFree();
-
- bool ref();
- bool deref();
-
- static bool isTestAndSetNative();
- static bool isTestAndSetWaitFree();
-
- bool testAndSetRelaxed(int expectedValue, int newValue);
- bool testAndSetAcquire(int expectedValue, int newValue);
- bool testAndSetRelease(int expectedValue, int newValue);
- bool testAndSetOrdered(int expectedValue, int newValue);
-
- static bool isFetchAndStoreNative();
- static bool isFetchAndStoreWaitFree();
-
- int fetchAndStoreRelaxed(int newValue);
- int fetchAndStoreAcquire(int newValue);
- int fetchAndStoreRelease(int newValue);
- int fetchAndStoreOrdered(int newValue);
-
- static bool isFetchAndAddNative();
- static bool isFetchAndAddWaitFree();
-
- int fetchAndAddRelaxed(int valueToAdd);
- int fetchAndAddAcquire(int valueToAdd);
- int fetchAndAddRelease(int valueToAdd);
- int fetchAndAddOrdered(int valueToAdd);
-};
-
-template <typename T>
-class QBasicAtomicPointer
-{
-public:
- T * volatile _q_value;
-
- // Atomic API, implemented in qatomic_XXX.h
-
- T *load() const { return _q_value; }
- T *loadAcquire() { return _q_value; }
- void store(T *newValue) { _q_value = newValue; }
- void storeRelease(T *newValue) { _q_value = newValue; }
-
- static bool isTestAndSetNative();
- static bool isTestAndSetWaitFree();
-
- bool testAndSetRelaxed(T *expectedValue, T *newValue);
- bool testAndSetAcquire(T *expectedValue, T *newValue);
- bool testAndSetRelease(T *expectedValue, T *newValue);
- bool testAndSetOrdered(T *expectedValue, T *newValue);
-
- static bool isFetchAndStoreNative();
- static bool isFetchAndStoreWaitFree();
-
- T *fetchAndStoreRelaxed(T *newValue);
- T *fetchAndStoreAcquire(T *newValue);
- T *fetchAndStoreRelease(T *newValue);
- T *fetchAndStoreOrdered(T *newValue);
-
- static bool isFetchAndAddNative();
- static bool isFetchAndAddWaitFree();
-
- T *fetchAndAddRelaxed(qptrdiff valueToAdd);
- T *fetchAndAddAcquire(qptrdiff valueToAdd);
- T *fetchAndAddRelease(qptrdiff valueToAdd);
- T *fetchAndAddOrdered(qptrdiff valueToAdd);
-};
-
-#define Q_BASIC_ATOMIC_INITIALIZER(a) { (a) }
-
-QT_END_NAMESPACE
-
-#endif // QOLDBASICATOMIC_H
diff --git a/src/corelib/thread/qthread.cpp b/src/corelib/thread/qthread.cpp
index 50ccca9eda..adad4b81a1 100644
--- a/src/corelib/thread/qthread.cpp
+++ b/src/corelib/thread/qthread.cpp
@@ -154,7 +154,9 @@ QThreadPrivate::QThreadPrivate(QThreadData *d)
thread_id = 0;
#elif defined (Q_OS_WIN)
handle = 0;
+# ifndef Q_OS_WINRT
id = 0;
+# endif
waiters = 0;
#endif
#if defined (Q_OS_WIN)
diff --git a/src/corelib/thread/qthread_p.h b/src/corelib/thread/qthread_p.h
index fce84e881b..e2951b125f 100644
--- a/src/corelib/thread/qthread_p.h
+++ b/src/corelib/thread/qthread_p.h
@@ -66,6 +66,10 @@
#include <algorithm>
+#ifdef Q_OS_WINRT
+#include <thread>
+#endif
+
QT_BEGIN_NAMESPACE
class QAbstractEventDispatcher;
@@ -173,8 +177,13 @@ public:
static unsigned int __stdcall start(void *);
static void finish(void *, bool lockAnyway=true);
+# ifndef Q_OS_WINRT
Qt::HANDLE handle;
unsigned int id;
+# else
+ std::thread *handle;
+ std::thread::id id;
+# endif
int waiters;
bool terminationEnabled, terminatePending;
# endif
diff --git a/src/corelib/thread/qthread_win.cpp b/src/corelib/thread/qthread_win.cpp
index 865b1e6af5..db5c13157c 100644
--- a/src/corelib/thread/qthread_win.cpp
+++ b/src/corelib/thread/qthread_win.cpp
@@ -40,7 +40,7 @@
****************************************************************************/
//#define WINVER 0x0500
-#if _WIN32_WINNT < 0x0400
+#if (_WIN32_WINNT < 0x0400) && !defined(Q_OS_WINRT)
#define _WIN32_WINNT 0x0400
#endif
@@ -54,10 +54,17 @@
#include <qpointer.h>
#include <private/qcoreapplication_p.h>
+#ifdef Q_OS_WINRT
+#include <private/qeventdispatcher_winrt_p.h>
+#else
#include <private/qeventdispatcher_win_p.h>
+#endif
#include <qt_windows.h>
+#ifdef Q_OS_WINRT
+#include <thread>
+#endif
#ifndef Q_OS_WINCE
#ifndef _MT
@@ -71,6 +78,7 @@
#ifndef QT_NO_THREAD
QT_BEGIN_NAMESPACE
+#ifndef Q_OS_WINRT
void qt_watch_adopted_thread(const HANDLE adoptedThreadHandle, QThread *qthread);
DWORD WINAPI qt_adopted_thread_watcher_function(LPVOID);
@@ -92,6 +100,38 @@ static void qt_free_tls()
}
}
Q_DESTRUCTOR_FUNCTION(qt_free_tls)
+#else // !Q_OS_WINRT
+
+__declspec(thread) static QThreadData* qt_current_thread_data_tls_index = 0;
+void qt_create_tls()
+{
+}
+
+static void qt_free_tls()
+{
+ if (qt_current_thread_data_tls_index) {
+ qt_current_thread_data_tls_index->deref();
+ qt_current_thread_data_tls_index = 0;
+ }
+}
+
+QThreadData* TlsGetValue(QThreadData*& tls)
+{
+ Q_ASSERT(tls == qt_current_thread_data_tls_index);
+ return tls;
+}
+
+void TlsSetValue(QThreadData*& tls, QThreadData* data)
+{
+ Q_ASSERT(tls == qt_current_thread_data_tls_index);
+ if (tls)
+ tls->deref();
+ tls = data;
+ if (tls)
+ tls->ref();
+}
+Q_DESTRUCTOR_FUNCTION(qt_free_tls)
+#endif // Q_OS_WINRT
/*
QThreadData
@@ -124,6 +164,9 @@ QThreadData *QThreadData::current(bool createIfNecessary)
if (!QCoreApplicationPrivate::theMainThread) {
QCoreApplicationPrivate::theMainThread = threadData->thread;
+#ifndef Q_OS_WINRT
+ // TODO: is there a way to reflect the branch's behavior using
+ // WinRT API?
} else {
HANDLE realHandle = INVALID_HANDLE_VALUE;
#if !defined(Q_OS_WINCE) || (defined(_WIN32_WCE) && (_WIN32_WCE>=0x600))
@@ -138,6 +181,7 @@ QThreadData *QThreadData::current(bool createIfNecessary)
realHandle = reinterpret_cast<HANDLE>(GetCurrentThreadId());
#endif
qt_watch_adopted_thread(realHandle, threadData->thread);
+#endif // !Q_OS_WINRT
}
}
return threadData;
@@ -145,10 +189,16 @@ QThreadData *QThreadData::current(bool createIfNecessary)
void QAdoptedThread::init()
{
+#ifndef Q_OS_WINRT
d_func()->handle = GetCurrentThread();
d_func()->id = GetCurrentThreadId();
+#else
+ d_func()->handle = nullptr;
+ d_func()->id = std::this_thread::get_id();
+#endif
}
+#ifndef Q_OS_WINRT
static QVector<HANDLE> qt_adopted_thread_handles;
static QVector<QThread *> qt_adopted_qthreads;
static QMutex qt_adopted_thread_watcher_mutex;
@@ -301,6 +351,7 @@ void qt_set_thread_name(HANDLE threadId, LPCSTR threadName)
}
}
#endif // !QT_NO_DEBUG && Q_CC_MSVC && !Q_OS_WINCE
+#endif // !Q_OS_WINRT
/**************************************************************************
** QThreadPrivate
@@ -310,7 +361,11 @@ void qt_set_thread_name(HANDLE threadId, LPCSTR threadName)
void QThreadPrivate::createEventDispatcher(QThreadData *data)
{
+#ifdef Q_OS_WINRT
+ QEventDispatcherWinRT *theEventDispatcher = new QEventDispatcherWinRT;
+#else
QEventDispatcherWin32 *theEventDispatcher = new QEventDispatcherWin32;
+#endif
data->eventDispatcher.storeRelease(theEventDispatcher);
theEventDispatcher->startingUp();
}
@@ -338,7 +393,7 @@ unsigned int __stdcall QT_ENSURE_STACK_ALIGNED_FOR_SSE QThreadPrivate::start(voi
else
createEventDispatcher(data);
-#if !defined(QT_NO_DEBUG) && defined(Q_CC_MSVC) && !defined(Q_OS_WINCE)
+#if !defined(QT_NO_DEBUG) && defined(Q_CC_MSVC) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT)
// sets the name of the current thread.
QByteArray objectName = thr->objectName().toLocal8Bit();
qt_set_thread_name((HANDLE)-1,
@@ -384,11 +439,20 @@ void QThreadPrivate::finish(void *arg, bool lockAnyway)
d->interruptionRequested = false;
if (!d->waiters) {
+#ifndef Q_OS_WINRT
CloseHandle(d->handle);
+#else
+ d->handle->detach();
+ delete d->handle;
+#endif
d->handle = 0;
}
+#ifndef Q_OS_WINRT
d->id = 0;
+#else
+ d->id = std::thread::id();
+#endif
}
@@ -404,10 +468,15 @@ Qt::HANDLE QThread::currentThreadId() Q_DECL_NOTHROW
int QThread::idealThreadCount() Q_DECL_NOTHROW
{
SYSTEM_INFO sysinfo;
+#ifndef Q_OS_WINRT
GetSystemInfo(&sysinfo);
+#else
+ GetNativeSystemInfo(&sysinfo);
+#endif
return sysinfo.dwNumberOfProcessors;
}
+#ifndef Q_OS_WINRT
void QThread::yieldCurrentThread()
{
#ifndef Q_OS_WINCE
@@ -431,7 +500,28 @@ void QThread::usleep(unsigned long usecs)
{
::Sleep((usecs / 1000) + 1);
}
+#else // !Q_OS_WINRT
+
+void QThread::yieldCurrentThread()
+{
+ std::this_thread::yield();
+}
+void QThread::sleep(unsigned long secs)
+{
+ std::this_thread::sleep_for(std::chrono::seconds(secs));
+}
+
+void QThread::msleep(unsigned long msecs)
+{
+ std::this_thread::sleep_for(std::chrono::milliseconds(msecs));
+}
+
+void QThread::usleep(unsigned long usecs)
+{
+ std::this_thread::sleep_for(std::chrono::microseconds(usecs));
+}
+#endif // Q_OS_WINRT
void QThread::start(Priority priority)
{
@@ -453,6 +543,7 @@ void QThread::start(Priority priority)
d->returnCode = 0;
d->interruptionRequested = false;
+#ifndef Q_OS_WINRT
/*
NOTE: we create the thread in the suspended state, set the
priority and then resume the thread.
@@ -517,6 +608,23 @@ void QThread::start(Priority priority)
if (ResumeThread(d->handle) == (DWORD) -1) {
qErrnoWarning("QThread::start: Failed to resume new thread");
}
+#else // !Q_OS_WINRT
+ d->handle = new std::thread(QThreadPrivate::start, this);
+
+ if (!d->handle) {
+ qErrnoWarning(errno, "QThread::start: Failed to create thread");
+ d->running = false;
+ d->finished = true;
+ return;
+ }
+
+ d->id = d->handle->get_id();
+
+ if (priority != NormalPriority || priority != InheritPriority) {
+ qWarning("QThread::start: Failed to set thread priority (not implemented)");
+ d->priority = NormalPriority;
+ }
+#endif // Q_OS_WINRT
}
void QThread::terminate()
@@ -529,7 +637,12 @@ void QThread::terminate()
d->terminatePending = true;
return;
}
+
+#ifndef Q_OS_WINRT
TerminateThread(d->handle, 0);
+#else // !Q_OS_WINRT
+ qWarning("QThread::terminate: Terminate is not supported on WinRT");
+#endif // Q_OS_WINRT
QThreadPrivate::finish(this, false);
}
@@ -538,7 +651,11 @@ bool QThread::wait(unsigned long time)
Q_D(QThread);
QMutexLocker locker(&d->mutex);
+#ifndef Q_OS_WINRT
if (d->id == GetCurrentThreadId()) {
+#else
+ if (d->id == std::this_thread::get_id()) {
+#endif
qWarning("QThread::wait: Thread tried to wait on itself");
return false;
}
@@ -549,6 +666,7 @@ bool QThread::wait(unsigned long time)
locker.mutex()->unlock();
bool ret = false;
+#ifndef Q_OS_WINRT
switch (WaitForSingleObject(d->handle, time)) {
case WAIT_OBJECT_0:
ret = true;
@@ -561,6 +679,24 @@ bool QThread::wait(unsigned long time)
default:
break;
}
+#else // !Q_OS_WINRT
+ if (d->handle->joinable()) {
+ HANDLE handle = d->handle->native_handle();
+ switch (WaitForSingleObjectEx(handle, time, FALSE)) {
+ case WAIT_OBJECT_0:
+ ret = true;
+ d->handle->join();
+ break;
+ case WAIT_FAILED:
+ qErrnoWarning("QThread::wait: WaitForSingleObjectEx() failed");
+ break;
+ case WAIT_ABANDONED:
+ case WAIT_TIMEOUT:
+ default:
+ break;
+ }
+ }
+#endif // Q_OS_WINRT
locker.mutex()->lock();
--d->waiters;
@@ -572,7 +708,12 @@ bool QThread::wait(unsigned long time)
}
if (d->finished && !d->waiters) {
+#ifndef Q_OS_WINRT
CloseHandle(d->handle);
+#else
+ d->handle->detach();
+ delete d->handle;
+#endif
d->handle = 0;
}
@@ -590,13 +731,16 @@ void QThread::setTerminationEnabled(bool enabled)
if (enabled && d->terminatePending) {
QThreadPrivate::finish(thr, false);
locker.unlock(); // don't leave the mutex locked!
+#ifndef Q_OS_WINRT
_endthreadex(0);
+#endif
}
}
// Caller must hold the mutex
void QThreadPrivate::setPriority(QThread::Priority threadPriority)
{
+#ifndef Q_OS_WINRT
// copied from start() with a few modifications:
int prio;
@@ -639,6 +783,12 @@ void QThreadPrivate::setPriority(QThread::Priority threadPriority)
if (!SetThreadPriority(handle, prio)) {
qErrnoWarning("QThread::setPriority: Failed to set thread priority");
}
+#else // !Q_OS_WINRT
+ if (priority != threadPriority) {
+ qWarning("QThread::setPriority: Failed to set thread priority (not implemented)");
+ return;
+ }
+#endif // Q_OS_WINRT
}
QT_END_NAMESPACE
diff --git a/src/corelib/thread/qthreadpool.cpp b/src/corelib/thread/qthreadpool.cpp
index fb1d1ee7cc..269f561a91 100644
--- a/src/corelib/thread/qthreadpool.cpp
+++ b/src/corelib/thread/qthreadpool.cpp
@@ -61,6 +61,7 @@ public:
void run();
void registerThreadInactive();
+ QWaitCondition runnableReady;
QThreadPoolPrivate *manager;
QRunnable *runnable;
};
@@ -128,14 +129,13 @@ void QThreadPoolThread::run()
// if too many threads are active, expire this thread
bool expired = manager->tooManyThreadsActive();
if (!expired) {
- ++manager->waitingThreads;
+ manager->waitingThreads.enqueue(this);
registerThreadInactive();
// wait for work, exiting after the expiry timeout is reached
- expired = !manager->runnableReady.wait(locker.mutex(), manager->expiryTimeout);
+ runnableReady.wait(locker.mutex(), manager->expiryTimeout);
++manager->activeThreads;
-
- if (expired)
- --manager->waitingThreads;
+ if (manager->waitingThreads.removeOne(this))
+ expired = true;
}
if (expired) {
manager->expiredThreads.enqueue(this);
@@ -160,7 +160,6 @@ QThreadPoolPrivate:: QThreadPoolPrivate()
expiryTimeout(30000),
maxThreadCount(qAbs(QThread::idealThreadCount())),
reservedThreads(0),
- waitingThreads(0),
activeThreads(0)
{ }
@@ -176,11 +175,10 @@ bool QThreadPoolPrivate::tryStart(QRunnable *task)
if (activeThreadCount() >= maxThreadCount)
return false;
- if (waitingThreads > 0) {
+ if (waitingThreads.count() > 0) {
// recycle an available thread
- --waitingThreads;
enqueueTask(task);
- runnableReady.wakeOne();
+ waitingThreads.takeFirst()->runnableReady.wakeOne();
return true;
}
@@ -225,7 +223,7 @@ int QThreadPoolPrivate::activeThreadCount() const
{
return (allThreads.count()
- expiredThreads.count()
- - waitingThreads
+ - waitingThreads.count()
+ reservedThreads);
}
@@ -266,7 +264,6 @@ void QThreadPoolPrivate::reset()
{
QMutexLocker locker(&mutex);
isExiting = true;
- runnableReady.wakeAll();
while (!allThreads.empty()) {
// move the contents of the set out so that we can iterate without the lock
@@ -275,6 +272,7 @@ void QThreadPoolPrivate::reset()
locker.unlock();
foreach (QThreadPoolThread *thread, allThreadsCopy) {
+ thread->runnableReady.wakeAll();
thread->wait();
delete thread;
}
@@ -283,7 +281,7 @@ void QThreadPoolPrivate::reset()
// repeat until all newly arrived threads have also completed
}
- waitingThreads = 0;
+ waitingThreads.clear();
expiredThreads.clear();
isExiting = false;
@@ -459,10 +457,8 @@ void QThreadPool::start(QRunnable *runnable, int priority)
if (!d->tryStart(runnable)) {
d->enqueueTask(runnable, priority);
- if (d->waitingThreads > 0) {
- --d->waitingThreads;
- d->runnableReady.wakeOne();
- }
+ if (!d->waitingThreads.isEmpty())
+ d->waitingThreads.takeFirst()->runnableReady.wakeOne();
}
}
diff --git a/src/corelib/thread/qthreadpool_p.h b/src/corelib/thread/qthreadpool_p.h
index ba77f7e57c..bd5f546fdb 100644
--- a/src/corelib/thread/qthreadpool_p.h
+++ b/src/corelib/thread/qthreadpool_p.h
@@ -87,8 +87,8 @@ public:
void stealRunnable(QRunnable *);
mutable QMutex mutex;
- QWaitCondition runnableReady;
QSet<QThreadPoolThread *> allThreads;
+ QQueue<QThreadPoolThread *> waitingThreads;
QQueue<QThreadPoolThread *> expiredThreads;
QList<QPair<QRunnable *, int> > queue;
QWaitCondition noActiveThreads;
@@ -97,7 +97,6 @@ public:
int expiryTimeout;
int maxThreadCount;
int reservedThreads;
- int waitingThreads;
int activeThreads;
};
diff --git a/src/corelib/thread/qwaitcondition.h b/src/corelib/thread/qwaitcondition.h
index 1468951373..ce073c21e9 100644
--- a/src/corelib/thread/qwaitcondition.h
+++ b/src/corelib/thread/qwaitcondition.h
@@ -84,9 +84,9 @@ public:
bool wait(QMutex *mutex, unsigned long time = ULONG_MAX)
{
- Q_UNUSED(mutex);
- Q_UNUSED(time);
- return true;
+ Q_UNUSED(mutex);
+ Q_UNUSED(time);
+ return true;
}
void wakeOne() {}
diff --git a/src/corelib/thread/qwaitcondition_win.cpp b/src/corelib/thread/qwaitcondition_win.cpp
index 1cb1f82b03..f09667a364 100644
--- a/src/corelib/thread/qwaitcondition_win.cpp
+++ b/src/corelib/thread/qwaitcondition_win.cpp
@@ -64,7 +64,11 @@ class QWaitConditionEvent
public:
inline QWaitConditionEvent() : priority(0), wokenUp(false)
{
+#ifndef Q_OS_WINRT
event = CreateEvent(NULL, TRUE, FALSE, NULL);
+#else
+ event = CreateEventEx(NULL, NULL, CREATE_EVENT_MANUAL_RESET, EVENT_ALL_ACCESS);
+#endif
}
inline ~QWaitConditionEvent() { CloseHandle(event); }
int priority;
@@ -91,7 +95,9 @@ QWaitConditionEvent *QWaitConditionPrivate::pre()
mtx.lock();
QWaitConditionEvent *wce =
freeQueue.isEmpty() ? new QWaitConditionEvent : freeQueue.takeFirst();
+#ifndef Q_OS_WINRT
wce->priority = GetThreadPriority(GetCurrentThread());
+#endif
wce->wokenUp = false;
// insert 'wce' into the queue (sorted by priority)
@@ -111,7 +117,12 @@ bool QWaitConditionPrivate::wait(QWaitConditionEvent *wce, unsigned long time)
{
// wait for the event
bool ret = false;
+#ifndef Q_OS_WINRT
switch (WaitForSingleObject(wce->event, time)) {
+#else
+ switch (WaitForSingleObjectEx(wce->event, time, FALSE)) {
+#endif
+
default: break;
case WAIT_OBJECT_0:
diff --git a/src/corelib/thread/thread.pri b/src/corelib/thread/thread.pri
index 13f0502b62..3c1ddd984a 100644
--- a/src/corelib/thread/thread.pri
+++ b/src/corelib/thread/thread.pri
@@ -17,8 +17,7 @@ HEADERS += thread/qmutex.h \
thread/qfuturesynchronizer.h \
thread/qfuturewatcher.h \
thread/qbasicatomic.h \
- thread/qgenericatomic.h \
- thread/qoldbasicatomic.h
+ thread/qgenericatomic.h
# private headers
HEADERS += thread/qmutex_p.h \