- atomic[meta header]
- std[meta namespace]
- function template[meta id-type]
- cpp11[meta cpp]
namespace std {
template <class T>
bool atomic_compare_exchange_weak_explicit(
volatile atomic<T>* object,
T* expected,
T desired,
memory_order success,
memory_order failure) noexcept; // (1) C++11
template <class T>
bool atomic_compare_exchange_weak_explicit(
volatile atomic<T>* object,
typename atomic<T>::value_type* expected,
typename atomic<T>::value_type desired,
memory_order success,
memory_order failure) noexcept; // (1) C++17
template <class T>
bool atomic_compare_exchange_weak_explicit(
atomic<T>* object,
T* expected,
T desired,
memory_order success,
memory_order failure) noexcept; // (2) C++11
template <class T>
bool atomic_compare_exchange_weak_explicit(
atomic<T>* object,
typename atomic<T>::value_type* expected,
typename atomic<T>::value_type desired,
memory_order success,
memory_order failure) noexcept; // (2) C++17
}
- atomic[link atomic.md]
- memory_order[link memory_order.md]
弱い比較でアトミックに値を入れ替える
- (1) :
- C++20 :
atomic<T>::is_always_lock_free
がtrue
であること
- C++20 :
failure
がmemory_order_release
,memory_order_acq_rel
ではないこと。failure
がsuccess
よりも強くないこと。
現在の値*object
とexpected
をバイトレベルで等値比較を行い、true
である場合は現在の値*object
をdesired
で置き換え、false
である場合は*expected
を現在の値*object
で置き換える。
バイト等値比較がtrue
の場合はsuccess
メモリオーダー、false
の場合はfailure
メモリオーダーに従って、アトミックに値の置き換えが行われる。
等値比較の結果が返される
投げない
この関数は、値が交換可能な場合でもCAS (compare-and-swap)操作が失敗する可能性がある。
atomic_compare_exchange_strong_explicit()
はより強い命令であり、交換可能な場合はCAS操作が常に成功する。
アーキテクチャによっては、この関数はatomic_compare_exchange_strong_explicit()
と等価だが、PowerPCやARMなどLL/SC命令を提供するアーキテクチャの場合、この関数はハードウェアの“弱いLL/SC命令”にて実装されうる。wikipedia:en:Load-link/store-conditional, wikipedia:Load-Link/Store-Conditional などを参照のこと。
通常、CAS操作は、CASが成功するまでループさせる。
しかし、もしCAS操作でSpurious Failureが発生しなければループさせる必要が無くなるといった状況であれば、atomic_compare_exchange_strong_explicit()
を使うことで効率良くCASを行うことができる。
逆に言えば、そのような状況でないなら常にループでatomic_compare_exchange_weak_explicit()
を利用すれば良い。
#include <iostream>
#include <atomic>
int main()
{
{
std::atomic<int> x(3);
// x == expectedなので、xは2に置き換えられる
int expected = 3;
bool result = std::atomic_compare_exchange_weak_explicit(&x, &expected, 2,
std::memory_order_acquire,
std::memory_order_acquire);
std::cout << std::boolalpha << result << " " << x.load() << " " << expected << std::endl;
}
{
std::atomic<int> x(3);
// x != expectedなので、expectedがxの値で置き換えられる
int expected = 1;
bool result = std::atomic_compare_exchange_weak_explicit(&x, &expected, 2,
std::memory_order_acquire,
std::memory_order_acquire);
std::cout << std::boolalpha << result << " " << x.load() << " " << expected << std::endl;
}
}
- std::atomic_compare_exchange_weak_explicit[color ff0000]
- x.load()[link /reference/atomic/atomic/load.md]
true 2 3
false 3 3
- C++11
- Clang: ??
- GCC: 4.7.0
- ICC: ??
- Visual C++: 2012, 2013
- atomic compare_exchange_weak/strong関数 - yohhoyの日記
- N2748 Strong Compare and Exchange
- cbloom rants: 07-14-11 - compare_exchange_strong vs compare_exchange_weak
- What does 'spurious failure' on a CAS mean? - StackOverflow
- “Strong” and “weak” hardware memory models - Sutter’s Mill
- P0558R1 Resolving
atomic<T>
named base class inconsistencies - P1831R1 Deprecating
volatile
: library- C++20での、
volatile
版への制約追加
- C++20での、