Skip to content

Commit 6477678

Browse files
committed
atomic_ref : C++26対応としてaddressメンバ関数を追加 (close #1387)
1 parent 21abedc commit 6477678

File tree

3 files changed

+113
-1
lines changed

3 files changed

+113
-1
lines changed

lang/cpp26.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ C++26とは、2026年中に改訂される予定の、C++バージョンの通
225225
### 並行・並列・非同期処理
226226
- [`<execution>`](/reference/execution.md)に汎用的な非同期実行を管理するフレームワークを追加
227227
- [`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)を追加
228-
- [`std::atomic_ref`](/reference/atomic/atomic_ref.md)クラスに、参照するオブジェクトのアドレスを取得する[`address()`](/reference/atomic/atomic_ref/address.md.nolink)メンバ関数を追加
228+
- [`std::atomic_ref`](/reference/atomic/atomic_ref.md)クラスに、参照するオブジェクトのアドレスを取得する[`address()`](/reference/atomic/atomic_ref/address.md)メンバ関数を追加
229229
- [`std::atomic`](/reference/atomic/atomic.md)クラスのテンプレートパラメータとしてCV修飾された型を禁止
230230
- [`std::atomic_ref`](/reference/atomic/atomic_ref.md)クラスのテンプレートパラメータとして、CV修飾された型を受け取れるようにした (内部でCV修飾が外される)
231231
- [`<atomic>`](/reference/atomic.md)ライブラリのアトミック操作を`constexpr`対応

reference/atomic/atomic_ref.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ C++26から、これらの特殊化はCV修飾された型に対しても行わ
5959
| [`wait`](atomic_ref/wait.md) | 起床されるまで待機する | C++20 |
6060
| [`notify_one`](atomic_ref/notify_one.md) | 待機しているスレッドをひとつ起床させる | C++20 |
6161
| [`notify_all`](atomic_ref/notify_all.md) | 待機している全てのスレッドを起床させる | C++20 |
62+
| [`address`](atomic_ref/address.md) | 参照しているオブジェクトのアドレスを取得する | C++26 |
6263
6364
6465
### 共通メンバ型
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
# address
2+
* atomic[meta header]
3+
* std[meta namespace]
4+
* atomic_ref[meta class]
5+
* function[meta id-type]
6+
* cpp26[meta cpp]
7+
8+
```cpp
9+
constexpr T* address() const noexcept;
10+
```
11+
12+
## 概要
13+
参照しているオブジェクトのアドレスを取得する。
14+
15+
### この関数を必要とする状況
16+
#### データ構造の要素へのアトミックアクセス
17+
配列の各要素にアトミックアクセスする際、[`std::atomic`](/reference/atomic/atomic.md)オブジェクトでは以下のように記述する。
18+
19+
```cpp
20+
std::array<std::atomic<int>, N> array;
21+
22+
int fetch_add_idx(std::atomic<int>* base, size_t i, int value) {
23+
return base[i].fetch_add(value);
24+
}
25+
```
26+
* fetch_add[link fetch_add.md]
27+
28+
これを`std::atomic_ref`で記述する場合、アトミック性をもたせてアクセスするには、この関数を使用して以下のようにする。
29+
30+
```cpp
31+
int fetch_add_idx(std::atomic_ref<int> base, size_t i, int value) {
32+
int* p = base.address();
33+
return std::atomic_ref{*(p+i)}.fetch_add(value);
34+
}
35+
```
36+
* fetch_add[link fetch_add.md
37+
38+
#### 必要なときにのみアトミックアクセスする
39+
以下の例では、複数のスレッドが並行にメモリにアクセスし、カウンタをインクリメントすることでアクセス終了を知らせている。最後のスレッドはメモリにアクセスする余分な処理を実行する必要があるが、並行にメモリにアクセスするほかのスレッドがないため、これらのアクセスはアトミックである必要がない:
40+
41+
```cpp
42+
void thread(atomic_ref<int>* data, atomic_ref<int> counter, int nthreads) {
43+
data->fetch_add(42, memory_order_relaxed);
44+
int* d = data->address(); // dataへの生ポインタを取得
45+
data->~atomic_ref(); // このスレッドのデータへのatomic_refを破棄する
46+
int pos = counter.fetch_add(1); // データの破棄が完了したことを伝える
47+
if (pos != (nthreads - 1))
48+
return;
49+
50+
// 最後のスレッド: アトミックアクセスする必要がない
51+
int last_data = *d; // 非アトミックアクセス
52+
// …
53+
}
54+
```
55+
56+
57+
## 戻り値
58+
`*this`が参照するオブジェクトをアドレス値を返す
59+
60+
61+
## 例外
62+
投げない
63+
64+
65+
## 例
66+
```cpp example
67+
#include <iostream>
68+
#include <atomic>
69+
#include <thread>
70+
71+
void f(std::atomic_ref<int> ar, int i) {
72+
int* p = ar.address();
73+
std::atomic_ref{p + i}.fetch_add(1);
74+
}
75+
76+
int main()
77+
{
78+
int ar[3] = {};
79+
80+
std::thread t1{[&ar]{ f(std::atomic_ref{ar[0]}, 1); }};
81+
std::thread t2{[&ar]{ f(std::atomic_ref{ar[0]}, 1); }};
82+
83+
t1.join();
84+
t2.join();
85+
86+
std::cout << ar[1] << std::endl;
87+
}
88+
```
89+
* address()[color ff0000]
90+
* fetch_add[link fetch_add.md]
91+
92+
93+
### 出力
94+
```
95+
2
96+
```
97+
98+
99+
## バージョン
100+
### 言語
101+
- C++26
102+
103+
104+
### 処理系
105+
- [Clang](/implementation.md#clang): 19.0 [mark noimpl]
106+
- [GCC](/implementation.md#gcc): 14 [mark noimpl]
107+
- [Visual C++](/implementation.md#visual_cpp): ??
108+
109+
110+
## 参照
111+
- [P2835R7 Expose `std::atomic_ref` 's object address](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2835r7.html)

0 commit comments

Comments
 (0)