Introduce QAtomicInteger<T> and derive QAtomicInt from it

QAtomicInteger<T> is to QBasicAtomicInteger<T> what QAtomicInt was to
QBasicAtomicInt: just a little more syntactic sugar. The Basic classes
do not always have a constructor, since they depend on compiler
support. The constructor is always present in the non-Basic class, at
the expense of making it non-POD for C++98 code.

This commit also repurposes most of QAtomicInt's documentation for
QAtomicInteger. It adds only the Q_ATOMIC_INTnn_IS_SUPPORTED macro
that explains whether the given type is supported on this platform.

Change-Id: I58886d6fa49fea4de24015c40dae29c9fa534e00
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Reviewed-by: Kurt Pattyn <pattyn.kurt@gmail.com>
This commit is contained in:
Thiago Macieira 2013-12-02 18:37:05 -08:00 committed by The Qt Project
parent 1b3a424bcf
commit e4533e3aeb
2 changed files with 242 additions and 146 deletions

View File

@ -44,17 +44,42 @@
/*! /*!
\class QAtomicInt \class QAtomicInt
\inmodule QtCore \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 \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 \ingroup thread
For atomic operations on pointers, see the QAtomicPointer class. For atomic operations on pointers, see the QAtomicPointer class.
An \e atomic operation is a complex operation that completes without interruption. 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. 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
\endlist
Of the list above, only the 32-bit-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 \section1 The Atomic API
\section2 Reference counting \section2 Reference counting
@ -69,7 +94,7 @@
\section2 Memory ordering \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 test-and-set, fetch-and-store, and fetch-and-add functions. Each
implementation defines a memory ordering semantic that describes implementation defines a memory ordering semantic that describes
how memory accesses surrounding the atomic instruction are how memory accesses surrounding the atomic instruction are
@ -95,8 +120,8 @@
\section2 Test-and-set \section2 Test-and-set
If the current value of the QAtomicInt is an expected value, the If the current value of the QAtomicInteger is an expected value, the
test-and-set functions assign a new value to the QAtomicInt and test-and-set functions assign a new value to the QAtomicInteger and
return true. If values are \a not the same, these functions do return true. If values are \a not the same, these functions do
nothing and return false. This operation equates to the following nothing and return false. This operation equates to the following
code: code:
@ -111,7 +136,7 @@
\section2 Fetch-and-store \section2 Fetch-and-store
The atomic fetch-and-store functions read the current value of the 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: value. This operation equates to the following code:
\snippet code/src_corelib_thread_qatomic.cpp 2 \snippet code/src_corelib_thread_qatomic.cpp 2
@ -124,7 +149,7 @@
\section2 Fetch-and-add \section2 Fetch-and-add
The atomic fetch-and-add functions read the current value of the 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 returning the original value. This operation equates to the
following code: following code:
@ -138,34 +163,35 @@
\section1 Feature Tests for the Atomic API \section1 Feature Tests for the Atomic API
Providing a platform-independent atomic API that works on all 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 guaranteed to work atomically on all processors. However, since
not all processors implement support for every operation provided 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. processor.
You can check at compile time which features are supported on your You can check at compile time which features are supported on your
hardware using various macros. These will tell you if your hardware using various macros. These will tell you if your
hardware always, sometimes, or does not support a particular hardware always, sometimes, or does not support a particular
operation. The macros have the form 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, is one of REFERENCE_COUNTING, TEST_AND_SET,
FETCH_AND_STORE, or FETCH_AND_ADD, and \e{HOW} is one of FETCH_AND_STORE, or FETCH_AND_ADD, and \e{HOW} is one of
ALWAYS, SOMETIMES, or NOT. There will always be exactly one ALWAYS, SOMETIMES, or NOT. There will always be exactly one
defined macro per operation. For example, if 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 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 An operation that completes in constant time is said to be
wait-free. Such operations are not implemented using locks or wait-free. Such operations are not implemented using locks or
loops of any kind. For atomic operations that are always loops of any kind. For atomic operations that are always
supported, and that are wait-free, Qt defines the 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{nn}_\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_ALWAYS_NATIVE.
In cases where an atomic operation is only supported in newer 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 check at runtime what your hardware supports with the
isReferenceCountingNative(), isTestAndSetNative(), isReferenceCountingNative(), isTestAndSetNative(),
isFetchAndStoreNative(), and isFetchAndAddNative() isFetchAndStoreNative(), and isFetchAndAddNative()
@ -173,32 +199,37 @@
isReferenceCountingWaitFree(), isTestAndSetWaitFree(), isReferenceCountingWaitFree(), isTestAndSetWaitFree(),
isFetchAndStoreWaitFree(), and isFetchAndAddWaitFree() functions. 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 \list
\li Q_ATOMIC_INT_REFERENCE_COUNTING_IS_ALWAYS_NATIVE \li Q_ATOMIC_INT\e{nn}_REFERENCE_COUNTING_IS_ALWAYS_NATIVE
\li Q_ATOMIC_INT_REFERENCE_COUNTING_IS_SOMETIMES_NATIVE \li Q_ATOMIC_INT\e{nn}_REFERENCE_COUNTING_IS_SOMETIMES_NATIVE
\li Q_ATOMIC_INT_REFERENCE_COUNTING_IS_NOT_NATIVE \li Q_ATOMIC_INT\e{nn}_REFERENCE_COUNTING_IS_NOT_NATIVE
\li Q_ATOMIC_INT_REFERENCE_COUNTING_IS_WAIT_FREE \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\e{nn}_TEST_AND_SET_IS_ALWAYS_NATIVE
\li Q_ATOMIC_INT_TEST_AND_SET_IS_SOMETIMES_NATIVE \li Q_ATOMIC_INT\e{nn}_TEST_AND_SET_IS_SOMETIMES_NATIVE
\li Q_ATOMIC_INT_TEST_AND_SET_IS_NOT_NATIVE \li Q_ATOMIC_INT\e{nn}_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_WAIT_FREE
\li Q_ATOMIC_INT_FETCH_AND_STORE_IS_ALWAYS_NATIVE \li Q_ATOMIC_INT\e{nn}_FETCH_AND_STORE_IS_ALWAYS_NATIVE
\li Q_ATOMIC_INT_FETCH_AND_STORE_IS_SOMETIMES_NATIVE \li Q_ATOMIC_INT\e{nn}_FETCH_AND_STORE_IS_SOMETIMES_NATIVE
\li Q_ATOMIC_INT_FETCH_AND_STORE_IS_NOT_NATIVE \li Q_ATOMIC_INT\e{nn}_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_WAIT_FREE
\li Q_ATOMIC_INT_FETCH_AND_ADD_IS_ALWAYS_NATIVE \li Q_ATOMIC_INT\e{nn}_FETCH_AND_ADD_IS_ALWAYS_NATIVE
\li Q_ATOMIC_INT_FETCH_AND_ADD_IS_SOMETIMES_NATIVE \li Q_ATOMIC_INT\e{nn}_FETCH_AND_ADD_IS_SOMETIMES_NATIVE
\li Q_ATOMIC_INT_FETCH_AND_ADD_IS_NOT_NATIVE \li Q_ATOMIC_INT\e{nn}_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_WAIT_FREE
\endlist \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 \sa QAtomicPointer
*/ */
@ -207,21 +238,27 @@
Constructs a QAtomicInt with the given \a value. 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. 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 Assigns \a other to this QAtomicInteger and returns a reference to
this QAtomicInt. this QAtomicInteger.
*/ */
/*!
\fn int QAtomicInt::load() const
Atomically loads the value of this QAtomicInt using relaxed memory /*!
\fn int QAtomicInteger::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 ordering. The value is not modified in any way, but note that there's no
guarantee that it remains so. guarantee that it remains so.
@ -229,9 +266,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 ordering. The value is not modified in any way, but note that there's no
guarantee that it remains so. guarantee that it remains so.
@ -239,7 +276,7 @@
*/ */
/*! /*!
\fn void QAtomicInt::store(int newValue) \fn void QAtomicInteger::store(int newValue)
Atomically stores the \a newValue value into this atomic type, using Atomically stores the \a newValue value into this atomic type, using
relaxed memory ordering. relaxed memory ordering.
@ -248,7 +285,7 @@
*/ */
/*! /*!
\fn void QAtomicInt::storeRelease(int newValue) \fn void QAtomicInteger::storeRelease(int newValue)
Atomically stores the \a newValue value into this atomic type, using Atomically stores the \a newValue value into this atomic type, using
the "Release" memory ordering. the "Release" memory ordering.
@ -256,23 +293,23 @@
\sa store(), load() \sa store(), load()
*/ */
/*! \fn bool QAtomicInt::isReferenceCountingNative() /*! \fn bool QAtomicInteger::isReferenceCountingNative()
Returns \c true if reference counting is implemented using atomic Returns \c true if reference counting is implemented using atomic
processor instructions, false otherwise. processor instructions, false otherwise.
*/ */
/*! \fn bool QAtomicInt::isReferenceCountingWaitFree() /*! \fn bool QAtomicInteger::isReferenceCountingWaitFree()
Returns \c true if atomic reference counting is wait-free, false Returns \c true if atomic reference counting is wait-free, false
otherwise. otherwise.
*/ */
/*! \fn bool QAtomicInt::ref() /*! \fn bool QAtomicInteger::ref()
Atomically increments the value of this QAtomicInt. Returns \c true Atomically increments the value of this QAtomicInteger. Returns \c true
if the new value is non-zero, false otherwise. 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 ordering}{memory ordering} semantics, which ensures that memory
access before and after the atomic operation (in program order) access before and after the atomic operation (in program order)
may not be re-ordered. may not be re-ordered.
@ -280,11 +317,11 @@
\sa deref() \sa deref()
*/ */
/*! \fn bool QAtomicInt::deref() /*! \fn bool QAtomicInteger::deref()
Atomically decrements the value of this QAtomicInt. Returns \c true Atomically decrements the value of this QAtomicInteger. Returns \c true
if the new value is non-zero, false otherwise. 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 ordering}{memory ordering} semantics, which ensures that memory
access before and after the atomic operation (in program order) access before and after the atomic operation (in program order)
may not be re-ordered. may not be re-ordered.
@ -292,340 +329,383 @@
\sa ref() \sa ref()
*/ */
/*! \fn bool QAtomicInt::isTestAndSetNative() /*! \fn bool QAtomicInteger::isTestAndSetNative()
Returns \c true if test-and-set is implemented using atomic processor Returns \c true if test-and-set is implemented using atomic processor
instructions, false otherwise. instructions, false otherwise.
*/ */
/*! \fn bool QAtomicInt::isTestAndSetWaitFree() /*! \fn bool QAtomicInteger::isTestAndSetWaitFree()
Returns \c true if atomic test-and-set is wait-free, false otherwise. 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. 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 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 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 ordering}{memory ordering} semantics, leaving the compiler and
processor to freely reorder memory accesses. 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. 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 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 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 ordering}{memory ordering} semantics, which ensures that memory
access following the atomic operation (in program order) may not access following the atomic operation (in program order) may not
be re-ordered before the atomic operation. 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. 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 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 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 ordering}{memory ordering} semantics, which ensures that memory
access before the atomic operation (in program order) may not be access before the atomic operation (in program order) may not be
re-ordered after the atomic operation. 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. 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 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 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 ordering}{memory ordering} semantics, which ensures that memory
access before and after the atomic operation (in program order) access before and after the atomic operation (in program order)
may not be re-ordered. may not be re-ordered.
*/ */
/*! \fn bool QAtomicInt::isFetchAndStoreNative() /*! \fn bool QAtomicInteger::isFetchAndStoreNative()
Returns \c true if fetch-and-store is implemented using atomic Returns \c true if fetch-and-store is implemented using atomic
processor instructions, false otherwise. processor instructions, false otherwise.
*/ */
/*! \fn bool QAtomicInt::isFetchAndStoreWaitFree() /*! \fn bool QAtomicInteger::isFetchAndStoreWaitFree()
Returns \c true if atomic fetch-and-store is wait-free, false Returns \c true if atomic fetch-and-store is wait-free, false
otherwise. otherwise.
*/ */
/*! \fn int QAtomicInt::fetchAndStoreRelaxed(int newValue) /*! \fn int QAtomicInteger::fetchAndStoreRelaxed(int newValue)
Atomic fetch-and-store. 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. \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 ordering}{memory ordering} semantics, leaving the compiler and
processor to freely reorder memory accesses. processor to freely reorder memory accesses.
*/ */
/*! \fn int QAtomicInt::fetchAndStoreAcquire(int newValue) /*! \fn int QAtomicInteger::fetchAndStoreAcquire(int newValue)
Atomic fetch-and-store. 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. \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 ordering}{memory ordering} semantics, which ensures that memory
access following the atomic operation (in program order) may not access following the atomic operation (in program order) may not
be re-ordered before the atomic operation. be re-ordered before the atomic operation.
*/ */
/*! \fn int QAtomicInt::fetchAndStoreRelease(int newValue) /*! \fn int QAtomicInteger::fetchAndStoreRelease(int newValue)
Atomic fetch-and-store. 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. \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 ordering}{memory ordering} semantics, which ensures that memory
access before the atomic operation (in program order) may not be access before the atomic operation (in program order) may not be
re-ordered after the atomic operation. re-ordered after the atomic operation.
*/ */
/*! \fn int QAtomicInt::fetchAndStoreOrdered(int newValue) /*! \fn int QAtomicInteger::fetchAndStoreOrdered(int newValue)
Atomic fetch-and-store. 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. \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 ordering}{memory ordering} semantics, which ensures that memory
access before and after the atomic operation (in program order) access before and after the atomic operation (in program order)
may not be re-ordered. may not be re-ordered.
*/ */
/*! \fn bool QAtomicInt::isFetchAndAddNative() /*! \fn bool QAtomicInteger::isFetchAndAddNative()
Returns \c true if fetch-and-add is implemented using atomic Returns \c true if fetch-and-add is implemented using atomic
processor instructions, false otherwise. processor instructions, false otherwise.
*/ */
/*! \fn bool QAtomicInt::isFetchAndAddWaitFree() /*! \fn bool QAtomicInteger::isFetchAndAddWaitFree()
Returns \c true if atomic fetch-and-add is wait-free, false Returns \c true if atomic fetch-and-add is wait-free, false
otherwise. otherwise.
*/ */
/*! \fn int QAtomicInt::fetchAndAddRelaxed(int valueToAdd) /*! \fn int QAtomicInteger::fetchAndAddRelaxed(int valueToAdd)
Atomic fetch-and-add. 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. \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 ordering}{memory ordering} semantics, leaving the compiler and
processor to freely reorder memory accesses. processor to freely reorder memory accesses.
*/ */
/*! \fn int QAtomicInt::fetchAndAddAcquire(int valueToAdd) /*! \fn int QAtomicInteger::fetchAndAddAcquire(int valueToAdd)
Atomic fetch-and-add. 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. \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 ordering}{memory ordering} semantics, which ensures that memory
access following the atomic operation (in program order) may not access following the atomic operation (in program order) may not
be re-ordered before the atomic operation. be re-ordered before the atomic operation.
*/ */
/*! \fn int QAtomicInt::fetchAndAddRelease(int valueToAdd) /*! \fn int QAtomicInteger::fetchAndAddRelease(int valueToAdd)
Atomic fetch-and-add. 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. \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 ordering}{memory ordering} semantics, which ensures that memory
access before the atomic operation (in program order) may not be access before the atomic operation (in program order) may not be
re-ordered after the atomic operation. re-ordered after the atomic operation.
*/ */
/*! \fn int QAtomicInt::fetchAndAddOrdered(int valueToAdd) /*! \fn int QAtomicInteger::fetchAndAddOrdered(int valueToAdd)
Atomic fetch-and-add. 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. \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 ordering}{memory ordering} semantics, which ensures that memory
access before and after the atomic operation (in program order) access before and after the atomic operation (in program order)
may not be re-ordered. may not be re-ordered.
*/ */
/*! /*!
\macro Q_ATOMIC_INT_REFERENCE_COUNTING_IS_ALWAYS_NATIVE \macro Q_ATOMIC_INTnn_IS_SUPPORTED
\relates QAtomicInt \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 This macro is defined if and only if all generations of your
processor support atomic reference counting. 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 \macro Q_ATOMIC_INTnn_REFERENCE_COUNTING_IS_SOMETIMES_NATIVE
\relates QAtomicInt \relates QAtomicInteger
This macro is defined when only certain generations of the This macro is defined when only certain generations of the
processor support atomic reference counting. Use the processor support atomic reference counting. Use the
QAtomicInt::isReferenceCountingNative() function to check what QAtomicInteger::isReferenceCountingNative() function to check what
your processor supports. 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 \macro Q_ATOMIC_INTnn_REFERENCE_COUNTING_IS_NOT_NATIVE
\relates QAtomicInt \relates QAtomicInteger
This macro is defined when the hardware does not support atomic This macro is defined when the hardware does not support atomic
reference counting. 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 \macro Q_ATOMIC_INTnn_REFERENCE_COUNTING_IS_WAIT_FREE
\relates QAtomicInt \relates QAtomicInteger
This macro is defined together with 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. 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 \macro Q_ATOMIC_INTnn_TEST_AND_SET_IS_ALWAYS_NATIVE
\relates QAtomicInt \relates QAtomicInteger
This macro is defined if and only if your processor supports This macro is defined if and only if your processor supports
atomic test-and-set on integers. 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 \macro Q_ATOMIC_INTnn_TEST_AND_SET_IS_SOMETIMES_NATIVE
\relates QAtomicInt \relates QAtomicInteger
This macro is defined when only certain generations of the This macro is defined when only certain generations of the
processor support atomic test-and-set on integers. Use 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. 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 \macro Q_ATOMIC_INTnn_TEST_AND_SET_IS_NOT_NATIVE
\relates QAtomicInt \relates QAtomicInteger
This macro is defined when the hardware does not support atomic This macro is defined when the hardware does not support atomic
test-and-set on integers. 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 \macro Q_ATOMIC_INTnn_TEST_AND_SET_IS_WAIT_FREE
\relates QAtomicInt \relates QAtomicInteger
This macro is defined together with 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. 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 \macro Q_ATOMIC_INTnn_FETCH_AND_STORE_IS_ALWAYS_NATIVE
\relates QAtomicInt \relates QAtomicInteger
This macro is defined if and only if your processor supports This macro is defined if and only if your processor supports
atomic fetch-and-store on integers. 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 \macro Q_ATOMIC_INTnn_FETCH_AND_STORE_IS_SOMETIMES_NATIVE
\relates QAtomicInt \relates QAtomicInteger
This macro is defined when only certain generations of the This macro is defined when only certain generations of the
processor support atomic fetch-and-store on integers. Use 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. 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 \macro Q_ATOMIC_INTnn_FETCH_AND_STORE_IS_NOT_NATIVE
\relates QAtomicInt \relates QAtomicInteger
This macro is defined when the hardware does not support atomic This macro is defined when the hardware does not support atomic
fetch-and-store on integers. 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 \macro Q_ATOMIC_INTnn_FETCH_AND_STORE_IS_WAIT_FREE
\relates QAtomicInt \relates QAtomicInteger
This macro is defined together with 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. 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 \macro Q_ATOMIC_INTnn_FETCH_AND_ADD_IS_ALWAYS_NATIVE
\relates QAtomicInt \relates QAtomicInteger
This macro is defined if and only if your processor supports This macro is defined if and only if your processor supports
atomic fetch-and-add on integers. 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 \macro Q_ATOMIC_INTnn_FETCH_AND_ADD_IS_SOMETIMES_NATIVE
\relates QAtomicInt \relates QAtomicInteger
This macro is defined when only certain generations of the This macro is defined when only certain generations of the
processor support atomic fetch-and-add on integers. Use 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. 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 \macro Q_ATOMIC_INTnn_FETCH_AND_ADD_IS_NOT_NATIVE
\relates QAtomicInt \relates QAtomicInteger
This macro is defined when the hardware does not support atomic This macro is defined when the hardware does not support atomic
fetch-and-add on integers. 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 \macro Q_ATOMIC_INTnn_FETCH_AND_ADD_IS_WAIT_FREE
\relates QAtomicInt \relates QAtomicInteger
This macro is defined together with 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. atomic fetch-and-add on integers is wait-free.
\e{nn} is the size of the integer, in bits (8, 16, 32 or 64).
*/ */
@ -639,7 +719,7 @@
\ingroup thread \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. 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. The QAtomicPointer class provides atomic test-and-set, fetch-and-store, and fetch-and-add for pointers.
@ -771,7 +851,7 @@
\endlist \endlist
\sa QAtomicInt \sa QAtomicInteger
*/ */
/*! \fn QAtomicPointer::QAtomicPointer(T *value) /*! \fn QAtomicPointer::QAtomicPointer(T *value)

View File

@ -55,25 +55,29 @@ QT_BEGIN_NAMESPACE
#endif #endif
// High-level atomic integer operations // High-level atomic integer operations
class QAtomicInt : public QBasicAtomicInt template <typename T>
class QAtomicInteger : public QBasicAtomicInteger<T>
{ {
public: public:
// Non-atomic API // Non-atomic API
#ifdef QT_BASIC_ATOMIC_HAS_CONSTRUCTORS #ifdef QT_BASIC_ATOMIC_HAS_CONSTRUCTORS
constexpr QAtomicInt(int value = 0) Q_DECL_NOTHROW : QBasicAtomicInt(value) {} constexpr QAtomicInteger(T value = 0) Q_DECL_NOTHROW : QBasicAtomicInteger<T>(value) {}
#else #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 #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->store(other.load());
} }
inline QAtomicInt &operator=(const QAtomicInt &other) Q_DECL_NOTHROW inline QAtomicInteger &operator=(const QAtomicInteger &other) Q_DECL_NOTHROW
{ {
this->store(other.load()); this->store(other.load());
return *this; return *this;
@ -117,6 +121,18 @@ public:
#endif #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 // High-level atomic pointer operations
template <typename T> template <typename T>
class QAtomicPointer : public QBasicAtomicPointer<T> class QAtomicPointer : public QBasicAtomicPointer<T>