在标准类型上使用原子操作
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++ 中 atomic
s 可以用锁实现(或者通常 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.
目标:我要实现这个功能:
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++ 中 atomic
s 可以用锁实现(或者通常 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.