[exec.sync.wait] (original) (raw)

33 Execution control library [exec]

33.9 Senders [exec.snd]

33.9.13 Sender consumers [exec.consumers]

33.9.13.1 this_thread​::​sync_wait [exec.sync.wait]

this_thread​::​sync_wait and this_thread​::​sync_wait_with_variantare used to block the current thread of execution until the specified sender completes and to return its async result.

sync_wait mandates that the input sender has exactly one value completion signature.

Let sync-wait-env be the following exposition-only class type:namespace std::this_thread { struct sync-wait-env { execution::run_loop* loop; auto query(execution::get_scheduler_t) const noexcept { return _loop_->get_scheduler();} auto query(execution::get_delegation_scheduler_t) const noexcept { return _loop_->get_scheduler();} };}

Let sync-wait-result-type and_sync-wait-with-variant-result-type_be exposition-only alias templates defined as follows:namespace std::this_thread { template<execution::sender_in<_sync-wait-env_> Sndr> using sync-wait-result-type = optional<execution::value_types_of_t<Sndr, _sync-wait-env_, _decayed-tuple_, type_identity_t>>;template<execution::sender_in<_sync-wait-env_> Sndr> using sync-wait-with-variant-result-type = optional<execution::value_types_of_t<Sndr, _sync-wait-env_>>;}

The name this_thread​::​sync_wait denotes a customization point object.

For a subexpression sndr, let Sndr be decltype((sndr)).

If sender_in<Sndr, _sync-wait-env_>is false, the expression this_thread​::​sync_wait(sndr) is ill-formed.

Otherwise, it is expression-equivalent to the following, except that sndr is evaluated only once:apply_sender(get-domain-early(sndr), sync_wait, sndr) Mandates:

Let sync-wait-state and _sync-wait-receiver_be the following exposition-only class templates:namespace std::this_thread { template<class Sndr> struct sync-wait-state { execution::run_loop loop; exception_ptr error; sync-wait-result-type<Sndr> result; };template<class Sndr> struct sync-wait-receiver { using receiver_concept = execution::receiver_t;sync-wait-state<Sndr>* state; template<class... Args> void set_value(Args&&... args) && noexcept;template<class Error> void set_error(Error&& err) && noexcept;void set_stopped() && noexcept;sync-wait-env get_env() const noexcept { return {&_state_->loop}; } };}

template<class... Args> void set_value(Args&&... args) && noexcept;

Effects: Equivalent to:try { _state_->result.emplace(std::forward<Args>(args)...);} catch (...) { _state_->error = current_exception();} _state_->loop.finish();

template<class Error> void set_error(Error&& err) && noexcept;

Effects: Equivalent to:_state_->error = AS-EXCEPT-PTR(std::forward<Error>(err)); _state_->loop.finish();

void set_stopped() && noexcept;

Effects: Equivalent to _state_->loop.finish().

For a subexpression sndr, let Sndr be decltype((sndr)).

If sender_to<Sndr, _sync-wait-receiver_<Sndr>>is false, the expression sync_wait.apply_sender(sndr) is ill-formed; otherwise, it is equivalent to:sync-wait-state<Sndr> state;auto op = connect(sndr, sync-wait-receiver<Sndr>{&state}); start(op); state.loop.run();if (state.error) { rethrow_exception(std::move(state.error));} return std::move(state.result);

The behavior of this_thread​::​sync_wait(sndr) is undefined unless: