最終更新日時:
が更新

履歴 編集

function template
<atomic>

std::atomic_compare_exchange_weak(C++11)

namespace std {
  template <class T>
  bool atomic_compare_exchange_weak(volatile atomic<T>* object, T* expected, T desired) noexcept;

  template <class T>
  bool atomic_compare_exchange_weak(atomic<T>* object, T* expected, T desired) noexcept;
}

概要

弱い比較でアトミックに値を入れ替える

効果

memory_order_seq_cstのメモリオーダーにしたがって現在の値objectexpectedをバイトレベルで等値比較を行い、trueである場合は現在の値objectdesiredで置き換え、falseである場合はexpectedを現在の値で置き換える。

戻り値

等値比較の結果が返される

例外

投げない

備考

この関数は、値が交換可能な場合でもCAS (compare-and-swap)操作が失敗する可能性がある(Spurious Failure)。

atomic_compare_exchange_strong()はより強い命令であり、交換可能な場合はCAS操作が常に成功する。

アーキテクチャによっては、この関数はatomic_compare_exchange_strong()と等価だが、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()を使うことで効率良くCASを行うことができる。

逆に言えば、そのような状況でないなら常にループでatomic_compare_exchange_weak()を利用すれば良い。

#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(&x, &expected, 2);

    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(&x, &expected, 2);

    std::cout << std::boolalpha << result << " " << x.load() << " " << expected << std::endl;
  }
}

出力

true 2 3
false 3 3

バージョン

言語

  • C++11

処理系

参照