一杯清酒邀明月
天下本无事,庸人扰之而烦耳。

QAtomicPointer类是一个模板类,它对指针提供与平台无关的原子操作

template <typename T> class QAtomicPointer

头文件:

#include <QAtomicPointer>

cmake:

1 find_package(Qt6 COMPONENTS Core REQUIRED)
2 target_link_libraries(mytarget PRIVATE Qt6::Core)

qmake:

QT += core

详细说明

有关整数的原子操作,请参阅QAtomicInteger类。

原子操作是一种不间断完成的复杂操作。QAtomicPointer类为指针提供了原子的测试和设置、获取和存储以及获取和添加。

原子API

内存排序

QAtomicPointer提供了原子测试和设置、获取和存储以及获取和添加函数的几种实现。每个实现都定义了一个内存排序语义,该语义描述了处理器如何执行围绕原子指令的内存访问。由于许多现代架构允许乱序执行和内存排序,因此使用正确的语义是必要的,以确保您的应用程序在所有处理器上正常运行。

  • Relaxed:非指定的内存排序,使编译器和处理器可以自由地对内存访问进行重新排序。
  • Acquire:原子操作之后的内存访问(按程序顺序)不能在原子操作之前重新排序。
  • Release:原子操作之前的内存访问(按程序顺序)不能在原子操作之后重新排序。
  • Ordered:相同的获取和发布语义组合

测试并设置

如果QAtomicPointer的当前值是期望值,则测试设置函数将新值分配给QAtomicPointer并返回true。如果值不相同,则这些函数不执行任何操作并返回false。此操作等于以下代码:

1 if (currentValue == expectedValue) {
2     currentValue = newValue;
3     return true;
4 }
5 return false;

有4个测试设置函数:testAndSetRelaxed(), testAndSetAcquire(), testAndSetRelease(), testAndSetOrdered()。有关不同的内存排序语义的说明,请参见上文。

提取并存储

原子获取和存储功能读取QAtomicPointer的当前值,然后分配一个新值,并返回原始值。此操作等于以下代码:

1 T *originalValue = currentValue;
2 currentValue = newValue;
3 return originalValue;

有4个访存函数:fetchAndStoreRelaxed(), fetchAndStoreAcquire(), fetchAndStoreRelease(), fetchAndStoreOrdered()。有关不同的内存排序语义的说明,请参见上文。

提取并添加

原子获取和添加函数读取QAtomicPointer的当前值,然后将给定值添加到当前值,并返回原始值。此操作等于以下代码:

1 T *originalValue = currentValue;
2 currentValue += valueToAdd;
3 return originalValue;

有4个获取和添加函数:fetchAndAddRelaxed(), fetchAndAddAcquire(), fetchAndAddRelease(), fetchAndAddOrdered().。有关不同的内存排序语义的说明,请参见上文。

原子API的功能测试

提供可在所有处理器上工作的独立于平台的原子API具有挑战性。QAtomicPointer提供的API可以保证在所有处理器上以原子方式工作。但是,由于不是所有处理器都实现对QAtomicPointer提供的每个操作的支持,因此有必要公开有关处理器的信息。

您可以在编译时使用各种宏检查硬件上支持哪些特性。这些将告诉您,您的硬件是否总是、有时或不支持特定的操作。宏的形式是Q_ATOMIC_POINTER_OPERATION_IS_HOW_NATIVE。操作是TEST_AND_SET, FETCH_AND_STORE,或FETCH_AND_ADD之一,而HOW是ALWAYS, SOMETIMES, or NOT之一。每次操作都只有一个已定义的宏。例如,如果定义了Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE,那么Q_ATOMIC_POINTER_TEST_AND_SET_IS_NOT_NATIVE和Q_ATOMIC_POINTER_TEST_AND_SET_IS_NOT_NATIVE都不会定义。

在固定时间内完成的操作称为无等待操作。这些操作不是使用锁或任何类型的循环来实现的。对于总是支持的、无等待的原子操作,Qt除了定义Q_ATOMIC_POINTER_OPERATION_IS_WAIT_FREE之外,还定义了Q_ATOMIC_POINTER_OPERATION_IS_ALWAYS_NATIVE。

在仅在新一代处理器中支持原子操作的情况下,QAtomicPointer还提供了一种方法,可以在运行时通过isTestAndSetNative()、isFetchAndStoreNative()isFetchAndAddNative()函数检查硬件支持什么。可以使用isstestandsetwaitfree()、isFetchAndStoreWaitFree()isFetchAndAddWaitFree()函数检测无等待实现。

以下是QAtomicPointer所有特性宏的完整列表:

  • Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE
  • Q_ATOMIC_POINTER_TEST_AND_SET_IS_SOMETIMES_NATIVE
  • Q_ATOMIC_POINTER_TEST_AND_SET_IS_NOT_NATIVE
  • Q_ATOMIC_POINTER_TEST_AND_SET_IS_WAIT_FREE
  • Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_ALWAYS_NATIVE
  • Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_SOMETIMES_NATIVE
  • Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_NOT_NATIVE
  • Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_WAIT_FREE
  • Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_ALWAYS_NATIVE
  • Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_SOMETIMES_NATIVE
  • Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_NOT_NATIVE
  • Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_WAIT_FREE

另请参见QAtomicInteger。

成员函数

QAtomicPointer

QAtomicPointer::QAtomicPointer(const QAtomicPointer &other)

构造other的副本。

QAtomicPointer::QAtomicPointer(T *value = nullptr)

构造一个具有给定值的QAtomicPointer 。

operator=

QAtomicPointer &QAtomicPointer::operator=(const QAtomicPointer &other)

将other赋值给这个QAtomicPointer,并返回对这个QAtomicPointer的引用。

fetchAndAddAcquire

*QAtomicPointer::fetchAndAddAcquire(qptrdiff valueToAdd)

原子获取和添加。

读取该QAtomicPointer的当前值,然后将valueToAdd添加到当前值,返回原始值。

这个函数使用了获取内存排序语义,这确保了原子操作之后的内存访问(按程序顺序)不会在原子操作之前重新排序。

fetchAndAddOrdered

*QAtomicPointer::fetchAndAddOrdered(qptrdiff valueToAdd)

原子获取和添加。

读取该QAtomicPointer的当前值,然后将valueToAdd添加到当前值,返回原始值。

这个函数使用有序的内存排序语义,它确保原子操作之前和之后的内存访问(按程序顺序)不会被重新排序。

posted on 2021-06-22 14:13  一杯清酒邀明月  阅读(685)  评论(0编辑  收藏  举报