Skip to content

Commit

Permalink
atomic_ref : C++26対応としてaddressメンバ関数を追加 (close #1387)
Browse files Browse the repository at this point in the history
  • Loading branch information
faithandbrave committed Dec 26, 2024
1 parent 21abedc commit 6477678
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 1 deletion.
2 changes: 1 addition & 1 deletion lang/cpp26.md
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ C++26とは、2026年中に改訂される予定の、C++バージョンの通
### 並行・並列・非同期処理
- [`<execution>`](/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修飾が外される)
- [`<atomic>`](/reference/atomic.md)ライブラリのアトミック操作を`constexpr`対応
Expand Down
1 change: 1 addition & 0 deletions reference/atomic/atomic_ref.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 |
### 共通メンバ型
Expand Down
111 changes: 111 additions & 0 deletions reference/atomic/atomic_ref/address.md
Original file line number Diff line number Diff line change
@@ -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<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`で記述する場合、アトミック性をもたせてアクセスするには、この関数を使用して以下のようにする。
```cpp
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

#### 必要なときにのみアトミックアクセスする
以下の例では、複数のスレッドが並行にメモリにアクセスし、カウンタをインクリメントすることでアクセス終了を知らせている。最後のスレッドはメモリにアクセスする余分な処理を実行する必要があるが、並行にメモリにアクセスするほかのスレッドがないため、これらのアクセスはアトミックである必要がない:

```cpp
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`が参照するオブジェクトをアドレス値を返す
## 例外
投げない
## 例
```cpp example
#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](/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)

0 comments on commit 6477678

Please sign in to comment.