std:: atomic_compare_exchange_weak, std:: atomic_compare_exchange_strong, std:: atomic_compare_exchange_weak_explicit, std:: atomic_compare_exchange_strong_explicit
|
定義済みヘッダー
<atomic>
|
||
|
template
<
class
T
>
bool
atomic_compare_exchange_weak
|
(1) | (C++11以降) |
|
template
<
class
T
>
bool
atomic_compare_exchange_weak
|
(2) | (C++11以降) |
|
template
<
class
T
>
bool
atomic_compare_exchange_strong
|
(3) | (C++11以降) |
|
template
<
class
T
>
bool
atomic_compare_exchange_strong
|
(4) | (C++11以降) |
|
template
<
class
T
>
bool
atomic_compare_exchange_weak_explicit
|
(5) | (C++11以降) |
|
template
<
class
T
>
bool
atomic_compare_exchange_weak_explicit
|
(6) | (C++11以降) |
|
template
<
class
T
>
bool
atomic_compare_exchange_strong_explicit
|
(7) | (C++11以降) |
|
template
<
class
T
>
bool
atomic_compare_exchange_strong_explicit
|
(8) | (C++11以降) |
オブジェクト表現 (C++20まで) 値表現 (C++20以降) を obj が指すオブジェクトと expected が指すオブジェクトの間でアトミックに比較し、それらがビット単位で等しい場合、前者を desired で置き換える(読み込み-修正-書き込み操作を実行)。そうでない場合、 obj が指す実際の値を * expected にロードする(ロード操作を実行)。
| オーバーロード | メモリモデル | |
|---|---|---|
| 読み込み-変更-書き込み操作 | 読み込み操作 | |
| (1-4) | std:: memory_order_seq_cst | std:: memory_order_seq_cst |
| (5-8) | success | failure |
これらの関数は、 member functions の観点から定義されており、 std::atomic のメンバ関数に基づいています:
failure が success よりも強い場合、または (C++17まで) std:: memory_order_release と std:: memory_order_acq_rel のいずれかである場合、動作は未定義です。
目次 |
パラメータ
| obj | - | テストおよび変更するアトミックオブジェクトへのポインタ |
| expected | - | アトミックオブジェクト内に存在することが期待される値へのポインタ |
| desired | - | 期待値と一致した場合にアトミックオブジェクトに格納する値 |
| success | - | 比較が成功した場合の読み込み-変更-書き込み操作のメモリ同期順序 |
| failure | - | 比較が失敗した場合のロード操作のメモリ同期順序 |
戻り値
比較の結果: true は * obj が * expected と等しい場合、 false はそれ以外の場合。
注記
std::atomic_compare_exchange_weak
および
std::atomic_compare_exchange_weak_explicit
(弱バージョン) は、偽の失敗を許容します。つまり、
*
obj
!
=
*
expected
が等しい場合でも、等しくないかのように動作することがあります。比較交換操作がループ内で行われる場合、これらの弱バージョンは一部のプラットフォームでより優れたパフォーマンスを発揮します。
弱い比較交換がループを必要とし、強い比較交換がそれを必要としない場合、
T
のオブジェクト表現が
パディングビット、
(C++20まで)
トラップビット、または同じ値に対して複数のオブジェクト表現を提供する場合(例:浮動小数点数のNaN)を除き、強い比較交換が推奨されます。これらのケースでは、弱い比較交換は通常、何らかの安定したオブジェクト表現に素早く収束するため有効です。
いくつかのメンバの値表現には参加するが他のメンバの値表現には参加しないビットを持つ共用体の場合、比較交換操作は常に失敗する可能性があります。なぜなら、そのようなパディングビットはアクティブなメンバの値表現に参加していない場合、不定値を持つからです。
|
オブジェクトの値表現に決して参加しないパディングビットは無視される。 |
(since C++20) |
例
比較交換操作は、ロックフリーデータ構造の基本的な構成要素として頻繁に使用されます。
#include <atomic> template<class T> struct node { T data; node* next; node(const T& data) : data(data), next(nullptr) {} }; template<class T> class stack { std::atomic<node<T>*> head; public: void push(const T& data) { node<T>* new_node = new node<T>(data); // put the current value of head into new_node->next new_node->next = head.load(std::memory_order_relaxed); // now make new_node the new head, but if the head // is no longer what's stored in new_node->next // (some other thread must have inserted a node just now) // then put that new head into new_node->next and try again while (!std::atomic_compare_exchange_weak_explicit( &head, &new_node->next, new_node, std::memory_order_release, std::memory_order_relaxed)) ; // the body of the loop is empty // note: the above loop is not thread-safe in at least // GCC prior to 4.8.3 (bug 60272), clang prior to 2014-05-05 (bug 18899) // MSVC prior to 2014-03-17 (bug 819819). See member function version for workaround } }; int main() { stack<int> s; s.push(1); s.push(2); s.push(3); }
不具合報告
以下の動作変更の欠陥報告書は、以前に公開されたC++規格に対して遡及的に適用されました。
| DR | 適用対象 | 公開時の動作 | 正しい動作 |
|---|---|---|---|
| P0558R1 | C++11 |
厳密な型一致が要求されていた。これは
T
が複数の引数から推論されていたため
|
T
は
obj からのみ推論される |
関連項目
|
アトミックオブジェクトの値を非アトミック引数と比較し、等しい場合はアトミック交換を、等しくない場合はアトミックロードを実行する
(
std::atomic<T>
の公開メンバ関数)
|
|
|
(C++11)
(C++11)
|
アトミックオブジェクトの値を非アトミック引数でアトミックに置き換え、アトミックオブジェクトの元の値を返す
(関数テンプレート) |
|
std::shared_ptrに対するアトミック操作を特殊化
(関数テンプレート) |
|
|
Cドキュメント
for
atomic_compare_exchange
,
atomic_compare_exchange_explicit
|
|