[exec.coro.util] (original) (raw)

33 Execution control library [exec]

33.13 Coroutine utilities [exec.coro.util]

33.13.1 execution​::​as_awaitable [exec.as.awaitable]

as_awaitable transforms an object into one that is awaitable within a particular coroutine.

Subclause [exec.coro.util] makes use of the following exposition-only entities:namespace std::execution { template<class Sndr, class Promise> concept awaitable-sender = single-sender<Sndr, env_of_t<Promise>> && sender_to<Sndr, _awaitable-receiver_> && requires (Promise& p) { { p.unhandled_stopped() } -> convertible_to<coroutine_handle<>>;};template<class Sndr, class Promise> class sender-awaitable; }

The type sender-awaitable<Sndr, Promise> is equivalent to:

namespace std::execution { template<class Sndr, class Promise> class sender-awaitable { struct unit {}; using value-type = single-sender-value-type<Sndr, env_of_t<Promise>>;using result-type = conditional_t<is_void_v<_value-type_>, unit, _value-type_>;struct awaitable-receiver; variant<monostate, _result-type_, exception_ptr> result{}; connect_result_t<Sndr, _awaitable-receiver_> state; 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();};}

awaitable-receiver is equivalent to:struct awaitable-receiver { using receiver_concept = receiver_t; variant<monostate, _result-type_, exception_ptr>* result-ptr; coroutine_handle<Promise> continuation; };

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.

Then:

_sender-awaitable_(Sndr&& sndr, Promise& p);

Effects: Initializes state withconnect(std::forward<Sndr>(sndr),awaitable-receiver{addressof(result), coroutine_handle<Promise>::from_promise(p)})

_value-type_ await_resume();

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

as_awaitable is a customization point object.

For subexpressions expr and pwhere 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 pare indeterminately sequenced:

33.13.2 execution​::​with_awaitable_senders [exec.with.awaitable.senders]

with_awaitable_senders, when used as the base class of a coroutine promise type, makes senders awaitable in that coroutine type.

In addition, it provides a default implementation of unhandled_stoppedsuch that if a sender completes by calling set_stopped, it is treated as if an uncatchable "stopped" exception were thrown from the await-expression.

[Note 1:

The coroutine is never resumed, and the unhandled_stopped of the coroutine caller's promise type is called.

— _end note_]

namespace std::execution { template<class-type Promise> struct with_awaitable_senders { template<class OtherPromise> requires (same\_as<OtherPromise, void>) void set_continuation(coroutine_handle<OtherPromise> h) noexcept; coroutine_handle<> continuation() const noexcept { return continuation; } coroutine_handle<> unhandled_stopped() noexcept { return stopped-handler(continuation.address());} template<class Value> see below await_transform(Value&& value);private: [[noreturn]] static coroutine_handle<> default-unhandled-stopped(void*) noexcept { terminate();} coroutine_handle<> continuation{}; coroutine_handle<> (*stopped-handler)(void*) noexcept = &default-unhandled-stopped;};}

template<class OtherPromise> requires (![same_as](concept.same#concept:same%5Fas "18.4.2 Concept same_­as [concept.same]")<OtherPromise, void>) void set_continuation(coroutine_handle<OtherPromise> h) noexcept;

Effects: Equivalent to:continuation = h;if constexpr ( requires(OtherPromise& other) { other.unhandled_stopped(); } ) { stopped-handler = [](void* p) noexcept -> coroutine_handle<> { return coroutine_handle<OtherPromise>::from_address(p) .promise().unhandled_stopped();};} else { stopped-handler = &default-unhandled-stopped;}

template<class Value> _call-result-t_<as_awaitable_t, Value, Promise&> await_transform(Value&& value);

Effects: Equivalent to:return as_awaitable(std::forward<Value>(value), static_cast<Promise&>(*this));