diff --git a/lang/cpp26.md b/lang/cpp26.md index 56ddce47d..076b5c095 100644 --- a/lang/cpp26.md +++ b/lang/cpp26.md @@ -225,7 +225,7 @@ C++26とは、2026年中に改訂される予定の、C++バージョンの通 ### 並行・並列・非同期処理 - [``](/reference/execution.md)に汎用的な非同期実行を管理するフレームワークを追加 - [`std::atomic`](/reference/atomic/atomic.md)オブジェクトに対する2つの値の最大値・最小値を取得する関数として、メンバ関数[`fetch_max()`](/reference/atomic/atomic/fetch_max.md)と[`fetch_min()`](/reference/atomic/atomic/fetch_min.md)、非メンバ関数として[`std::atomic_fetch_max`](/reference/atomic/atomic_fetch_max.md)、[`std::atomic_fetch_max_explicit`](/reference/atomic/atomic_fetch_max_explicit.md)、[`std::atomic_fetch_min`](/reference/atomic/atomic_fetch_min.md)、[`std::atomic_fetch_min_explicit`](/reference/atomic/atomic_fetch_min_explicit.md)を追加 -- [`std::atomic_ref`](/reference/atomic/atomic_ref.md)クラスに、参照するオブジェクトのアドレスを取得する[`address()`](/reference/atomic/atomic_ref/address.md.nolink)メンバ関数を追加 +- [`std::atomic_ref`](/reference/atomic/atomic_ref.md)クラスに、参照するオブジェクトのアドレスを取得する[`address()`](/reference/atomic/atomic_ref/address.md)メンバ関数を追加 - [`std::atomic`](/reference/atomic/atomic.md)クラスのテンプレートパラメータとしてCV修飾された型を禁止 - [`std::atomic_ref`](/reference/atomic/atomic_ref.md)クラスのテンプレートパラメータとして、CV修飾された型を受け取れるようにした (内部でCV修飾が外される) - [``](/reference/atomic.md)ライブラリのアトミック操作を`constexpr`対応 diff --git a/reference/atomic/atomic_ref.md b/reference/atomic/atomic_ref.md index d9f77af79..2323676da 100644 --- a/reference/atomic/atomic_ref.md +++ b/reference/atomic/atomic_ref.md @@ -59,6 +59,7 @@ C++26から、これらの特殊化はCV修飾された型に対しても行わ | [`wait`](atomic_ref/wait.md) | 起床されるまで待機する | C++20 | | [`notify_one`](atomic_ref/notify_one.md) | 待機しているスレッドをひとつ起床させる | C++20 | | [`notify_all`](atomic_ref/notify_all.md) | 待機している全てのスレッドを起床させる | C++20 | +| [`address`](atomic_ref/address.md) | 参照しているオブジェクトのアドレスを取得する | C++26 | ### 共通メンバ型 diff --git a/reference/atomic/atomic_ref/address.md b/reference/atomic/atomic_ref/address.md new file mode 100644 index 000000000..11afa684b --- /dev/null +++ b/reference/atomic/atomic_ref/address.md @@ -0,0 +1,111 @@ +# address +* atomic[meta header] +* std[meta namespace] +* atomic_ref[meta class] +* function[meta id-type] +* cpp26[meta cpp] + +```cpp +constexpr T* address() const noexcept; +``` + +## 概要 +参照しているオブジェクトのアドレスを取得する。 + +### この関数を必要とする状況 +#### データ構造の要素へのアトミックアクセス +配列の各要素にアトミックアクセスする際、[`std::atomic`](/reference/atomic/atomic.md)オブジェクトでは以下のように記述する。 + +```cpp +std::array, N> array; + +int fetch_add_idx(std::atomic* base, size_t i, int value) { + return base[i].fetch_add(value); +} +``` +* fetch_add[link fetch_add.md] + +これを`std::atomic_ref`で記述する場合、アトミック性をもたせてアクセスするには、この関数を使用して以下のようにする。 + +```cpp +int fetch_add_idx(std::atomic_ref 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 + +#### 必要なときにのみアトミックアクセスする +以下の例では、複数のスレッドが並行にメモリにアクセスし、カウンタをインクリメントすることでアクセス終了を知らせている。最後のスレッドはメモリにアクセスする余分な処理を実行する必要があるが、並行にメモリにアクセスするほかのスレッドがないため、これらのアクセスはアトミックである必要がない: + +```cpp +void thread(atomic_ref* data, atomic_ref 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`が参照するオブジェクトをアドレス値を返す + + +## 例外 +投げない + + +## 例 +```cpp example +#include +#include +#include + +void f(std::atomic_ref 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](/implementation.md#clang): 19.0 [mark noimpl] +- [GCC](/implementation.md#gcc): 14 [mark noimpl] +- [Visual C++](/implementation.md#visual_cpp): ?? + + +## 参照 +- [P2835R7 Expose `std::atomic_ref` 's object address](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2835r7.html)