Detailed Description

An atomic operation is a complex operation that completes without interruption. The QAtomicInteger class provides atomic reference counting, test-and-set, fetch-and-store, and fetch-and-add for integers.

The template parameter T must be a C++ integer type:

8-bit: char, signed char, unsigned char, qint8, quint8

16-bit: short, unsigned short, qint16, quint16, char16_t (C++11)

32-bit: int, unsigned int, qint32, quint32, char32_t (C++11)

64-bit: long long, unsigned long long, qint64, quint64

platform-specific size: long, unsigned long

pointer size: qintptr, quintptr, qptrdiff

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 Q_ATOMIC_INT\e{nn}_IS_SUPPORTED, where \e{nn} is the number of bits desired.

The Atomic API

Reference counting

The ref() and deref() functions provide an efficient reference counting API. The return value of these functions are used to indicate when the last reference has been released. These functions allow you to implement your own implicitly shared classes.

Memory ordering

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 executed by the processor. Since many modern architectures allow out-of-order execution and memory ordering, using the correct semantic is necessary to ensure that your application functions properly on all processors.

Acquire - memory access following the atomic operation (in program order) may not be re-ordered before the atomic operation.

Release - memory access before the atomic operation (in program order) may not be re-ordered after the atomic operation.

Ordered - the same Acquire and Release semantics combined.

Test-and-set

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 not the same, these functions do nothing and return false. This operation equates to the following code:

Fetch-and-add

The atomic fetch-and-add functions read the current value of the QAtomicInteger and then add the given value to the current value, returning the original value. This operation equates to the following code:

Feature Tests for the Atomic API

Providing a platform-independent atomic API that works on all 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 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_INTnn_OPERATION_IS_HOW_NATIVE. nn is the size of the integer (in bits), OPERATION is one of REFERENCE_COUNTING, TEST_AND_SET, FETCH_AND_STORE, or FETCH_AND_ADD, and HOW is one of ALWAYS, SOMETIMES, or NOT. There will always be exactly one defined macro per operation. For example, if Q_ATOMIC_INT32_REFERENCE_COUNTING_IS_ALWAYS_NATIVE is defined, neither Q_ATOMIC_INT_REFERENCE_COUNTING_IS_SOMETIMES_NATIVE nor 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_INTnn_OPERATION_IS_WAIT_FREE in addition to the Q_ATOMIC_INTnn_OPERATION_IS_ALWAYS_NATIVE.

For compatibility with previous versions of Qt, macros with an empty 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.

void QAtomicInteger::storeRelease(TnewValue)

bool QAtomicInteger::testAndSetAcquire(TexpectedValue, TnewValue)

Atomic test-and-set.

If the current value of this QAtomicInteger is the expectedValue, the test-and-set functions assign the newValue to this QAtomicInteger and return true. If the values are not the same, this function does nothing and returns false.

This function uses acquirememory ordering semantics, which ensures that memory access following the atomic operation (in program order) may not be re-ordered before the atomic operation.

bool QAtomicInteger::testAndSetOrdered(TexpectedValue, TnewValue)

Atomic test-and-set.

If the current value of this QAtomicInteger is the expectedValue, the test-and-set functions assign the newValue to this QAtomicInteger and return true. If the values are not the same, this function does nothing and returns false.

This function uses orderedmemory ordering semantics, which ensures that memory access before and after the atomic operation (in program order) may not be re-ordered.

bool QAtomicInteger::testAndSetRelaxed(TexpectedValue, TnewValue)

Atomic test-and-set.

If the current value of this QAtomicInteger is the expectedValue, the test-and-set functions assign the newValue to this QAtomicInteger and return true. If the values are not the same, this function does nothing and returns false.

bool QAtomicInteger::testAndSetRelease(TexpectedValue, TnewValue)

Atomic test-and-set.

If the current value of this QAtomicInteger is the expectedValue, the test-and-set functions assign the newValue to this QAtomicInteger and return true. If the values are not the same, this function does nothing and returns false.

This function uses releasememory ordering semantics, which ensures that memory access before the atomic operation (in program order) may not be re-ordered after the atomic operation.

QAtomicInteger::operator T() const

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.

Macro Documentation

Q_ATOMIC_INTnn_FETCH_AND_ADD_IS_ALWAYS_NATIVE

This macro is defined if and only if your processor supports atomic fetch-and-add on integers.

nn is the size of the integer, in bits (8, 16, 32 or 64).

Q_ATOMIC_INTnn_FETCH_AND_ADD_IS_NOT_NATIVE

This macro is defined when the hardware does not support atomic fetch-and-add on integers.

nn is the size of the integer, in bits (8, 16, 32 or 64).

Q_ATOMIC_INTnn_FETCH_AND_ADD_IS_SOMETIMES_NATIVE

This macro is defined when only certain generations of the processor support atomic fetch-and-add on integers. Use the QAtomicInteger::isFetchAndAddNative() function to check what your processor supports.

Q_ATOMIC_INTnn_FETCH_AND_STORE_IS_ALWAYS_NATIVE

This macro is defined if and only if your processor supports atomic fetch-and-store on integers.

nn is the size of the integer, in bits (8, 16, 32 or 64).

Q_ATOMIC_INTnn_FETCH_AND_STORE_IS_NOT_NATIVE

This macro is defined when the hardware does not support atomic fetch-and-store on integers.

nn is the size of the integer, in bits (8, 16, 32 or 64).

Q_ATOMIC_INTnn_FETCH_AND_STORE_IS_SOMETIMES_NATIVE

This macro is defined when only certain generations of the processor support atomic fetch-and-store on integers. Use the QAtomicInteger::isFetchAndStoreNative() function to check what your processor supports.

Q_ATOMIC_INTnn_TEST_AND_SET_IS_ALWAYS_NATIVE

This macro is defined if and only if your processor supports atomic test-and-set on integers.

nn is the size of the integer, in bits (8, 16, 32 or 64).

Q_ATOMIC_INTnn_TEST_AND_SET_IS_NOT_NATIVE

This macro is defined when the hardware does not support atomic test-and-set on integers.

nn is the size of the integer, in bits (8, 16, 32 or 64).

Q_ATOMIC_INTnn_TEST_AND_SET_IS_SOMETIMES_NATIVE

This macro is defined when only certain generations of the processor support atomic test-and-set on integers. Use the QAtomicInteger::isTestAndSetNative() function to check what your processor supports.