Init
This commit is contained in:
222
cppdraft/exec/bulk.md
Normal file
222
cppdraft/exec/bulk.md
Normal file
@@ -0,0 +1,222 @@
|
||||
[exec.bulk]
|
||||
|
||||
# 33 Execution control library [[exec]](./#exec)
|
||||
|
||||
## 33.9 Senders [[exec.snd]](exec.snd#exec.bulk)
|
||||
|
||||
### 33.9.12 Sender adaptors [[exec.adapt]](exec.adapt#exec.bulk)
|
||||
|
||||
#### 33.9.12.11 execution::bulk, execution::bulk_chunked, and execution::bulk_unchunked [exec.bulk]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L4109)
|
||||
|
||||
bulk, bulk_chunked, and bulk_unchunked run a task repeatedly for every index in an index space[.](#1.sentence-1)
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L4113)
|
||||
|
||||
The names bulk, bulk_chunked, and bulk_unchunked denote pipeable sender adaptor objects[.](#2.sentence-1)
|
||||
|
||||
Let *bulk-algo* be eitherbulk, bulk_chunked, or bulk_unchunked[.](#2.sentence-2)
|
||||
|
||||
For subexpressions sndr, policy, shape, and f,
|
||||
letPolicy be remove_cvref_t<decltype(policy)>,Shape be decltype(auto(shape)), andFunc be decay_t<decltype((f))>[.](#2.sentence-3)
|
||||
|
||||
If
|
||||
|
||||
- [(2.1)](#2.1)
|
||||
|
||||
decltype((sndr)) does not satisfy [sender](exec.snd.concepts#concept:sender "33.9.3 Sender concepts [exec.snd.concepts]"), or
|
||||
|
||||
- [(2.2)](#2.2)
|
||||
|
||||
is_execution_policy_v<Policy> is false, or
|
||||
|
||||
- [(2.3)](#2.3)
|
||||
|
||||
Shape does not satisfy [integral](concepts.arithmetic#concept:integral "18.4.7 Arithmetic concepts [concepts.arithmetic]"), or
|
||||
|
||||
- [(2.4)](#2.4)
|
||||
|
||||
Func does not model [copy_constructible](concept.copyconstructible#concept:copy_constructible "18.4.14 Concept copy_constructible [concept.copyconstructible]"),
|
||||
|
||||
*bulk-algo*(sndr, policy, shape, f) is ill-formed[.](#2.sentence-4)
|
||||
|
||||
[3](#3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L4136)
|
||||
|
||||
Otherwise,
|
||||
the expression *bulk-algo*(sndr, policy, shape, f) is expression-equivalent to:
|
||||
|
||||
transform_sender(*get-domain-early*(sndr), *make-sender*(*bulk-algo*, *product-type*<*see below*, Shape, Func>{policy, shape, f}, sndr)) except that sndr is evaluated only once[.](#3.sentence-2)
|
||||
|
||||
The first template argument of *product-type* is Policy if Policy models [copy_constructible](concept.copyconstructible#concept:copy_constructible "18.4.14 Concept copy_constructible [concept.copyconstructible]"), andconst Policy& otherwise[.](#3.sentence-3)
|
||||
|
||||
[4](#4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L4150)
|
||||
|
||||
Let sndr and env be subexpressions such thatSndr is decltype((sndr))[.](#4.sentence-1)
|
||||
|
||||
If [*sender-for*](exec.snd.concepts#concept:sender-for "33.9.3 Sender concepts [exec.snd.concepts]")<Sndr, bulk_t> is false, then
|
||||
the expression bulk.transform_sender(sndr, env) is ill-formed;
|
||||
otherwise, it is equivalent to:auto [_, data, child] = sndr;auto& [policy, shape, f] = data;auto new_f = [func = std::move(f)](Shape begin, Shape end, auto&&... vs)noexcept(noexcept(f(begin, vs...))) {while (begin != end) func(begin++, vs...);}return bulk_chunked(std::move(child), policy, shape, std::move(new_f));
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
This causes the bulk(sndr, policy, shape, f) sender to be
|
||||
expressed in terms of bulk_chunked(sndr, policy, shape, f) when
|
||||
it is connected to a receiver whose
|
||||
execution domain does not customize bulk[.](#4.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[5](#5)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L4172)
|
||||
|
||||
The exposition-only class template *impls-for* ([[exec.snd.expos]](exec.snd.expos "33.9.2 Exposition-only entities"))
|
||||
is specialized for bulk_chunked_t as follows:
|
||||
|
||||
[ð](#lib:impls-for%3cbulk_chunked_t%3e)
|
||||
|
||||
namespace std::execution {template<>struct *impls-for*<bulk_chunked_t> : *default-impls* {static constexpr auto *complete* = *see below*; template<class Sndr, class... Env>static consteval void *check-types*(); };}
|
||||
|
||||
The member *impls-for*<bulk_chunked_t>::*complete* is initialized with a callable object equivalent to the following lambda:[]<class Index, class State, class Rcvr, class Tag, class... Args>(Index, State& state, Rcvr& rcvr, Tag, Args&&... args) noexcept-> void requires *see below* {if constexpr ([same_as](concept.same#concept:same_as "18.4.2 Concept same_as [concept.same]")<Tag, set_value_t>) {auto& [policy, shape, f] = state; constexpr bool nothrow = noexcept(f(auto(shape), auto(shape), args...)); *TRY-EVAL*(rcvr, [&]() noexcept(nothrow) { f(static_cast<decltype(auto(shape))>(0), auto(shape), args...);
|
||||
Tag()(std::move(rcvr), std::forward<Args>(args)...); }()); } else { Tag()(std::move(rcvr), std::forward<Args>(args)...); }}
|
||||
|
||||
The expression in the [*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [temp.pre]") of the lambda above istrue if and only
|
||||
if Tag denotes a type other than set_value_t or
|
||||
if the expression f(auto(shape), auto(shape), args...) is well-formed[.](#5.sentence-3)
|
||||
|
||||
[6](#6)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L4210)
|
||||
|
||||
The exposition-only class template *impls-for* ([[exec.snd.expos]](exec.snd.expos "33.9.2 Exposition-only entities"))
|
||||
is specialized for bulk_unchunked_t as follows:namespace std::execution {template<>struct *impls-for*<bulk_unchunked_t> : *default-impls* {static constexpr auto *complete* = *see below*; };}
|
||||
|
||||
The member *impls-for*<bulk_unchunked_t>::*complete* is initialized with a callable object equivalent to the following lambda:[]<class Index, class State, class Rcvr, class Tag, class... Args>(Index, State& state, Rcvr& rcvr, Tag, Args&&... args) noexcept-> void requires *see below* {if constexpr ([same_as](concept.same#concept:same_as "18.4.2 Concept same_as [concept.same]")<Tag, set_value_t>) {auto& [shape, f] = state; constexpr bool nothrow = noexcept(f(auto(shape), args...)); *TRY-EVAL*(rcvr, [&]() noexcept(nothrow) {for (decltype(auto(shape)) i = 0; i < shape; ++i) { f(auto(i), args...); } Tag()(std::move(rcvr), std::forward<Args>(args)...); }()); } else { Tag()(std::move(rcvr), std::forward<Args>(args)...); }}
|
||||
|
||||
The expression in the [*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [temp.pre]") of the lambda above
|
||||
is true if and only
|
||||
if Tag denotes a type other than set_value_t or
|
||||
if the expression f(auto(shape), args...) is well-formed[.](#6.sentence-3)
|
||||
|
||||
[ð](#lib:check-types,impls-for%3cbulk_t%3e)
|
||||
|
||||
`template<class Sndr, class... Env>
|
||||
static consteval void check-types();
|
||||
`
|
||||
|
||||
[7](#7)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L4253)
|
||||
|
||||
*Effects*: Equivalent to:auto cs = get_completion_signatures<*child-type*<Sndr>, *FWD-ENV-T*(Env)...>();auto fn = []<class... Ts>(set_value_t(*)(Ts...)) {if constexpr (<remove_cvref_t<*data-type*<Sndr>>, Ts&...>)throw *unspecified-exception*();};
|
||||
cs.*for-each*(*overload-set*(fn, [](auto){})); where *unspecified-exception* is
|
||||
a type derived from exception[.](#7.sentence-1)
|
||||
|
||||
[8](#8)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L4268)
|
||||
|
||||
Let the subexpression out_sndr denote
|
||||
the result of the invocation*bulk-algo*(sndr, policy, shape, f) or
|
||||
an object equal to such, and
|
||||
let the subexpression rcvr denote a receiver
|
||||
such that the expression connect(out_sndr, rcvr) is well-formed[.](#8.sentence-1)
|
||||
|
||||
The expression connect(out_sndr, rcvr) has undefined behavior
|
||||
unless it creates an asynchronous operation ([[exec.async.ops]](exec.async.ops "33.3 Asynchronous operations")) that,
|
||||
when started:
|
||||
|
||||
- [(8.1)](#8.1)
|
||||
|
||||
If sndr has a successful completion, whereargs is a pack of lvalue subexpressions
|
||||
referring to the value completion result datums of sndr, or
|
||||
decayed copies of those values if they model [copy_constructible](concept.copyconstructible#concept:copy_constructible "18.4.14 Concept copy_constructible [concept.copyconstructible]"),
|
||||
then:
|
||||
|
||||
* [(8.1.1)](#8.1.1)
|
||||
|
||||
If out_sndr also completes successfully, then:
|
||||
|
||||
+
|
||||
[(8.1.1.1)](#8.1.1.1)
|
||||
for bulk,
|
||||
invokes f(i, args...) for every i of type Shape from 0 to shape;
|
||||
|
||||
+
|
||||
[(8.1.1.2)](#8.1.1.2)
|
||||
for bulk_unchunked,
|
||||
invokes f(i, args...) for every i of type Shape from 0 to shape;
|
||||
*Recommended practice*: The underlying scheduler should execute each iteration
|
||||
on a distinct execution agent[.](#8.1.1.2.sentence-2)
|
||||
|
||||
+
|
||||
[(8.1.1.3)](#8.1.1.3)
|
||||
for bulk_chunked,
|
||||
invokes f(b, e, args...) zero or more times
|
||||
with pairs of b and e of type Shape in range [0, shape],
|
||||
such that b<e and
|
||||
for every i of type Shape from 0 to shape,
|
||||
there is exactly one invocation with a pair b and e,
|
||||
such that i is in the range [b, e)[.](#8.1.1.3.sentence-1)
|
||||
|
||||
* [(8.1.2)](#8.1.2)
|
||||
|
||||
If out_sndr completes with set_error(rcvr, eptr), then
|
||||
the asynchronous operation may invoke a subset of
|
||||
the invocations of f before the error completion handler is called, and eptr is an exception_ptr containing either:
|
||||
+
|
||||
[(8.1.2.1)](#8.1.2.1)
|
||||
an exception thrown by an invocation of f, or
|
||||
|
||||
+
|
||||
[(8.1.2.2)](#8.1.2.2)
|
||||
a bad_alloc exception if
|
||||
the implementation fails to allocate required resources, or
|
||||
|
||||
+
|
||||
[(8.1.2.3)](#8.1.2.3)
|
||||
an exception derived from runtime_error[.](#8.1.2.sentence-1)
|
||||
|
||||
* [(8.1.3)](#8.1.3)
|
||||
|
||||
If out_sndr completes with set_stopped(rcvr), then
|
||||
the asynchronous operation may invoke a subset of
|
||||
the invocations of f before the stopped completion handler[.](#8.1.3.sentence-1)
|
||||
|
||||
- [(8.2)](#8.2)
|
||||
|
||||
If sndr does not complete with set_value, then
|
||||
the completion is forwarded to recv[.](#8.2.sentence-1)
|
||||
|
||||
- [(8.3)](#8.3)
|
||||
|
||||
For *bulk-algo*,
|
||||
the parameter policy describes
|
||||
the manner in which
|
||||
the execution of the asynchronous operations corresponding to these algorithms
|
||||
may be parallelized and
|
||||
the manner in which
|
||||
they apply f[.](#8.3.sentence-1)
|
||||
Permissions and requirements
|
||||
on parallel algorithm element access functions ([[algorithms.parallel.exec]](algorithms.parallel.exec "26.3.3 Effect of execution policies on algorithm execution"))
|
||||
apply to f[.](#8.3.sentence-2)
|
||||
|
||||
[9](#9)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L4358)
|
||||
|
||||
[*Note [2](#note-2)*:
|
||||
|
||||
The asynchronous operation corresponding to*bulk-algo*(sndr, policy, shape, f) can complete with set_stopped if cancellation is requested or
|
||||
ignore cancellation requests[.](#9.sentence-1)
|
||||
|
||||
â *end note*]
|
||||
Reference in New Issue
Block a user