名前空間
変種
操作

std::atomic_compare_exchange_weak, std::atomic_compare_exchange_strong, std::atomic_compare_exchange_weak_explicit, std::atomic_compare_exchange_strong_explicit

From cppreference.com
< cpp‎ | atomic
 
 
並行性サポートライブラリ
スレッド
(C++11)
(C++20)
this_thread 名前空間
(C++11)
(C++11)
(C++11)
協調的なキャンセル
排他制御
(C++11)
汎用ロック管理
(C++11)
(C++11)
(C++11)
(C++11)
(C++11)
条件変数
(C++11)
セマフォ
ラッチとバリア
(C++20)
(C++20)
future
(C++11)
(C++11)
(C++11)
(C++11)
安全なメモリ解放 (Safe Reclamation)
(C++26)
ハザードポインタ
アトミック型
(C++11)
(C++20)
アトミック型の初期化
(C++11)(C++20で非推奨)
(C++11)(C++20で非推奨)
メモリオーダー
(C++11)(C++26で非推奨)
アトミック操作のためのフリー関数
atomic_compare_exchange_weakatomic_compare_exchange_weak_explicitatomic_compare_exchange_strongatomic_compare_exchange_strong_explicit
(C++11)(C++11)(C++11)(C++11)
アトミックフラグのためのフリー関数
 
ヘッダー <atomic> で定義
template< class T >

bool atomic_compare_exchange_weak
    ( std::atomic<T>* obj, typename std::atomic<T>::value_type* expected,

      typename std::atomic<T>::value_type desired ) noexcept;
(1) (C++11以降)
template< class T >

bool atomic_compare_exchange_weak
    ( volatile std::atomic<T>* obj,
      typename std::atomic<T>::value_type* expected,

      typename std::atomic<T>::value_type desired ) noexcept;
(2) (C++11以降)
template< class T >

bool atomic_compare_exchange_strong
    ( std::atomic<T>* obj, typename std::atomic<T>::value_type* expected,

      typename std::atomic<T>::value_type desired ) noexcept;
(3) (C++11以降)
template< class T >

bool atomic_compare_exchange_strong
    ( volatile std::atomic<T>* obj,
      typename std::atomic<T>::value_type* expected,

      typename std::atomic<T>::value_type desired ) noexcept;
(4) (C++11以降)
template< class T >

bool atomic_compare_exchange_weak_explicit
    ( std::atomic<T>* obj, typename std::atomic<T>::value_type* expected,
      typename std::atomic<T>::value_type desired,

      std::memory_order success, std::memory_order failure ) noexcept;
(5) (C++11以降)
template< class T >

bool atomic_compare_exchange_weak_explicit
    ( volatile std::atomic<T>* obj,
      typename std::atomic<T>::value_type* expected,
      typename std::atomic<T>::value_type desired,

      std::memory_order success, std::memory_order failure ) noexcept;
(6) (C++11以降)
template< class T >

bool atomic_compare_exchange_strong_explicit
    ( std::atomic<T>* obj, typename std::atomic<T>::value_type* expected,
      typename std::atomic<T>::value_type desired,

      std::memory_order success, std::memory_order failure ) noexcept;
(7) (C++11以降)
template< class T >

bool atomic_compare_exchange_strong_explicit
    ( volatile std::atomic<T>* obj,
      typename std::atomic<T>::value_type* expected,
      typename std::atomic<T>::value_type desired,

      std::memory_order success, std::memory_order failure ) noexcept;
(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メンバ関数によって定義されています。

1,2) obj->compare_exchange_weak(*expected, desired)
3,4) obj->compare_exchange_strong(*expected, desired)
5,6) obj->compare_exchange_weak(*expected, desired, success, failure)
7,8) obj->compare_exchange_strong(*expected, desired, success, failure)

もし failuresuccess より強い場合、または 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 メンバ関数) [編集]
アトミックオブジェクトの値を非アトミックな引数でアトミックに置き換え、アトミックオブジェクトの古い値を返す
(関数テンプレート) [編集]
std::shared_ptr のアトミック操作を特化します。
(関数テンプレート)
C 言語のドキュメント (atomic_compare_exchange, atomic_compare_exchange_explicit)
English 日本語 中文(简体) 中文(繁體)