yohhoyの日記

技術的メモをしていきたい日記

atomic compare_exchange_weak/strong関数

C++11標準ライブラリのatomic操作関数compare_exchange_weakcompare_exchange_strongについてメモ。

両関数ともに変数のatomicなCAS(compare-and-swap)操作を提供する。weak版とstrong版との動作仕様は、weak版では “交換可能な場合でもCAS操作失敗する可能性がある(spurious failure)”*1 が、strong版では “交換可能な場合は常にCAS操作が成功する” という点のみ異なる。当初はweak版のみが定義されていたが、強いCAS操作命令をもつハードウェア性能を生かすために、N2748にてstrong版が追加された。

利用指針は下記の通り。大抵のケースでは ループ構造+compare_exchange_weakでよい(はず)。

  • アルゴリズム上、CAS操作をループで括る必要があればcompare_exchange_weakを利用する。(例:一般的なLock-Freeアルゴリズム実装など)
  • アルゴリズム上の制約が無く、かつ Spurious failure を許容しない場合はcompare_exchange_strongを利用する。(例:pthread spinlock相当のtrylock操作実装*2

N3337 29.6.5/p25より引用。

Remark: A weak compare-and-exchange operation may fail spuriously. That is, even when the contents of memory referred to by expected and object are equal, it may return false and store back to expected the same memory contents that were originally there. [Note: This spurious failure enables implementation of compare-and-exchange on a broader class of machines, e.g., load-locked store-conditional machines. A consequence of spurious failure is that nearly all uses of weak compareand-exchange will be in a loop.
When a compare-and-exchange is in a loop, the weak version will yield better performance on some platforms. When a weak compare-and-exchange would require a loop and a strong one would not, the strong one is preferable. -- end note]

関連URL

*1:PowerPCやARMなどLL/SC命令を提供するアーキテクチャの場合、compare_exchange_weak はハードウェアの “弱いLL/SC命令” にて実装されうる。wikipedia:en:Load-link/store-conditional, wikipedia:Load-Link/Store-Conditional などを参照のこと。

*2:C++11標準 mutex のtry_lock操作セマンティクスであれば、その内部実装を compare_exchange_weak で行っても良い。