web-dev-qa-db-ja.com

最大値をアトミックに更新するにはどうすればよいですか?

シリアルコードでは、最大値の更新は次の方法で簡単に実行できます。

template<typename T>
void update_maximum(T& maximum_value, T const& value) noexcept
{
  if(value > maximum_value) maximum_value = value;
}

ただし、最大値を保持するatomic<T>変数に対してこれをどのように行う必要がありますか。

template<typename T>
void update_maximum(std::atomic<T>& maximum_value, T const& value) noexcept
{
   // want a lock-free, thread-safe implementation
}

明らかに、別のスレッドがロードとストアの間でmaximum_valueを変更する可能性があるため、シリアルバージョンのコードは機能しません。 compare_exchange==ではなく>を比較します)を使用してこれを実装できますか?どうやって?

明示的なロックは許可されていないことに注意してください(許可されているロックは、std::atomic<T>の実装に付属しているロックのみです)。

37
Walter

単一の操作では不可能なようですが、最終的に成功するか、アトミック変数の値がvalueより大きくなるまで、これを実行しようとするループを作成できます。

template<typename T>
void update_maximum(std::atomic<T>& maximum_value, T const& value) noexcept
{
    T prev_value = maximum_value;
    while(prev_value < value &&
            !maximum_value.compare_exchange_weak(prev_value, value))
        {}
}
41
zch