- atomic[meta header]
- std[meta namespace]
- atomic_ref[meta class]
- function[meta id-type]
- cpp26[meta cpp]
constexpr T* address() const noexcept;
参照しているオブジェクトのアドレスを取得する。
配列の各要素にアトミックアクセスする際、std::atomic
オブジェクトでは以下のように記述する。
std::array<std::atomic<int>, N> array;
int fetch_add_idx(std::atomic<int>* base, size_t i, int value) {
return base[i].fetch_add(value);
}
- fetch_add[link fetch_add.md]
これをstd::atomic_ref
で記述する場合、アトミック性をもたせてアクセスするには、この関数を使用して以下のようにする。
int fetch_add_idx(std::atomic_ref<int> base, size_t i, int value) {
int* p = base.address();
return std::atomic_ref{*(p+i)}.fetch_add(value);
}
- fetch_add[link fetch_add.md
以下の例では、複数のスレッドが並行にメモリにアクセスし、カウンタをインクリメントすることでアクセス終了を知らせている。最後のスレッドはメモリにアクセスする余分な処理を実行する必要があるが、並行にメモリにアクセスするほかのスレッドがないため、これらのアクセスはアトミックである必要がない:
void thread(atomic_ref<int>* data, atomic_ref<int> counter, int nthreads) {
data->fetch_add(42, memory_order_relaxed);
int* d = data->address(); // dataへの生ポインタを取得
data->~atomic_ref(); // このスレッドのデータへのatomic_refを破棄する
int pos = counter.fetch_add(1); // データの破棄が完了したことを伝える
if (pos != (nthreads - 1))
return;
// 最後のスレッド: アトミックアクセスする必要がない
int last_data = *d; // 非アトミックアクセス
// …
}
*this
が参照するオブジェクトをアドレス値を返す
投げない
#include <iostream>
#include <atomic>
#include <thread>
void f(std::atomic_ref<int> ar, int i) {
int* p = ar.address();
std::atomic_ref{p + i}.fetch_add(1);
}
int main()
{
int ar[3] = {};
std::thread t1{[&ar]{ f(std::atomic_ref{ar[0]}, 1); }};
std::thread t2{[&ar]{ f(std::atomic_ref{ar[0]}, 1); }};
t1.join();
t2.join();
std::cout << ar[1] << std::endl;
}
- address()[color ff0000]
- fetch_add[link fetch_add.md]
2
- C++26
- Clang: 19.0 [mark noimpl]
- GCC: 14 [mark noimpl]
- Visual C++: ??