Skip to content

Commit 876474c

Browse files
committed
execution: bulk (#1384)
1 parent ae2af90 commit 876474c

File tree

3 files changed

+139
-1
lines changed

3 files changed

+139
-1
lines changed

reference/execution/execution.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ namespace std::execution {
121121
| [`execution::let_value`](execution/let_value.md) | 値完了結果から入れ子の非同期操作へ変換 (customization point object) | C++26 |
122122
| [`execution::let_error`](execution/let_error.md.nolink) | エラー完了結果から入れ子の非同期操作へ変換 (customization point object) | C++26 |
123123
| [`execution::let_stopped`](execution/let_stopped.md.nolink) | 停止完了を入れ子の非同期操作へ変換 (customization point object) | C++26 |
124-
| [`execution::bulk`](execution/bulk.md.nolink) | インデクス空間上で指定関数を連続実行 (customization point object) | C++26 |
124+
| [`execution::bulk`](execution/bulk.md) | インデクス空間上で指定関数を反復実行 (customization point object) | C++26 |
125125
| [`execution::split`](execution/split.md) | 入力Senderの値を複製回送信可能とする (customization point object) | C++26 |
126126
| [`execution::when_all`](execution/when_all.md) | 全ての入力Sender完了を待機 (customization point object) | C++26 |
127127
| [`execution::when_all_with_variant`](execution/when_all_with_variant.md) | 複数の値完了シグネチャをもつ全ての入力Sender完了を待機 (customization point object) | C++26 |
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
# bulk
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 bulk_t { unspecified };
10+
inline constexpr bulk_t bulk{};
11+
}
12+
```
13+
* unspecified[italic]
14+
15+
## 概要
16+
`bulk`は、インデクス空間の各インデクスに対してタスクを反復実行するSenderアダプタである。
17+
18+
`bulk`はパイプライン記法をサポートする。
19+
20+
21+
## 効果
22+
説明用の式`sndr`, `shape`, `f`に対して、型`Shape`を`decltype(auto(shape))`とする。下記いずれかの条件をみたすとき、呼び出し式`bulk(sndr, shape, f)`は不適格となる。
23+
24+
- `decltype((sndr))`が[`sender`](sender.md)を満たさない、もしくは
25+
- `Shape`が[`integral`](/reference/concepts/integral.md)を満たさない、もしくは
26+
- `decltype((f))`が[`movable-value`](../movable-value.md)を満たさないとき。
27+
28+
そうでなければ、呼び出し式`bulk(sndr, shape, f)`は`sndr`が1回だけ評価されることを除いて、下記と等価。
29+
30+
```cpp
31+
transform_sender(get-domain-early(sndr), make-sender(bulk, product-type{shape, f}, sndr))
32+
```
33+
* transform_sender[link transform_sender.md]
34+
* get-domain-early[link get-domain-early.md]
35+
* make-sender[link make-sender.md]
36+
* product-type[link product-type.md]
37+
38+
39+
### Senderアルゴリズムタグ `bulk`
40+
Senderアルゴリズム動作説明用のクラステンプレート[`impls-for`](impls-for.md)に対して、下記の特殊化が定義される。
41+
42+
```cpp
43+
namespace std::execution {
44+
template<>
45+
struct impls-for<bulk_t> : default-impls {
46+
static constexpr auto complete = see below;
47+
};
48+
}
49+
```
50+
* impls-for[link impls-for.md]
51+
* default-impls[link impls-for.md]
52+
* see below[italic]
53+
54+
`impls-for<bulk_t>::complete`メンバは、下記ラムダ式と等価な関数呼び出し可能なオブジェクトで初期化される。
55+
56+
```cpp
57+
[]<class Index, class State, class Rcvr, class Tag, class... Args>
58+
(Index, State& state, Rcvr& rcvr, Tag, Args&&... args) noexcept -> void requires see below {
59+
if constexpr (same_as<Tag, set_value_t>) {
60+
auto& [shape, f] = state;
61+
constexpr bool nothrow = noexcept(f(auto(shape), args...));
62+
TRY-EVAL(rcvr, [&]() noexcept(nothrow) {
63+
for (decltype(auto(shape)) i = 0; i < shape; ++i) {
64+
f(auto(i), args...);
65+
}
66+
Tag()(std::move(rcvr), std::forward<Args>(args)...);
67+
}());
68+
} else {
69+
Tag()(std::move(rcvr), std::forward<Args>(args)...);
70+
}
71+
}
72+
```
73+
* set_value_t[link set_value.md]
74+
* TRY-EVAL[link TRY-EVAL.md.nolink]
75+
* std::move[link /reference/utility/move.md]
76+
* see below[italic]
77+
78+
`Tag`[`set_value_t`](set_value.md)以外の型であるとき、もしくは式`f(auto(shape), args...)`が適格なときに限って、上記ラムダ式のrequires節が満たされる。
79+
80+
81+
## カスタマイゼーションポイント
82+
Senderアルゴリズム構築時および[Receiver](receiver.md)接続時に、関連付けられた実行ドメインに対して[`execution::transform_sender`](transform_sender.md)経由でSender変換が行われる。
83+
[デフォルト実行ドメイン](default_domain.md)では無変換。
84+
85+
説明用の式`out_sndr`を`bulk(sndr, shape, f)`の戻り値[Sender](sender.md)とし、式`rcvr`を式[`connect`](connect.md)`(out_sndr, rcvr)`が適格となる[Receiver](receiver.md)とする。式[`connect`](connect.md)`(out_sndr, rcvr)`は[開始(start)](start.md)時に下記を満たす非同期操作を生成しない場合、動作は未定義となる。
86+
87+
- 値完了操作において、パック`args`を入力[Sender](sender.md)の値完了結果データを参照する左辺値式としたとき、型`Shape`の半開区間`[0, Shape)`における全ての`i`に対して`f(i, args...)`を呼び出すこと。
88+
- `sndr`により送信された全ての完了操作を伝搬すること。
89+
90+
91+
## 備考
92+
非同期実行フレームワークで定義される[デフォルト実行ドメイン](default_domain.md)では、`bulk`に指定したタスク`f`は単一スレッド上で逐次実行される。
93+
94+
95+
## 例
96+
```cpp example
97+
#include <print>
98+
#include <execution>
99+
namespace ex = std::execution;
100+
101+
int main()
102+
{
103+
ex::sender auto sndr =
104+
ex::just()
105+
| ex::bulk(3, [](int i) {
106+
std::println("{}", i);
107+
});
108+
std::this_thread::sync_wait(sndr);
109+
}
110+
```
111+
* ex::bulk[color ff0000]
112+
* ex::sender[link sender.md]
113+
* ex::just[link just.md]
114+
* std::this_thread::sync_wait[link ../this_thread/sync_wait.md]
115+
116+
### 出力例
117+
```
118+
0
119+
1
120+
2
121+
```
122+
123+
124+
## バージョン
125+
### 言語
126+
- C++26
127+
128+
### 処理系
129+
- [Clang](/implementation.md#clang): ??
130+
- [GCC](/implementation.md#gcc): ??
131+
- [ICC](/implementation.md#icc): ??
132+
- [Visual C++](/implementation.md#visual_cpp): ??
133+
134+
135+
## 参照
136+
- [P2999R3 Sender Algorithm Customization](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2999r3.html)
137+
- [P2300R10 `std::execution`](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html)

reference/execution/execution/let_value.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ namespace std::execution {
114114
```
115115
* set_value[link set_value.md]
116116
* decayed-typeof[link decayed-typeof.md.nolink]
117+
* TRY-EVAL[link TRY-EVAL.md.nolink]
117118
* std::move[link /reference/utility/move.md]
118119
119120
説明用の式`sndr`と`env`に対して、型`Sndr`を`decltype((sndr))`とする。[`sender-for`](sender-for.md)`<Sndr, decayed-typeof<let_value>> == false`のとき、式`let_value.transform_env(sndr, env)`は不適格となる。

0 commit comments

Comments
 (0)