Skip to content

Commit 331cc4e

Browse files
committed
execution: starts_on (#1384)
1 parent 1adf476 commit 331cc4e

9 files changed

Lines changed: 172 additions & 13 deletions

File tree

reference/execution/execution.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ namespace std::execution {
111111
| 名前 | 説明 | 対応バージョン |
112112
|------|------|----------------|
113113
| [`execution::sender_adaptor_closure`](execution/sender_adaptor_closure.md.nolink) | Senderアダプタ実装用クロージャ型(class template) | C++26 |
114-
| [`execution::starts_on`](execution/starts_on.md.nolink) | 指定Scheduler上で開始する (customization point object) | C++26 |
114+
| [`execution::starts_on`](execution/starts_on.md) | 指定Scheduler上で開始する (customization point object) | C++26 |
115115
| [`execution::continues_on`](execution/continues_on.md.nolink) | 指定Scheduler上で継続する (customization point object) | C++26 |
116116
| [`execution::on`](execution/on.md.nolink) | 指定Scheduler上で実行する (customization point object) | C++26 |
117117
| [`execution::schedule_from`](execution/schedule_from.md.nolink) | Sender完了に依存する作業をスケジュール (customization point object) | C++26 |

reference/execution/execution/into_variant.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ namespace std::execution {
8585
8686
8787
## カスタマイゼーションポイント
88-
[Sender](sender.md)`sndr`に[関連付けられた実行ドメイン](get-domain-early.md)`dom`に対して[`execution::transform_sender`](transform_sender.md)経由でSender変換が行われる。
88+
Senderアルゴリズム構築時に、入力[Sender](sender.md)`sndr`に[関連付けられた実行ドメイン](get-domain-early.md)に対して[`execution::transform_sender`](transform_sender.md)経由でSender変換が行われる。
8989
[デフォルト実行ドメイン](../execution/default_domain.md)では無変換。
9090
9191

reference/execution/execution/just.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ namespace std::execution {
2222
2323
2424
### Senderアルゴリズムタグ `just`
25-
Senderアルゴリズム動作説明用のクラステンプレート`impls-for`に対して、下記の特殊化が定義される。
25+
Senderアルゴリズム動作説明用のクラステンプレート[`impls-for`](impls-for.md)に対して、下記の特殊化が定義される。
2626
2727
```cpp
2828
namespace std::execution {

reference/execution/execution/read_env.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ namespace std::execution {
2323
2424
2525
### Senderアルゴリズムタグ
26-
Senderアルゴリズム動作説明用のクラステンプレート`impls-for`に対して、下記の特殊化が定義される。
26+
Senderアルゴリズム動作説明用のクラステンプレート[`impls-for`](impls-for.md)に対して、下記の特殊化が定義される。
2727
2828
```cpp
2929
namespace std::execution {
@@ -66,8 +66,9 @@ int main()
6666
* ex::read_env[color ff0000]
6767
* ex::sender[link sender.md]
6868
* ex::get_scheduler[link get_scheduler.md]
69-
* ex::starts_on[link starts_on.md.nolink]
69+
* ex::starts_on[link starts_on.md]
7070
* std::this_thread::sync_wait[link ../this_thread/sync_wait.md]
71+
* value()[link /reference/optional/optional/value.md]
7172
7273
### 出力
7374
```

reference/execution/execution/schedule.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,13 @@ namespace std::execution {
1313
* unspecified[italic]
1414
1515
## 概要
16-
`schedule`は、[Scheduler](scheduler.md)から[スケジュールSender](sender.md)を取得するSenderファクトリである。
16+
`schedule`は、[Scheduler](scheduler.md)からスケジュール[Sender](sender.md)を取得するSenderファクトリである。
17+
18+
### スケジュールSender
19+
`schedule(sch)`式の結果はスケジュールSender(schedule sender)と呼ばれる。
1720
1821
スケジュールSenderより生成される[非同期操作](operation_state.md)を開始すると、Schedulerに関連付けられた実行リソース上で空の[値完了関数](set_value.md)を呼び出す。
19-
スケジュールSenderの[値完了Scheduler](get_completion_scheduler.md)は、引数に指定したScheduler`sch`に等しい。
22+
スケジュールSenderの[値完了Scheduler](get_completion_scheduler.md)は、`schedule(sch)`式の引数に指定した[Scheduler](scheduler.md)`sch`に等しい。
2023
2124
2225
## 効果
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
# starts_on
2+
* execution[meta header]
3+
* cpo[meta id-type]
4+
* std::execution[meta namespace]
5+
* cpp26[meta cpp]
6+
7+
```cpp
8+
namespace std::execution {
9+
struct starts_on_t { unspecified };
10+
inline constexpr starts_on_t starts_on{};
11+
}
12+
```
13+
* unspecified[italic]
14+
15+
## 概要
16+
`starts_on`は、入力[Sender](sender.md)を指定[Scheduler](scheduler.md)に関連付けられた実行リソースに属する実行エージェント上で開始するSenderアダプタである。
17+
18+
19+
## 効果
20+
説明用の式`sch`と`sndr`に対して、`decltype((sch))`が[`scheduler`](scheduler.md)を満たさない、もしくは`decltype((sndr))`が[`sender`](sender.md)を満たさないとき、呼び出し式`starts_on(sch, sndr)`は不適格となる。
21+
22+
そうでなければ、呼び出し式`starts_on(sch, sndr)`は`sch`が1回だけ評価されることを除いて、下記と等価。
23+
24+
```cpp
25+
transform_sender(
26+
query-or-default(get_domain, sch, default_domain()),
27+
make-sender(starts_on, sch, sndr))
28+
```
29+
* transform_sender[link transform_sender.md]
30+
* query-or-default[link query-or-default.md.nolink]
31+
* get_domain[link get_domain.md]
32+
* default_domain()[link default_domain.md]
33+
* make-sender[link make-sender.md]
34+
35+
36+
### Senderアルゴリズムタグ `starts_on`
37+
説明用の式`out_sndr``env`に対して、型`OutSndr``decltype((out_sndr))`とする。[`sender-for`](sender-for.md)`<OutSndr, starts_on_t> == false`のとき、式`starts_on.transform_env(out_sndr, env)`および式`starts_on.transform_sender(out_sndr, env)`はいずれも不適格となる。
38+
39+
そうでなければ、下記の通り。
40+
41+
-`starts_on.transform_env(out_sndr, env)`は下記と等価。
42+
43+
```cpp
44+
auto&& [_, sch, _] = out_sndr;
45+
return JOIN-ENV(SCHED-ENV(sch), FWD-ENV(env));
46+
```
47+
* JOIN-ENV[link JOIN-ENV.md.nolink]
48+
* SCHED-ENV[link SCHED-ENV.md.nolink]
49+
* FWD-ENV[link ../forwarding_query.md]
50+
51+
- 式`starts_on.transform_sender(out_sndr, env)`は下記と等価。
52+
53+
```cpp
54+
auto&& [_, sch, sndr] = out_sndr;
55+
return let_value(
56+
schedule(sch),
57+
[sndr = std::forward_like<OutSndr>(sndr)]() mutable
58+
noexcept(is_nothrow_move_constructible_v<decay_t<OutSndr>>) {
59+
return std::move(sndr);
60+
});
61+
```
62+
* let_value[link let_value.md.nolink]
63+
* schedule[link schedule.md]
64+
* is_nothrow_move_constructible_v[link /reference/type_traits/is_nothrow_move_constructible.md]
65+
* decay_t[link /reference/type_traits/decay.md]
66+
* std::move[link /reference/utility/move.md]
67+
68+
69+
## カスタマイゼーションポイント
70+
Senderアルゴリズム構築時に、[Scheduler](scheduler.md)`sch`[関連付けられた実行ドメイン](query-or-default.md.nolink)に対して[`execution::transform_sender`](transform_sender.md)経由でSender変換が行われる。
71+
[デフォルト実行ドメイン](../execution/default_domain.md)では無変換。
72+
73+
[Receiver](receiver.md)との[接続(connect)](connect.md)時に、[関連付けられた実行ドメイン](get-domain-late.md)に対して[`execution::transform_sender`](transform_sender.md)経由でSender変換が行われる。
74+
[デフォルト実行ドメイン](../execution/default_domain.md)では`starts_on.transform_sender(out_sndr, env)`が呼ばれ、前述仕様通りのSenderへと変換される。
75+
76+
説明用の式`out_sndr``starts_on(sch, sndr)`の戻り値[Sender](sender.md)とし、型`OutSndr``decltype((out_sndr))`とする。式`out_rcvr`[`sender_in`](sender_in.md)`<OutSndr, Env> == true`となる[環境](../queryable.md)`Env`に関連付けられた[Receiver](receiver.md)とする。`out_sndr``out_rcvr`との[接続(connect)](connect.md)結果[Operation State](operation_state.md)への左辺値参照を`op`としたとき、
77+
78+
- 呼び出し[`start`](start.md)`(op)`は、[Scheduler](scheduler.md)`sch`に関連づけられた実行リソースに属する実行エージェント上で入力[Sender](sender.md)`sndr`を開始すべき。
79+
- `sch`上でのスケジューリングが失敗した場合、未規定の実行エージェント上で`out_rcvr`[エラー完了](set_error.md)が行われるべき。
80+
81+
82+
##
83+
```cpp example
84+
#include <thread>
85+
#include <print>
86+
#include <execution>
87+
namespace ex = std::execution;
88+
89+
int main()
90+
{
91+
ex::run_loop loop;
92+
std::jthread worker{[&]{
93+
std::println("start worker#{}", std::this_thread::get_id());
94+
loop.run();
95+
}};
96+
97+
ex::scheduler auto sch = loop.get_scheduler();
98+
ex::sender auto sndr =
99+
ex::starts_on(sch, ex::just(21))
100+
| ex::then([](int n) {
101+
std::println("on worker#{}", std::this_thread::get_id());
102+
return n * 2;
103+
});
104+
105+
std::println("main#{}", std::this_thread::get_id());
106+
107+
auto [val] = std::this_thread::sync_wait(std::move(sndr)).value();
108+
std::println("val={}", val);
109+
110+
loop.finish();
111+
}
112+
```
113+
* ex::starts_on[color ff0000]
114+
* ex::run_loop[link run_loop.md]
115+
* ex::sender[link sender.md]
116+
* ex::scheduler[link scheduler.md]
117+
* ex::then[link then.md]
118+
* get_scheduler()[link run_loop/get_scheduler.md]
119+
* run()[link run_loop/run.md]
120+
* finish()[link run_loop/finish.md]
121+
* std::this_thread::sync_wait[link ../this_thread/sync_wait.md]
122+
* value()[link /reference/optional/optional/value.md]
123+
* std::move[link /reference/utility/move.md]
124+
* std::this_thread::get_id()[link /reference/thread/this_thread/get_id.md]
125+
126+
127+
### 出力例
128+
```
129+
main#126057012819776
130+
start worker#126057007023680
131+
on worker#126057007023680
132+
val=42
133+
```
134+
135+
136+
## バージョン
137+
### 言語
138+
- C++26
139+
140+
### 処理系
141+
- [Clang](/implementation.md#clang): ??
142+
- [GCC](/implementation.md#gcc): ??
143+
- [ICC](/implementation.md#icc): ??
144+
- [Visual C++](/implementation.md#visual_cpp): ??
145+
146+
147+
## 関連項目
148+
- [`execution::schedule`](schedule.md)
149+
- [`execution::continues_on`](continues_on.md.nolink)
150+
- [`execution::on`](on.md.nolink)
151+
152+
153+
## 参照
154+
- [P2999R3 Sender Algorithm Customization](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2999r3.html)
155+
- [P2300R10 `std::execution`](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html)

reference/execution/execution/then.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ transform_sender(get-domain-early(sndr), make-sender(then, f, sndr))
3232

3333

3434
### Senderアルゴリズムタグ `then`
35-
Senderアルゴリズム動作説明用のクラステンプレート`impls-for`に対して、下記の特殊化が定義される。
35+
Senderアルゴリズム動作説明用のクラステンプレート[`impls-for`](impls-for.md)に対して、下記の特殊化が定義される。
3636

3737
```cpp
3838
namespace std::execution {
@@ -60,7 +60,7 @@ namespace std::execution {
6060
6161
6262
## カスタマイゼーションポイント
63-
[Sender](sender.md)`sndr`に[関連付けられた実行ドメイン](get-domain-early.md)`dom`に対して[`execution::transform_sender`](transform_sender.md)経由でSender変換が行われる。
63+
Senderアルゴリズム構築時に、入力[Sender](sender.md)`sndr`に[関連付けられた実行ドメイン](get-domain-early.md)に対して[`execution::transform_sender`](transform_sender.md)経由でSender変換が行われる。
6464
[デフォルト実行ドメイン](../execution/default_domain.md)では無変換。
6565
6666
戻り値の[Sender](sender.md)`out_sndr`が下記を満たさない場合、呼び出し式`then(sndr, f)`の動作は未定義となる。

reference/execution/this_thread/sync_wait.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ namespace std::this_thread {
1313
* unspecified[italic]
1414
1515
## 概要
16-
`sync_wait`は、[Sender](../execution/sender.md)が完了するまで現在のスレッドをブロックし、非同期操作の結果を取得するSenderコンシューマである。
16+
`sync_wait`は、入力[Sender](../execution/sender.md)が完了するまで現在のスレッドをブロックし、非同期操作の結果を取得するSenderコンシューマである。
1717
1818
`sync_wait`は入力Senderが[値完了シグネチャ](../execution/set_value.md)を1個だけ持つことを要求する。
1919
値完了シグネチャが複数存在する場合は[`sync_wait_with_variant`](sync_wait_with_variant.md)アルゴリズムを利用する。
@@ -85,7 +85,7 @@ return std::move(state.result);
8585

8686

8787
## カスタマイゼーションポイント
88-
[Sender](../execution/sender.md)`sndr`に[関連付けられた実行ドメイン](../execution/get-domain-early.md)`dom`に対して、
88+
入力[Sender](../execution/sender.md)`sndr`[関連付けられた実行ドメイン](../execution/get-domain-early.md)`dom`に対して、
8989
[`execution::apply_sender`](../execution/apply_sender.md)経由で`dom.apply_sender(sync_wait, sndr)`が呼ばれる。
9090

9191
[デフォルト実行ドメイン](../execution/default_domain.md)では、`sync_wait.apply_sender(sndr)`が呼ばれる。

reference/execution/this_thread/sync_wait_with_variant.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ namespace std::this_thread {
1313
* unspecified[italic]
1414
1515
## 概要
16-
`sync_wait_with_variant`は、[Sender](../execution/sender.md)が完了するまで現在のスレッドをブロックし、非同期操作の結果を取得するSenderコンシューマである。
16+
`sync_wait_with_variant`は、入力[Sender](../execution/sender.md)が完了するまで現在のスレッドをブロックし、非同期操作の結果を取得するSenderコンシューマである。
1717
1818
`sync_wait_with_variant`は入力Senderが複数の[値完了シグネチャ](../execution/set_value.md)を持つケースに対応する。
1919
値完了シグネチャが1個だけの場合は[`sync_wait`](sync_wait.md)アルゴリズムを利用する。
@@ -76,7 +76,7 @@ return result_type(nullopt);
7676

7777

7878
## カスタマイゼーションポイント
79-
[Sender](../execution/sender.md)`sndr`に[関連付けられた実行ドメイン](../execution/get-domain-early.md)`dom`に対して、
79+
入力[Sender](../execution/sender.md)`sndr`[関連付けられた実行ドメイン](../execution/get-domain-early.md)`dom`に対して、
8080
[`execution::apply_sender`](../execution/apply_sender.md)経由で`dom.apply_sender(sync_wait_with_variant, sndr)`が呼ばれる。
8181

8282
[デフォルト実行ドメイン](../execution/default_domain.md)では、`sync_wait_with_variant.apply_sender(sndr)`が呼ばれる。

0 commit comments

Comments
 (0)