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以降) |
pointed to by obj を、expected が指すオブジェクトの内容と比較し、それらがビット単位で等しい場合は、obj が指すオブジェクトを desired の値で置き換えます (Read-Modify-Write 操作)。それ以外の場合は、obj が指すオブジェクトの現在の値を *expected にロードします (Load 操作)。
| オーバーロード | Read-Modify-Write 操作のメモリモデル | |
|---|---|---|
| Read-Modify-Write 操作の | Load 操作の | |
| (1-4) | std::memory_order_seq_cst | std::memory_order_seq_cst |
| (5-8) | success | failure |
これらの関数は、std::atomic のメンバ関数によって定義されています。
もし failure が success より強い場合、または std::memory_order_release または std::memory_order_acq_rel のいずれかである場合(until C++17)、未定義の動作となります。
目次 |
[編集] パラメータ
| obj | - | テストおよび変更するアトミックオブジェクトへのポインタ |
| expected | - | アトミックオブジェクトに期待される値へのポインタ |
| desired | - | アトミックオブジェクトが期待どおりの場合に格納する値 |
| success | - | 比較が成功した場合の読み取り-変更-書き込み操作のメモリ同期順序 |
| failure | - | 比較が失敗した場合の読み込み操作のメモリ同期順序 |
[編集] 戻り値
比較の結果: true は *obj が *expected と等しかった場合、false はそうでない場合。
[編集] 注記
std::atomic_compare_exchange_weak および std::atomic_compare_exchange_weak_explicit (weak バージョン) は、一時的に失敗することが許容されます。つまり、*obj != *expected であっても、それらが等しいかのように動作することがあります。比較交換がループ内で行われる場合、一部のプラットフォームではパフォーマンスが向上します。
weak 比較交換がループを必要とし、strong 比較交換が不要な場合、strong 比較交換が優先されます。ただし、`T` のオブジェクト表現にパディングビット、(until C++20)、トラップビットが含まれる場合、または同じ値に対して複数のオブジェクト表現を提供する (例: 浮動小数点 NaN) 場合は、weak 比較交換は通常、安定したオブジェクト表現にすぐに収束するため、機能します。
一部のメンバーの値表現には参加するが、他のメンバーの値表現には参加しないビットを持つ共用体の場合、比較交換は常に失敗する可能性があります。これは、アクティブなメンバーの値表現に参加しない場合、そのようなパディングビットには不定な値が含まれるためです。
|
オブジェクトの値表現に決して参加しないパディングビットは無視されます。 |
(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> の public メンバ関数) | |
| (C++11)(C++11) |
アトミックオブジェクトの値を非アトミックな引数でアトミックに置き換え、アトミックオブジェクトの古い値を返す (関数テンプレート) |
| std::shared_ptr のアトミック操作を特化します。 (関数テンプレート) | |
| C 言語のドキュメント (atomic_compare_exchange, atomic_compare_exchange_explicit)
| |