Skip to content

Commit a510758

Browse files
committed
execution: P3149R11 scope_token(#1510)
- scope_tokenコンセプト - simple_counting_scopeクラス(概要のみ) - counting_scopeクラス(概要のみ)
1 parent d589652 commit a510758

File tree

5 files changed

+349
-1
lines changed

5 files changed

+349
-1
lines changed

reference/execution/execution.md

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,15 +131,18 @@ namespace std::execution {
131131
| [`execution::into_variant`](execution/into_variant.md) | 複数の値完了シグネチャを単一[`variant`](/reference/variant/variant.md)型の値完了シグネチャに変換 (customization point object) | C++26 |
132132
| [`execution::stopped_as_optional`](execution/stopped_as_optional.md) | 入力Senderの停止完了を空の[`optional`](/reference/optional/optional.md)値完了に変換 (customization point object) | C++26 |
133133
| [`execution::stopped_as_error`](execution/stopped_as_error.md) | 入力Senderの停止完了をエラー完了に変換 (customization point object) | C++26 |
134+
| [`execution::associate`](execution/associate.md.nolink) | 非同期スコープへの関連付け (customization point object) | C++26 |
135+
| [`execution::spawn_future`](execution/spawn_future.md.nolink) | 非同期操作を早期開始 (customization point object) | C++26 |
134136
135137
### Senderコンシューマ
136138
137139
| 名前 | 説明 | 対応バージョン |
138140
|------|------|----------------|
139141
| [`this_thread::sync_wait`](this_thread/sync_wait.md) | 現在のスレッド上でSender完了を待機 (customization point object) | C++26 |
140142
| [`this_thread::sync_wait_with_variant`](this_thread/sync_wait_with_variant.md) | 現在のスレッド上でSender完了を待機 (customization point object) | C++26 |
143+
| [`execution::spawn`](execution/spawn.md.nolink) | 非同期操作を早期開始 (customization point object) | C++26 |
141144
142-
Senderコンシューマは名前空間 `std::this_thread` で定義される。
145+
Senderコンシューマは名前空間 `std::this_thread` および名前空間 `std::execution` で定義される。
143146
144147
### Sender/Receiverユーティリティ
145148
@@ -158,6 +161,14 @@ Senderコンシューマは名前空間 `std::this_thread` で定義される。
158161
| [`execution::as_awaitable`](execution/as_awaitable.md) | Senderを[Awaitable型](/lang/cpp20/coroutines.md)へ変換 (customization point object) | C++26 |
159162
| [`execution::with_awaitable_senders`](execution/with_awaitable_senders.md) | [Promise型](/lang/cpp20/coroutines.md)の基底クラス (class template) | C++26 |
160163
164+
### 実行スコープユーティリティ
165+
166+
| 名前 | 説明 | 対応バージョン |
167+
|------|------|----------------|
168+
| [`execution::scope_token`](execution/scope_token.md) | 非同期スコープトークン (concept) | C++26 |
169+
| [`execution::simple_counting_scope`](execution/simple_counting_scope.md) | カウント式非同期スコープ (class) | C++26 |
170+
| [`execution::counting_scope`](execution/counting_scope.md) | 停止要求可能なカウント式非同期スコープ (class) | C++26 |
171+
161172
### 並列Scheduler
162173
163174
| 名前 | 説明 | 対応バージョン |
@@ -176,6 +187,7 @@ Senderコンシューマは名前空間 `std::this_thread` で定義される。
176187
- [P0024R2 The Parallelism TS Should be Standardized](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0024r2.html)
177188
- [P2300R10 `std::execution`](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html)
178189
- [P2079R10 Parallel scheduler](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p2079r10.html)
190+
- [P3149R11 `async_scope` - Creating scopes for non-sequential concurrency](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3149r11.html)
179191
- [P3284R4 `write_env` and `unstoppable` Sender Adaptors](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3284r4.html)
180192
- [P3481R5 `std::execution::bulk()` issues](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3481r5.html)
181193
- [P3557R3 High-Quality Sender Diagnostics with Constexpr Exceptions](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3557r3.html)
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# counting_scope
2+
* execution[meta header]
3+
* class[meta id-type]
4+
* std::execution[meta namespace]
5+
* cpp26[meta cpp]
6+
7+
```cpp
8+
namespace std::execution {
9+
class counting_scope;
10+
}
11+
```
12+
13+
## 概要
14+
`counting_scope`は、停止要求を作成可能なカウント式の非同期スコープを表現する。
15+
16+
17+
## メンバ関数
18+
19+
| 名前 | 説明 | 対応バージョン |
20+
|------|------|----------------|
21+
| [`(constructor)`](counting_scope/op_constructor.md.nolink) | コンストラクタ | C++26 |
22+
| [`(destructor)`](counting_scope/op_destructor.md.nolink) | デストラクタ | C++26 |
23+
| [`get_token`](counting_scope/get_token.md.nolink) | 非同期スコープトークンを取得 | C++26 |
24+
| [`close`](counting_scope/close.md.nolink) | 非同期スコープを閉じる | C++26 |
25+
| [`join`](counting_scope/join.md.nolink) | 非同期スコープを合流する[Sender](sender.md)取得 | C++26 |
26+
| [`request_stop`](counting_scope/request_stop.md.nolink) | 停止要求を行う | C++26 |
27+
28+
## メンバ型
29+
30+
| 名前 | 説明 | 対応バージョン |
31+
|------|------|----------------|
32+
| [`token`](counting_scope/token.md.nolink) | 非同期スコープトークン型 | C++26 |
33+
34+
## 静的メンバ変数
35+
36+
| 名前 | 説明 | 対応バージョン |
37+
|------|------|----------------|
38+
| `constexpr size_t max_associations = implementation-defined;` | 関連付けの最大数 | C++26 |
39+
40+
41+
## バージョン
42+
### 言語
43+
- C++26
44+
45+
### 処理系
46+
- [Clang](/implementation.md#clang): ??
47+
- [GCC](/implementation.md#gcc): ??
48+
- [ICC](/implementation.md#icc): ??
49+
- [Visual C++](/implementation.md#visual_cpp): ??
50+
51+
52+
## 関連項目
53+
- [`execution::simple_counting_scope`](simple_counting_scope.md)
54+
55+
56+
## 参照
57+
- [P3149R11 `async_scope` - Creating scopes for non-sequential concurrency](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3149r11.html)
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
# scope_token
2+
* execution[meta header]
3+
* concept[meta id-type]
4+
* std::execution[meta namespace]
5+
* cpp26[meta cpp]
6+
7+
```cpp
8+
namespace std::execution {
9+
template<class Token>
10+
concept scope_token =
11+
copyable<Token> &&
12+
requires(const Token token) {
13+
{ token.try_associate() } -> same_as<bool>;
14+
{ token.disassociate() } noexcept -> same_as<void>;
15+
{ token.wrap(declval<test-sender>()) } -> sender_in<test-env>;
16+
};
17+
}
18+
```
19+
* copyable[link /reference/concepts/copyable.md]
20+
* sender_in[link sender_in.md]
21+
* test-sender[italic]
22+
* test-env[italic]
23+
24+
## 概要
25+
`scope_token`コンセプトは、[Sender](sender.md)と非同期スコープ間の関連付けを作成するために利用できる型`Token`に対する要件を定義する。
26+
27+
`test-sender`と`test-env`は、[`sender_in`](sender_in.md)`<test-sender, test-env>`のモデルである未規定の型とする。
28+
29+
30+
## モデル
31+
型`Token`は、次のとき`scope_token`のモデルとなる。
32+
33+
- `Token`型オブジェクトのコピー構築、ムーブ構築、コピー代入、ムーブ代入から例外送出しない、かつ
34+
- (const修飾の可能性のある)型`Token`の左辺値`token`が与えられたとき、型`decltype((sndr))`が[`sender`](sender.md)のモデルである全ての式`sndr`に対して、
35+
- `token.warp(sndr)`が有効な式、かつ
36+
- `decltype(token.warp(sndr))`は[`sender`](sender.md)のモデルであり、かつ
37+
- [`sender_in`](sender_in.md)`<decltype((sndr)), E>`のモデルである全ての`E`型に対して、[`completion_signatures_of_t`](completion_signatures_of_t.md)`<decltype(token.wrap(sndr)), E>`は[`completion_signatures_of_t`](completion_signatures_of_t.md)`<decltype((sndr)), E>`と同一の完了シグネチャを含むこと。
38+
39+
40+
## 例
41+
```cpp example
42+
#include <execution>
43+
namespace ex = std::execution;
44+
45+
int main()
46+
{
47+
ex::counting_scope scope;
48+
ex::scope_token auto token = scope.get_token();
49+
}
50+
```
51+
* ex::scope_token[color ff0000]
52+
* ex::counting_scope[link counting_scope.md]
53+
54+
### 出力
55+
```
56+
```
57+
58+
59+
## バージョン
60+
### 言語
61+
- C++26
62+
63+
### 処理系
64+
- [Clang](/implementation.md#clang): ??
65+
- [GCC](/implementation.md#gcc): ??
66+
- [ICC](/implementation.md#icc): ??
67+
- [Visual C++](/implementation.md#visual_cpp): ??
68+
69+
70+
## 関連項目
71+
- [`execution::associate`](associate.md.nolink)
72+
- [`execution::spawn_future`](spawn_future.md.nolink)
73+
- [`execution::spawn`](spawn.md.nolink)
74+
75+
76+
## 参照
77+
- [P3149R11 `async_scope` - Creating scopes for non-sequential concurrency](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3149r11.html)
Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
# simple_counting_scope
2+
* execution[meta header]
3+
* class[meta id-type]
4+
* std::execution[meta namespace]
5+
* cpp26[meta cpp]
6+
7+
```cpp
8+
namespace std::execution {
9+
class simple_counting_scope;
10+
}
11+
```
12+
13+
## 概要
14+
`simple_counting_scope`は、カウント式の非同期スコープを表現する。
15+
16+
17+
## クラス仕様
18+
`simple_counting_scope`型と[`counting_scope`](counting_scope.md)型による非同期スコープは関連付けカウントを管理する。
19+
20+
クラス動作説明用のメンバ変数として下記を保持する。
21+
22+
- `count` : `size_t`型の関連付けカウント値
23+
- `state` : `scope-state-type`列挙型(後述)の状態
24+
25+
26+
### 状態遷移
27+
説明専用の各種エンティティを下記の通り定義する。
28+
29+
- `Scope`型 : `simple_counting_scope`または`counting_scope`のいずれか
30+
- `scope`オブジェクト : `Scope`型のオブジェクト
31+
- `tkn`オブジェクト : `scope.get_token()`が返す`Scope::token`型のオブジェクト
32+
- `jsndr` : `scope.join()`が返す[Sender](sender.md)
33+
- `op` : `jsndr`を[Receiver](receiver.md)と接続して得られる[Operation State](operation_state.md)
34+
35+
```cpp
36+
enum scope-state-type { // exposition only
37+
unused, // exposition only
38+
open, // exposition only
39+
closed, // exposition only
40+
open-and-joining, // exposition only
41+
closed-and-joining, // exposition only
42+
unused-and-closed, // exposition only
43+
joined, // exposition only
44+
};
45+
```
46+
47+
`scope`はその生存期間中にさまざまな状態をとり、各状態で許可される操作とその結果を決定する:
48+
49+
- `unused` : 新しく構築されたオブジェクトは`unused`状態で開始する。
50+
- `open` : `scope``unused`状態にあるとき`tkn.try_associate()`が呼び出されると、`scope``open`状態に遷移する。
51+
- `open-and-joining` : `scope``unused`または`open`状態にあるとき[Operation State](operation_state.md)`op`[開始(start)](start.md)されると、`scope``open-and-joining`状態に遷移する。
52+
- `closed` : `scope``open`状態にあるとき`scope.close()`が呼び出されると、`scope``closed`状態に遷移する。
53+
- `unused-and-closed` : `scope``unused`状態にあるとき`scope.close()`が呼び出されると、`scope``unused-and-closed`状態に遷移する。
54+
- `closed-and-joining` : `scope``open-and-joining`状態にあるとき`scope.close()`が呼び出される、もしくは`scope``closed`または`unused-and-closed`状態にあるとき[Operation State](operation_state.md)`op`[開始(start)](start.md)されると、`scope``closed-and-joining`状態に遷移する。
55+
- `joined` : `scope``open-and-joining`または`closed-and-joining`状態にあるとき関連付けカウントがゼロに到達すると、`scope``joined`状態に遷移する。
56+
57+
58+
### Senderアルゴリズムタグ `scope-join-t`
59+
説明専用の[Senderアルゴリズムタグ型](tag_of_t.md)`scope-join-t`を定義する。
60+
61+
```cpp
62+
struct scope-join-t {}; // exposition only
63+
```
64+
65+
Senderアルゴリズム動作説明用のクラステンプレート[`impls-for`](impls-for.md)に対して、下記の特殊化が定義される。
66+
67+
```cpp
68+
namespace std::execution {
69+
template<>
70+
struct impls-for<scope-join-t> : default-impls {
71+
template<class Scope, class Rcvr>
72+
struct state { // exposition only
73+
struct rcvr-t { // exposition only
74+
using receiver_concept = receiver_t;
75+
76+
Rcvr& rcvr; // exposition only
77+
78+
void set_value() && noexcept {
79+
execution::set_value(std::move(rcvr));
80+
}
81+
82+
template<class E>
83+
void set_error(E&& e) && noexcept {
84+
execution::set_error(std::move(rcvr), std::forward<E>(e));
85+
}
86+
87+
void set_stopped() && noexcept {
88+
execution::set_stopped(std::move(rcvr));
89+
}
90+
91+
decltype(auto) get_env() const noexcept {
92+
return execution::get_env(rcvr);
93+
}
94+
};
95+
96+
using sched-sender = // exposition only
97+
decltype(schedule(get_scheduler(get_env(declval<Rcvr&>()))));
98+
using op-t = // exposition only
99+
connect_result_t<sched-sender, rcvr-t>;
100+
101+
Scope* scope; // exposition only
102+
Rcvr& receiver; // exposition only
103+
op-t op; // exposition only
104+
105+
state(Scope* scope, Rcvr& rcvr) // exposition only
106+
noexcept(nothrow-callable<connect_t, sched-sender, rcvr-t>)
107+
: scope(scope),
108+
receiver(rcvr),
109+
op(connect(schedule(get_scheduler(get_env(rcvr))), rcvr-t(rcvr))) {}
110+
111+
void complete() noexcept { // exposition only
112+
start(op);
113+
}
114+
115+
void complete-inline() noexcept { // exposition only
116+
set_value(std::move(receiver));
117+
}
118+
};
119+
120+
static constexpr auto get-state = // exposition only
121+
[]<class Rcvr>(auto&& sender, Rcvr& receiver)
122+
noexcept(is_nothrow_constructible_v<state<Rcvr>, data-type<decltype(sender)>, Rcvr&>) {
123+
auto[_, self] = sender;
124+
return state(self, receiver);
125+
};
126+
127+
static constexpr auto start = // exposition only
128+
[](auto& s, auto&) noexcept {
129+
if (s.scope->start-join-sender(s))
130+
s.complete-inline();
131+
};
132+
};
133+
}
134+
```
135+
* impls-for[link impls-for.md]
136+
* default-impls[link impls-for.md]
137+
* receiver_t[link receiver.md]
138+
* execution::set_value[link set_value.md]
139+
* execution::set_error[link set_error.md]
140+
* execution::set_stopped[link set_stopped.md]
141+
* execution::get_env[link get_env.md]
142+
* schedule[link schedule.md]
143+
* get_scheduler[link get_scheduler.md]
144+
* connect_result_t[link connect_result_t.md]
145+
* connect_t[link connect.md]
146+
* connect[link connect.md]
147+
* start[link start.md]
148+
* data-type[link data-type.md]
149+
* nothrow-callable[link /reference/functional/nothrow-callable.md]
150+
* is_nothrow_constructible_v[link /reference/type_traits/is_nothrow_constructible.md]
151+
* std::move[link /reference/utility/move.md]
152+
153+
154+
## メンバ関数
155+
156+
| 名前 | 説明 | 対応バージョン |
157+
|------|------|----------------|
158+
| [`(constructor)`](simple_counting_scope/op_constructor.md.nolink) | コンストラクタ | C++26 |
159+
| [`(destructor)`](simple_counting_scope/op_destructor.md.nolink) | デストラクタ | C++26 |
160+
| [`get_token`](simple_counting_scope/get_token.md.nolink) | 非同期スコープトークンを取得 | C++26 |
161+
| [`close`](simple_counting_scope/close.md.nolink) | 非同期スコープを閉じる | C++26 |
162+
| [`join`](simple_counting_scope/join.md.nolink) | 非同期スコープを合流する[Sender](sender.md)取得 | C++26 |
163+
164+
### 説明専用メンバ関数
165+
166+
| 名前 | 説明 | 対応バージョン |
167+
|------|------|----------------|
168+
| [`try-associate`](simple_counting_scope/try-associate.md.nolink) | 関連付けを試行 | C++26 |
169+
| [`disassociate`](simple_counting_scope/disassociate.md.nolink) | 関連付けを解除| C++26 |
170+
| [`start-join-sender`](simple_counting_scope/start-join-sender.md.nolink) | 合流[Sender](sender.md)を開始 | C++26 |
171+
172+
## メンバ型
173+
174+
| 名前 | 説明 | 対応バージョン |
175+
|------|------|----------------|
176+
| [`token`](simple_counting_scope/token.md.nolink) | 非同期スコープトークン型 | C++26 |
177+
178+
## 静的メンバ変数
179+
180+
| 名前 | 説明 | 対応バージョン |
181+
|------|------|----------------|
182+
| `constexpr size_t max_associations = implementation-defined;` | 関連付けの最大数 | C++26 |
183+
184+
185+
## バージョン
186+
### 言語
187+
- C++26
188+
189+
### 処理系
190+
- [Clang](/implementation.md#clang): ??
191+
- [GCC](/implementation.md#gcc): ??
192+
- [ICC](/implementation.md#icc): ??
193+
- [Visual C++](/implementation.md#visual_cpp): ??
194+
195+
196+
## 関連項目
197+
- [`execution::counting_scope`](counting_scope.md)
198+
199+
200+
## 参照
201+
- [P3149R11 `async_scope` - Creating scopes for non-sequential concurrency](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3149r11.html)

working_style.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ C++11以降対応については対応バージョンを明記します。バー
6868
| arithmetic type | 算術型 |
6969
| associative container(s) | 連想コンテナ |
7070
| asynchronous operation | 非同期操作 |
71+
| async scope | 非同期スコープ |
7172
| base class | 基底クラス |
7273
| bidirectional iterator | 双方向イテレータ |
7374
| bucket | バケット |

0 commit comments

Comments
 (0)