在标准类型上使用原子操作

using atomic operations on standard types

目标:我要实现这个功能:

int atomicCAS(int* address, int compare, int val);

这是一个 CUDA function,但我想在 C++ 中为 CPU 实现它。 它必须与此 API 兼容,即我无法更改 address.

的类型

我假设通用硬件,例如amd64,和一个通用的编译器,例如GCC 或 Clang。

对应的 C++ STL 函数是 std::atomic::compare_exchange_strong,但是,它需要一个 std::atomic 类型,我不确定我是否可以像这样做:

((std::atomic<int>&) address)->compare_exchange_strong(...)

我也可以使用 GCC 内置函数 __atomic_compare_exchange_n 但不确定是否有任何注意事项或什么是断言这是有效的良好检查。

__sync_val_compare_and_swap 可能就是您要找的

我相信没有可移植的方法来做到这一点,主要是因为在 C++ 中 atomics 可以用锁实现(或者通常 sizeof(T) != sizeof(atomic<T>) )。

如您所述,您可以使用 GCC 内置函数。 libstdc++ 也使用它们来实现 std::atomic<Integral>,因此每当您需要实现与 std::atomic 方法等效的方法时,您可以查看 bits/atomic_base.h.

对于atomic::compare_exchange_strong

_GLIBCXX_ALWAYS_INLINE bool
  compare_exchange_strong(__int_type& __i1, __int_type __i2,
              memory_order __m1,
              memory_order __m2) volatile noexcept
  {
     memory_order __b2 = __m2 & __memory_order_mask;
     memory_order __b1 = __m1 & __memory_order_mask;

     __glibcxx_assert(__b2 != memory_order_release);
     __glibcxx_assert(__b2 != memory_order_acq_rel);
     __glibcxx_assert(__b2 <= __b1);

     return __atomic_compare_exchange_n(&_M_i, &__i1, __i2, 0, __m1, __m2);
  }

编辑: 改编自之前的代码:

int atomicCAS(int* address, int *compare, int val)
{
    return __atomic_compare_exchange_n(address, compare, val, 0,
                                       __ATOMIC_SEQ_CST,
                                       __ATOMIC_ACQUIRE);
}

注意 compare 是一个 in-out 参数,失败时它将被 *address 的当前值覆盖。 此版本等效于具有默认内存排序的 atomic<int>::compare_exchange_strong,请参阅 godbolt.