Files
cppdraft_translate/cppdraft/exec/as/awaitable.md
2025-10-25 03:02:53 +03:00

124 lines
7.0 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

[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)