This commit is contained in:
2025-10-25 03:02:53 +03:00
commit 043225d523
3416 changed files with 681196 additions and 0 deletions

View File

@@ -0,0 +1,123 @@
[exec.as.awaitable]
# 33 Execution control library [[exec]](./#exec)
## 33.13 Coroutine utilities [[exec.coro.util]](exec.coro.util#exec.as.awaitable)
### 33.13.1 execution::as_awaitable [exec.as.awaitable]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L6609)
as_awaitable transforms an object into one
that is awaitable within a particular coroutine[.](#1.sentence-1)
Subclause [[exec.coro.util]](exec.coro.util "33.13Coroutine utilities") makes use of
the following exposition-only entities:namespace std::execution {template<class Sndr, class Promise>concept [*awaitable-sender*](#concept:awaitable-sender "33.13.1execution::as_­awaitable[exec.as.awaitable]") =[*single-sender*](execution.syn#concept:single-sender "33.4Header <execution> synopsis[execution.syn]")<Sndr, env_of_t<Promise>> &&[sender_to](exec.snd.concepts#concept:sender_to "33.9.3Sender concepts[exec.snd.concepts]")<Sndr, *awaitable-receiver*> && // *see below*requires (Promise& p) {{ p.unhandled_stopped() } -> [convertible_to](concept.convertible#concept:convertible_to "18.4.4Concept convertible_­to[concept.convertible]")<coroutine_handle<>>; }; template<class Sndr>concept [*has-queryable-await-completion-adaptor*](#concept:has-queryable-await-completion-adaptor "33.13.1execution::as_­awaitable[exec.as.awaitable]") = // *exposition only*[sender](exec.snd.concepts#concept:sender "33.9.3Sender concepts[exec.snd.concepts]")<Sndr> &&requires(Sndr&& sender) { get_await_completion_adaptor(get_env(sender)); }; template<class Sndr, class Promise>class *sender-awaitable*; // *exposition only*}
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L6636)
The type *sender-awaitable*<Sndr, Promise> is equivalent to:
namespace std::execution {template<class Sndr, class Promise>class *sender-awaitable* {struct *unit* {}; // *exposition only*using *value-type* = // *exposition only**single-sender-value-type*<Sndr, env_of_t<Promise>>; using *result-type* = // *exposition only* conditional_t<is_void_v<*value-type*>, unit, *value-type*>; struct *awaitable-receiver*; // *exposition only* variant<monostate, *result-type*, exception_ptr> *result*{}; // *exposition only* connect_result_t<Sndr, *awaitable-receiver*> *state*; // *exposition only*public:*sender-awaitable*(Sndr&& sndr, Promise& p); static constexpr bool await_ready() noexcept { return false; }void await_suspend(coroutine_handle<Promise>) noexcept { start(*state*); }*value-type* await_resume(); };}
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L6662)
*awaitable-receiver* is equivalent to:struct *awaitable-receiver* {using receiver_concept = receiver_t;
variant<monostate, *result-type*, exception_ptr>* *result-ptr*; // *exposition only* coroutine_handle<Promise> *continuation*; // *exposition only*// *see below*};
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L6673)
Let rcvr be an rvalue expression of type *awaitable-receiver*,
let crcvr be a const lvalue that refers to rcvr,
let vs be a pack of subexpressions, and
let err be an expression of type Err[.](#4.sentence-1)
Then:
- [(4.1)](#4.1)
If [constructible_from](concept.constructible#concept:constructible_from "18.4.11Concept constructible_­from[concept.constructible]")<*result-type*, decltype((vs))...> is satisfied,
the expression set_value(
rcvr, vs...) is equivalent to:try { rcvr.*result-ptr*->template emplace<1>(vs...);} catch(...) { rcvr.*result-ptr*->template emplace<2>(current_exception());} rcvr.*continuation*.resume();
Otherwise, set_value(rcvr, vs...) is ill-formed[.](#4.1.sentence-2)
- [(4.2)](#4.2)
The expression set_error(rcvr, err) is equivalent to:rcvr.*result-ptr*->template emplace<2>(*AS-EXCEPT-PTR*(err)); // see [[exec.general]](exec.general "33.1General") rcvr.*continuation*.resume();
- [(4.3)](#4.3)
The expression set_stopped(rcvr) is equivalent to:static_cast<coroutine_handle<>>(rcvr.*continuation*.promise().unhandled_stopped()).resume();
- [(4.4)](#4.4)
For any expression tag whose type satisfies [*forwarding-query*](execution.syn#concept:forwarding-query "33.4Header <execution> synopsis[execution.syn]") and
for any pack of subexpressions as,get_env(crcvr).query(tag, as...) is expression-equivalent to:tag(get_env(as_const(crcvr.*continuation*.promise())), as...)
[🔗](#itemdecl:1)
`sender-awaitable(Sndr&& sndr, Promise& p);
`
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L6718)
*Effects*: Initializes *state* withconnect(std::forward<Sndr>(sndr), *awaitable-receiver*{addressof(result), coroutine_handle<Promise>::from_promise(p)})
[🔗](#itemdecl:2)
`value-type await_resume();
`
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L6732)
*Effects*: Equivalent to:if (*result*.index() == 2) rethrow_exception(get<2>(*result*));if constexpr (!is_void_v<*value-type*>)return std::forward<*value-type*>(get<1>(*result*));
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L6743)
as_awaitable is a customization point object[.](#7.sentence-1)
For subexpressions expr and p where p is an lvalue,Expr names the type decltype((expr)) andPromise names the type decay_t<decltype((p))>,as_awaitable(expr, p) is expression-equivalent to,
except that the evaluations of expr and p are indeterminately sequenced:
- [(7.1)](#7.1)
expr.as_awaitable(p) if that expression is well-formed[.](#7.1.sentence-1)
*Mandates*: [*is-awaitable*](exec.awaitable#concept:is-awaitable "33.9.4Awaitable helpers[exec.awaitable]")<A, Promise> is true,
where A is the type of the expression above[.](#7.1.sentence-2)
- [(7.2)](#7.2)
Otherwise, (void(p), expr) if [*is-awaitable*](exec.awaitable#concept:is-awaitable "33.9.4Awaitable helpers[exec.awaitable]")<Expr, U> is true,
where U is an unspecified class type
that is not Promise and
that lacks a member named await_transform[.](#7.2.sentence-1)
*Preconditions*: [*is-awaitable*](exec.awaitable#concept:is-awaitable "33.9.4Awaitable helpers[exec.awaitable]")<Expr, Promise> is true and
the expression co_await expr in a coroutine with promise type U is expression-equivalent to
the same expression in a coroutine with promise type Promise[.](#7.2.sentence-2)
- [(7.3)](#7.3)
Otherwise, *sender-awaitable*{*adapted-expr*, p} if*has-queryable-await-completion-adaptor*<Expr> and*awaitable-sender*<decltype((*adapted-expr*)), Promise> are both satisfied, where *adapted-expr* isget_await_completion_adaptor(get_env(expr))(expr),
except that expr is evaluated only once[.](#7.3.sentence-1)
- [(7.4)](#7.4)
Otherwise, *sender-awaitable*{expr, p} if [*awaitable-sender*](#concept:awaitable-sender "33.13.1execution::as_­awaitable[exec.as.awaitable]")<Expr, Promise> is true[.](#7.4.sentence-1)
- [(7.5)](#7.5)
Otherwise, (void(p), expr)[.](#7.5.sentence-1)