[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.13 Coroutine utilities") makes use of the following exposition-only entities:namespace std::execution {templateconcept [*awaitable-sender*](#concept:awaitable-sender "33.13.1 execution​::​as_­awaitable [exec.as.awaitable]") =[*single-sender*](execution.syn#concept:single-sender "33.4 Header synopsis [execution.syn]")> &&[sender_to](exec.snd.concepts#concept:sender_to "33.9.3 Sender concepts [exec.snd.concepts]") && // *see below*requires (Promise& p) {{ p.unhandled_stopped() } -> [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")>; }; templateconcept [*has-queryable-await-completion-adaptor*](#concept:has-queryable-await-completion-adaptor "33.13.1 execution​::​as_­awaitable [exec.as.awaitable]") = // *exposition only*[sender](exec.snd.concepts#concept:sender "33.9.3 Sender concepts [exec.snd.concepts]") &&requires(Sndr&& sender) { get_await_completion_adaptor(get_env(sender)); }; templateclass *sender-awaitable*; // *exposition only*} [2](#2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L6636) The type *sender-awaitable* is equivalent to: namespace std::execution {templateclass *sender-awaitable* {struct *unit* {}; // *exposition only*using *value-type* = // *exposition only**single-sender-value-type*>; using *result-type* = // *exposition only* conditional_t, unit, *value-type*>; struct *awaitable-receiver*; // *exposition only* variant *result*{}; // *exposition only* connect_result_t *state*; // *exposition only*public:*sender-awaitable*(Sndr&& sndr, Promise& p); static constexpr bool await_ready() noexcept { return false; }void await_suspend(coroutine_handle) 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* *result-ptr*; // *exposition only* coroutine_handle *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.11 Concept 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.1 General") rcvr.*continuation*.resume(); - [(4.3)](#4.3) The expression set_stopped(rcvr) is equivalent to:static_cast>(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.4 Header 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), *awaitable-receiver*{addressof(result), coroutine_handle::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,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.4 Awaitable helpers [exec.awaitable]") 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.4 Awaitable helpers [exec.awaitable]") 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.4 Awaitable helpers [exec.awaitable]") 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* and*awaitable-sender* 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.1 execution​::​as_­awaitable [exec.as.awaitable]") is true[.](#7.4.sentence-1) - [(7.5)](#7.5) Otherwise, (void(p), expr)[.](#7.5.sentence-1)