関数はatomic_compare_exchange_XXX
「期待される」引数を観測値で更新するため、ループは次のようになります。
expected = current;
do {
desired = f(expected);
} while (!current.atomic_compare_exchange_weak(expected, desired));
目的の値が期待値から独立している場合、このループは次のようになります。
desired = ...;
expected = current;
while (current.atomic_compare_exchange_weak(expected, desired))
;
いくつかのセマンティクスを追加しましょう。複数のスレッドがこれを同時に実行しているとしましょう。いずれの場合desired
も、現在のスレッドのゼロ以外の ID であり、current
一部のスレッドが確実にクリーンアップ タスクを実行するように相互排除を提供するために使用されます。どのスレッドかはあまり気にしませんが、一部のスレッドが確実にアクセスできるようにしたいと考えています (また、他のスレッドが から ID を読み取って勝者を監視できる可能性もありますcurrent
)。
以下を使用して、目的のセマンティクスを実現できます。
expected = 0;
if (current.atomic_compare_exchange_strong(expected, this_thread)) {
// I'm the winner
do_some_cleanup_thing();
current = 0;
} else {
std::cout << expected << " is the winner\n";
}
これは、偽の障害が発生する可能性があるためatomic_compare_exchange_weak
、 と同じ効果を達成するためにループが必要になるケースです。atomic_compare_exchange_strong
expected = 0;
while(!current.atomic_compare_exchange_weak(expected, this_thread)
&& expected == 0))
;
if (expected == this_thread) {
do_some_cleanup_thing();
current = 0;
} else {
std::cout << expected << " is the winner\n";
}
atomic_compare_exchange_strong
標準では、この場合、forでループするよりも実装がより効率的なコードを提供する可能性があることが示唆されています..._weak
(§29.6.5/25 [atomics.types.operations.req])。