Skip to content

Commit e974ac0

Browse files
committed
fixup: add up to 34.9.9
1 parent 2d037c9 commit e974ac0

File tree

1 file changed

+258
-0
lines changed

1 file changed

+258
-0
lines changed

source/exec.tex

Lines changed: 258 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2202,6 +2202,264 @@
22022202
\tcode{noexcept(\exposid{final-sndr})}.
22032203
\end{itemdescr}
22042204

2205+
\rSec2[exec.snd.transform.env]{\tcode{execution::transform_env}}
2206+
2207+
\begin{itemdecl}
2208+
namespace std::execution {
2209+
template<class Domain, @\libconcept{sender}@ Sndr, @\exposconcept{queryable}@ Env>
2210+
constexpr @\exposconcept{queryable}@ decltype(auto) transform_env(Domain dom, Sndr&& sndr, Env&& env) noexcept;
2211+
}
2212+
\end{itemdecl}
2213+
2214+
\begin{itemdescr}
2215+
\pnum
2216+
Let \tcode{e} be the expression
2217+
\begin{codeblock}
2218+
dom.transform_env(std::forward<Sndr>(sndr), std::forward<Env>(env))
2219+
\end{codeblock}
2220+
if that expression is well-formed; otherwise,
2221+
\begin{codeblock}
2222+
default_domain().transform_env(std::forward<Sndr>(sndr), std::forward<Env>(env))
2223+
\end{codeblock}
2224+
2225+
\pnum
2226+
\mandates
2227+
\tcode{noexcept(e)} is \tcode{true}.
2228+
2229+
\pnum
2230+
\returns
2231+
\tcode{e}
2232+
\end{itemdescr}
2233+
2234+
\rSec2[exec.snd.apply]{\tcode{execution::apply_sender}}
2235+
2236+
\begin{itemdecl}
2237+
namespace std::execution {
2238+
template<class Domain, class Tag, @\libconcept{sender}@ Sndr, class... Args>
2239+
constexpr decltype(auto) apply_sender(Domain dom, Tag, Sndr&& sndr, Args&&... args)
2240+
noexcept(see below);
2241+
}
2242+
\end{itemdecl}
2243+
2244+
\begin{itemdescr}
2245+
\pnum
2246+
Let $e$ be the expression
2247+
\begin{codeblock}
2248+
dom.apply_sender(Tag(), std::forward<Sndr>(sndr), std::forward<Args>(args)...)
2249+
\end{codeblock}
2250+
if that expression is well-formed; otherwise,
2251+
\begin{codeblock}
2252+
default_domain().apply_sender(Tag(), std::forward<Sndr>(sndr), std::forward<Args>(args)...)
2253+
\end{codeblock}
2254+
2255+
\pnum
2256+
\constraints
2257+
The expression $e$ is well-formed.
2258+
2259+
\pnum
2260+
\returns
2261+
$e$
2262+
2263+
\pnum
2264+
\remarks
2265+
The exception specification is equivalent to \tcode{noexcept($e$)}.
2266+
\end{itemdescr}
2267+
2268+
\rSec2[exec.getcomplsigs]{\tcode{execution::get_completion_signatures}}
2269+
2270+
\pnum
2271+
\tcode{get_completion_signatures} is a customization point object.
2272+
Let \tcode{sndr} be an expression
2273+
such that \tcode{decltype((sndr))} is \tcode{Sndr}, and
2274+
let \tcode{env} be an expression
2275+
such that \tcode{decltype((env))} is \tcode{Env}.
2276+
Let \tcode{new_sndr} be the expression
2277+
\tcode{transform_sender(decltype(\exposid{get-domain-late}(sndr, env)){}, sndr, env)}, and
2278+
let \tcode{NewSndr} be \tcode{decltype((new_sndr))}.
2279+
Then \tcode{get_completion_signatures(sndr, env)} is expression-equivalent to
2280+
\tcode{(void(sndr), void(env), CS())}
2281+
except that \tcode{void(sndr)} and \tcode{void(env)} are
2282+
indeterminately sequenced,
2283+
where \tcode{CS} is:
2284+
\begin{itemize}
2285+
\item
2286+
\tcode{decltype(new_sndr.get_completion_signatures(env))}
2287+
if that type is well-formed,
2288+
2289+
\item
2290+
Otherwise, \tcode{remove_cvref_t<NewSndr>::completion_signatures}
2291+
if that type is well-formed,
2292+
2293+
\item
2294+
Otherwise,
2295+
if \tcode{\exposid{is-awaitable}<NewSndr, env-promise<Env>>} is \tcode{true},
2296+
then:
2297+
\begin{codeblock}
2298+
completion_signatures<
2299+
@\exposid{SET-VALUE-SIG}@(@\exposid{await-result-type}@<NewSndr, @\exposid{env-promise}@<Env>>), // \iref{exec.snd.concepts}
2300+
set_error_t(exception_ptr),
2301+
set_stopped_t()>
2302+
\end{codeblock}
2303+
2304+
\item
2305+
Otherwise, \tcode{CS} is ill-formed.
2306+
\end{itemize}
2307+
2308+
\pnum
2309+
Let \tcode{rcvr} be an rvalue
2310+
whose type \tcode{Rcvr} models \libconcept{receiver}, and
2311+
let \tcode{Sndr} be the type of a sender
2312+
such that \tcode{\libconcept{sender_in}<Sndr, env_of_t<Rcvr>>} is \tcode{true}.
2313+
Let \tcode{Sigs...} be the template arguments of
2314+
the \tcode{completion_signatures} specialization
2315+
named by \tcode{completion_signatures_of_t<Sndr, env_of_t<Rcvr>>}.
2316+
Let \tcode{CSO} be a completion function.
2317+
If sender \tcode{Sndr} or its operation state cause
2318+
the expression \tcode{CSO(rcvr, args...)}
2319+
to be potentially evaluated\iref{basic.def.odr}
2320+
then there shall be a signature \tcode{Sig} in \tcode{Sigs...}
2321+
such that
2322+
\begin{codeblock}
2323+
@\exposid{MATCHING-SIG}@(@\exposid{decayed-typeof}@<CSO>(decltype(args)...), Sig)
2324+
\end{codeblock}
2325+
is \tcode{true}\iref{exec.general}.
2326+
2327+
\rSec2[exec.connect]{\tcode{execution::connect}}
2328+
2329+
\pnum
2330+
\tcode{connect} connects\iref{exec.async.ops} a sender with a receiver.
2331+
2332+
\pnum
2333+
The name \tcode{connect} denotes a customization point object.
2334+
For subexpressions \tcode{sndr} and \tcode{rcvr},
2335+
let \tcode{Sndr} be \tcode{decltype((sndr))} and
2336+
\tcode{Rcvr} be \tcode{decltype((rcvr))},
2337+
let \tcode{new_sndr} be the expression
2338+
\begin{codeblock}
2339+
transform_sender(decltype(@\exposid{get-domain-late}@(sndr, get_env(rcvr))){}, sndr, get_env(rcvr))
2340+
\end{codeblock}
2341+
and let \tcode{DS} and \tcode{DR} be
2342+
\tcode{decay_t<decltype((new_sndr))>} and \tcode{decay_t<Rcvr>}, respectively.
2343+
2344+
\pnum
2345+
Let \exposid{connect-awaitable-promise} be the following exposition-only class:
2346+
2347+
\begin{codeblock}
2348+
namespace std::execution {
2349+
struct @\exposid{connect-awaitable-promise}@ : @\exposid{with-await-transform}@<@\exposid{connect-awaitable-promise}@> {
2350+
2351+
@\exposid{connect-awaitable-promise}@(DS&, DR& rcvr) noexcept : @\exposid{rcvr}@(rcvr) {}
2352+
2353+
suspend_always initial_suspend() noexcept { return {}; }
2354+
[[noreturn]] suspend_always final_suspend() noexcept { terminate(); }
2355+
[[noreturn]] void unhandled_exception() noexcept { terminate(); }
2356+
[[noreturn]] void return_void() noexcept { terminate(); }
2357+
2358+
coroutine_handle<> unhandled_stopped() noexcept {
2359+
set_stopped(std::move(@\exposid{rcvr}@));
2360+
return noop_coroutine();
2361+
}
2362+
2363+
@\exposid{operation-state-task}@ get_return_object() noexcept {
2364+
return @\exposid{operation-state-task}@{
2365+
coroutine_handle<@\exposid{connect-awaitable-promise}@>::from_promise(*this)};
2366+
}
2367+
2368+
env_of_t<DR> get_env() const noexcept {
2369+
return execution::get_env(@\exposid{rcvr}@);
2370+
}
2371+
2372+
private:
2373+
DR& @\exposid{rcvr}@; // \expos
2374+
};
2375+
}
2376+
\end{codeblock}
2377+
2378+
\pnum
2379+
Let \exposid{operation-state-task} be the following exposition-only class:
2380+
\begin{codeblock}
2381+
namespace std::execution {
2382+
struct @\exposid{operation-state-task}@ {
2383+
using operation_state_concept = operation_state_t;
2384+
using promise_type = @\exposid{connect-awaitable-promise}@;
2385+
2386+
explicit @\exposid{operation-state-task}@(coroutine_handle<> h) noexcept : coro(h) {}
2387+
@\exposid{operation-state-task}@(@\exposid{operation-state-task}@&& o) noexcept
2388+
: @\exposid{coro}@(exchange(o.@\exposid{coro}@, {})) {}
2389+
~@\exposid{operation-state-task}@() { if (@\exposid{coro}@) @\exposid{coro}@.destroy(); }
2390+
2391+
void start() & noexcept {
2392+
@\exposid{coro}@.resume();
2393+
}
2394+
2395+
private:
2396+
coroutine_handle<> @\exposid{coro}@; // \expos
2397+
};
2398+
}
2399+
\end{codeblock}
2400+
2401+
\pnum
2402+
Let \tcode{V} name the type
2403+
\tcode{\exposid{await-result-type}<DS, \exposid{connect-awaitable-promise}>},
2404+
let \tcode{Sigs} name the type
2405+
\begin{codeblock}
2406+
completion_signatures<
2407+
@\exposid{SET-VALUE-SIG}@(V), // see \iref{exec.snd.concepts}
2408+
set_error_t(exception_ptr),
2409+
set_stopped_t()>
2410+
\end{codeblock}
2411+
and let \exposid{connect-awaitable} be an exposition-only coroutine
2412+
defined as follows:
2413+
\begin{codeblock}
2414+
namespace std::execution {
2415+
template<class Fun, class... Ts>
2416+
auto @\exposid{suspend-complete}@(Fun fun, Ts&&... as) noexcept { // \expos
2417+
auto fn = [&, fun]() noexcept { fun(std::forward<Ts>(as)...); };
2418+
2419+
struct awaiter {
2420+
decltype(@\exposid{fn}@) @\exposid{fn}@; // \expos
2421+
2422+
static constexpr bool await_ready() noexcept { return false; }
2423+
void await_suspend(coroutine_handle<>) noexcept { @\exposid{fn}@(); }
2424+
[[noreturn]] void await_resume() noexcept { unreachable(); }
2425+
};
2426+
return awaiter{@\exposid{fn}@};
2427+
}
2428+
2429+
@\exposid{operation-state-task}@ @\exposid{connect-awaitable}@(DS sndr, DR rcvr) requires @\libconcept{receiver_of}@<DR, Sigs> {
2430+
exception_ptr ep;
2431+
try {
2432+
if constexpr (@\libconcept{same_as}@<V, void>) {
2433+
co_await std::move(sndr);
2434+
co_await @\exposid{suspend-complete}@(set_value, std::move(rcvr));
2435+
} else {
2436+
co_await @\exposid{suspend-complete}@(set_value, std::move(rcvr), co_await std::move(sndr));
2437+
}
2438+
} catch(...) {
2439+
ep = current_exception();
2440+
}
2441+
co_await @\exposid{suspend-complete}@(set_error, std::move(rcvr), std::move(ep));
2442+
}
2443+
}
2444+
\end{codeblock}
2445+
2446+
\pnum
2447+
The expression \tcode{connect(sndr, rcvr)} is expression-equivalent to:
2448+
\begin{itemize}
2449+
\item
2450+
\tcode{new_sndr.connect(rcvr)} if that expression is well-formed.
2451+
2452+
\mandates
2453+
The type of the expression above satisfies \libconcept{operation_state}.
2454+
2455+
\item
2456+
Otherwise, \tcode{\exposid{connect-awaitable}(new_sndr, rcvr)}.
2457+
\end{itemize}
2458+
2459+
\mandates
2460+
\tcode{\libconcept{sender}<Sndr> \&\& \libconcept{receiver}<Rcvr>} is \tcode{true}.
2461+
2462+
22052463
\rSec1[exec.util]{Sender/receiver utilities}
22062464

22072465
\rSec1[exec.ctx]{Execution contexts}

0 commit comments

Comments
 (0)