33 Execution control library [exec] (original) (raw)
33.9 Senders [exec.snd]
33.9.10 execution​::​connect [exec.connect]
The name connect denotes a customization point object.
For subexpressions sndr and rcvr, let Sndr be decltype((sndr)) andRcvr be decltype((rcvr)), let new_sndr be the expressiontransform_sender(decltype(get-domain-late(sndr, get_env(rcvr))){}, sndr, get_env(rcvr)) and let DS and DR bedecay_t<decltype((new_sndr))> and decay_t<Rcvr>, respectively.
Let connect-awaitable-promise be the following exposition-only class:
namespace std::execution { struct connect-awaitable-promise : with-await-transform<_connect-awaitable-promise_> { connect-awaitable-promise(DS&, DR& rcvr) noexcept : rcvr(rcvr) {} suspend_always initial_suspend() noexcept { return {}; } [[noreturn]] suspend_always final_suspend() noexcept { terminate(); } [[noreturn]] void unhandled_exception() noexcept { terminate(); } [[noreturn]] void return_void() noexcept { terminate(); } coroutine_handle<> unhandled_stopped() noexcept { set_stopped(std::move(rcvr));return noop_coroutine();} operation-state-task get_return_object() noexcept { return operation-state-task{ coroutine_handle<_connect-awaitable-promise_>::from_promise(*this)};} env_of_t<DR> get_env() const noexcept { return execution::get_env(rcvr);} private: DR& rcvr; };}
Let operation-state-task be the following exposition-only class:namespace std::execution { struct operation-state-task { using operation_state_concept = operation_state_t;using promise_type = connect-awaitable-promise;explicit operation-state-task(coroutine_handle<> h) noexcept : coro(h) {} operation-state-task(operation-state-task&&) = delete;~operation-state-task() { coro.destroy(); } void start() & noexcept { coro.resume();} private: coroutine_handle<> coro; };}
Let V name the type_await-result-type_<DS, _connect-awaitable-promise_>, let Sigs name the typecompletion_signatures< _SET-VALUE-SIG_(V), set_error_t(exception_ptr), set_stopped_t()> and let connect-awaitable be an exposition-only coroutine defined as follows:namespace std::execution { template<class Fun, class... Ts> auto suspend-complete(Fun fun, Ts&&... as) noexcept { auto fn = [&, fun]() noexcept { fun(std::forward<Ts>(as)...); };struct awaiter { decltype(fn) fn; static constexpr bool await_ready() noexcept { return false; } void await_suspend(coroutine_handle<>) noexcept { fn(); } [[noreturn]] void await_resume() noexcept { unreachable(); } };return awaiter{fn};} operation-state-task connect-awaitable(DS sndr, DR rcvr) requires receiver_of<DR, Sigs> { exception_ptr ep;try { if constexpr (same_as<V, void>) { co_await std::move(sndr);co_await suspend-complete(set_value, std::move(rcvr));} else { co_await suspend-complete(set_value, std::move(rcvr), co_await std::move(sndr));} } catch(...) { ep = current_exception();} co_await suspend-complete(set_error, std::move(rcvr), std::move(ep));} }
The expression connect(sndr, rcvr) is expression-equivalent to: