[exec.sync.wait] # 33 Execution control library [[exec]](./#exec) ## 33.9 Senders [[exec.snd]](exec.snd#exec.sync.wait) ### 33.9.13 Sender consumers [[exec.consumers]](exec.consumers#exec.sync.wait) #### 33.9.13.1 this_thread​::​sync_wait [exec.sync.wait] [1](#1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L5595) this_thread​::​sync_wait and this_thread​::​sync_wait_with_variant are used to block the current thread of execution until the specified sender completes and to return its async result[.](#1.sentence-1) sync_wait mandates that the input sender has exactly one value completion signature[.](#1.sentence-2) [2](#2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L5604) Let *sync-wait-env* be the following exposition-only class type:namespace std::this_thread {struct *sync-wait-env* { execution::run_loop* *loop*; // *exposition only*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(); }};} [3](#3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L5622) 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 Sndr>using *sync-wait-result-type* = optional>; template Sndr>using *sync-wait-with-variant-result-type* = optional>;} [4](#4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L5639) The name this_thread​::​sync_wait denotes a customization point object[.](#4.sentence-1) For a subexpression sndr, let Sndr be decltype((sndr))[.](#4.sentence-2) The expression this_thread​::​sync_wait(sndr) is expression-equivalent to the following, except that sndr is evaluated only once:apply_sender(*get-domain-early*(sndr), sync_wait, sndr)*Mandates*: - [(4.1)](#4.1) [sender_in](exec.snd.concepts#concept:sender_in "33.9.3 Sender concepts [exec.snd.concepts]") is true[.](#4.1.sentence-1) - [(4.2)](#4.2) The type *sync-wait-result-type* is well-formed[.](#4.2.sentence-1) - [(4.3)](#4.3) [same_as](concept.same#concept:same_as "18.4.2 Concept same_­as [concept.same]")> is true, where e is the apply_sender expression above[.](#4.3.sentence-1) [5](#5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L5659) Let *sync-wait-state* and *sync-wait-receiver* be the following exposition-only class templates:namespace std::this_thread {templatestruct *sync-wait-state* { // *exposition only* execution::run_loop *loop*; // *exposition only* exception_ptr *error*; // *exposition only**sync-wait-result-type* *result*; // *exposition only*}; templatestruct *sync-wait-receiver* { // *exposition only*using receiver_concept = execution::receiver_t; *sync-wait-state** *state*; // *exposition only*templatevoid set_value(Args&&... args) && noexcept; templatevoid set_error(Error&& err) && noexcept; void set_stopped() && noexcept; *sync-wait-env* get_env() const noexcept { return {&*state*->*loop*}; }};} [🔗](#itemdecl:1) `template void set_value(Args&&... args) && noexcept; ` [6](#6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L5695) *Effects*: Equivalent to:try {*state*->*result*.emplace(std::forward(args)...);} catch (...) {*state*->*error* = current_exception();}*state*->*loop*.finish(); [🔗](#itemdecl:2) `template void set_error(Error&& err) && noexcept; ` [7](#7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L5714) *Effects*: Equivalent to:*state*->*error* = *AS-EXCEPT-PTR*(std::forward(err)); // see [[exec.general]](exec.general "33.1 General")*state*->*loop*.finish(); [🔗](#itemdecl:3) `void set_stopped() && noexcept; ` [8](#8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L5728) *Effects*: Equivalent to *state*->*loop*.finish()[.](#8.sentence-1) [9](#9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L5733) For a subexpression sndr, let Sndr be decltype((sndr))[.](#9.sentence-1) If [sender_to](exec.snd.concepts#concept:sender_to "33.9.3 Sender concepts [exec.snd.concepts]")> is false, the expression sync_wait.apply_sender(sndr) is ill-formed; otherwise, it is equivalent to:*sync-wait-state* state;auto op = connect(sndr, *sync-wait-receiver*{&state}); start(op); state.*loop*.run();if (state.*error*) { rethrow_exception(std::move(state.*error*));}return std::move(state.*result*); [10](#10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L5751) The behavior of this_thread​::​sync_wait(sndr) is undefined unless: - [(10.1)](#10.1) It blocks the current thread of execution ([[defns.block]](defns.block "3.6 block")) with forward progress guarantee delegation ([[intro.progress]](intro.progress "6.10.2.3 Forward progress")) until the specified sender completes[.](#10.1.sentence-1) [*Note [1](#note-1)*: The default implementation of sync_wait achieves forward progress guarantee delegation by providing a run_loop scheduler via the get_delegation_scheduler query on the *sync-wait-receiver*'s environment[.](#10.1.sentence-2) The run_loop is driven by the current thread of execution[.](#10.1.sentence-3) — *end note*] - [(10.2)](#10.2) It returns the specified sender's async results as follows: * [(10.2.1)](#10.2.1) For a value completion, the result datums are returned in a tuple in an engaged optional object[.](#10.2.1.sentence-1) * [(10.2.2)](#10.2.2) For an error completion, an exception is thrown[.](#10.2.2.sentence-1) * [(10.2.3)](#10.2.3) For a stopped completion, a disengaged optional object is returned[.](#10.2.3.sentence-1)