[support.coroutine] # 17 Language support library [[support]](./#support) ## 17.13 Coroutines [support.coroutine] ### [17.13.1](#general) General [[support.coroutine.general]](support.coroutine.general) [1](#general-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L5749) The header defines several types providing compile and run-time support for coroutines in a C++ program[.](#general-1.sentence-1) ### [17.13.2](#coroutine.syn) Header synopsis [[coroutine.syn]](coroutine.syn) [🔗](#header:%3ccoroutine%3e_) // all freestanding#include // see [[compare.syn]](compare.syn "17.12.1 Header synopsis")namespace std {// [[coroutine.traits]](#coroutine.traits "17.13.3 Coroutine traits"), coroutine traitstemplatestruct coroutine_traits; // [[coroutine.handle]](#coroutine.handle "17.13.4 Class template coroutine_­handle"), coroutine handletemplatestruct coroutine_handle; // [[coroutine.handle.compare]](#coroutine.handle.compare "17.13.4.8 Comparison operators"), comparison operatorsconstexpr bool operator==(coroutine_handle<> x, coroutine_handle<> y) noexcept; constexpr strong_ordering operator<=>(coroutine_handle<> x, coroutine_handle<> y) noexcept; // [[coroutine.handle.hash]](#coroutine.handle.hash "17.13.4.9 Hash support"), hash supporttemplate struct hash; template struct hash>; // [[coroutine.noop]](#coroutine.noop "17.13.5 No-op coroutines"), no-op coroutinesstruct noop_coroutine_promise; template<> struct coroutine_handle; using noop_coroutine_handle = coroutine_handle; noop_coroutine_handle noop_coroutine() noexcept; // [[coroutine.trivial.awaitables]](#coroutine.trivial.awaitables "17.13.6 Trivial awaitables"), trivial awaitablesstruct suspend_never; struct suspend_always;} ### [17.13.3](#coroutine.traits) Coroutine traits [[coroutine.traits]](coroutine.traits) #### [17.13.3.1](#coroutine.traits.general) General [[coroutine.traits.general]](coroutine.traits.general) [1](#coroutine.traits.general-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L5798) Subclause [[coroutine.traits]](#coroutine.traits "17.13.3 Coroutine traits") defines requirements on classes representing[*coroutine traits*](#def:coroutine_traits), and defines the class templatecoroutine_traits that meets those requirements[.](#coroutine.traits.general-1.sentence-1) #### [17.13.3.2](#coroutine.traits.primary) Class template coroutine_traits [[coroutine.traits.primary]](coroutine.traits.primary) [1](#coroutine.traits.primary-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L5808) The header [](#header:%3ccoroutine%3e "17.13.2 Header synopsis [coroutine.syn]") defines the primary templatecoroutine_traits such that if ArgTypes is a parameter pack of types and if the [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3 Qualified names [expr.prim.id.qual]") R​::​promise_type is valid and denotes a type ([[temp.deduct]](temp.deduct "13.10.3 Template argument deduction")), then coroutine_traits has the following publicly accessible member:using promise_type = typename R::promise_type; Otherwise, coroutine_traits has no members[.](#coroutine.traits.primary-1.sentence-2) [2](#coroutine.traits.primary-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L5822) Program-defined specializations of this template shall define a publicly accessible nested type named promise_type[.](#coroutine.traits.primary-2.sentence-1) ### [17.13.4](#coroutine.handle) Class template coroutine_handle [[coroutine.handle]](coroutine.handle) #### [17.13.4.1](#coroutine.handle.general) General [[coroutine.handle.general]](coroutine.handle.general) [🔗](#lib:coroutine_handle) namespace std {template<>struct coroutine_handle{// [[coroutine.handle.con]](#coroutine.handle.con "17.13.4.2 Construct/reset"), construct/resetconstexpr coroutine_handle() noexcept; constexpr coroutine_handle(nullptr_t) noexcept; coroutine_handle& operator=(nullptr_t) noexcept; // [[coroutine.handle.export.import]](#coroutine.handle.export.import "17.13.4.4 Export/import"), export/importconstexpr void* address() const noexcept; static constexpr coroutine_handle from_address(void* addr); // [[coroutine.handle.observers]](#coroutine.handle.observers "17.13.4.5 Observers"), observersconstexpr explicit operator bool() const noexcept; bool done() const; // [[coroutine.handle.resumption]](#coroutine.handle.resumption "17.13.4.6 Resumption"), resumptionvoid operator()() const; void resume() const; void destroy() const; private:void* ptr; // *exposition only*}; templatestruct coroutine_handle {// [[coroutine.handle.con]](#coroutine.handle.con "17.13.4.2 Construct/reset"), construct/resetconstexpr coroutine_handle() noexcept; constexpr coroutine_handle(nullptr_t) noexcept; static coroutine_handle from_promise(Promise&); coroutine_handle& operator=(nullptr_t) noexcept; // [[coroutine.handle.export.import]](#coroutine.handle.export.import "17.13.4.4 Export/import"), export/importconstexpr void* address() const noexcept; static constexpr coroutine_handle from_address(void* addr); // [[coroutine.handle.conv]](#coroutine.handle.conv "17.13.4.3 Conversion"), conversionconstexpr operator coroutine_handle<>() const noexcept; // [[coroutine.handle.observers]](#coroutine.handle.observers "17.13.4.5 Observers"), observersconstexpr explicit operator bool() const noexcept; bool done() const; // [[coroutine.handle.resumption]](#coroutine.handle.resumption "17.13.4.6 Resumption"), resumptionvoid operator()() const; void resume() const; void destroy() const; // [[coroutine.handle.promise]](#coroutine.handle.promise "17.13.4.7 Promise access"), promise access Promise& promise() const; private:void* ptr; // *exposition only*};} [1](#coroutine.handle.general-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L5892) An object of typecoroutine_handle is called a [*coroutine handle*](#def:coroutine_handle) and can be used to refer to a suspended or executing coroutine[.](#coroutine.handle.general-1.sentence-1) A coroutine_handle object whose member address() returns a null pointer value does not refer to any coroutine[.](#coroutine.handle.general-1.sentence-2) Two coroutine_handle objects refer to the same coroutine if and only if their member address() returns the same non-null value[.](#coroutine.handle.general-1.sentence-3) [2](#coroutine.handle.general-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L5903) If a program declares an explicit or partial specialization ofcoroutine_handle, the behavior is undefined[.](#coroutine.handle.general-2.sentence-1) #### [17.13.4.2](#coroutine.handle.con) Construct/reset [[coroutine.handle.con]](coroutine.handle.con) [🔗](#lib:coroutine_handle,constructor) `constexpr coroutine_handle() noexcept; constexpr coroutine_handle(nullptr_t) noexcept; ` [1](#coroutine.handle.con-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L5916) *Postconditions*: address() == nullptr[.](#coroutine.handle.con-1.sentence-1) [🔗](#lib:from_promise,coroutine_handle) `static coroutine_handle from_promise(Promise& p); ` [2](#coroutine.handle.con-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L5927) *Preconditions*: p is a reference to a promise object of a coroutine[.](#coroutine.handle.con-2.sentence-1) [3](#coroutine.handle.con-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L5931) *Postconditions*: addressof(h.promise()) == addressof(p)[.](#coroutine.handle.con-3.sentence-1) [4](#coroutine.handle.con-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L5935) *Returns*: A coroutine handle h referring to the coroutine[.](#coroutine.handle.con-4.sentence-1) [🔗](#lib:operator=,coroutine_handle) `coroutine_handle& operator=(nullptr_t) noexcept; ` [5](#coroutine.handle.con-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L5946) *Postconditions*: address() == nullptr[.](#coroutine.handle.con-5.sentence-1) [6](#coroutine.handle.con-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L5950) *Returns*: *this[.](#coroutine.handle.con-6.sentence-1) #### [17.13.4.3](#coroutine.handle.conv) Conversion [[coroutine.handle.conv]](coroutine.handle.conv) [🔗](#lib:operator_coroutine_handle%3c%3e,coroutine_handle) `constexpr operator coroutine_handle<>() const noexcept; ` [1](#coroutine.handle.conv-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L5963) *Effects*: Equivalent to: return coroutine_handle<>​::​from_address(address()); #### [17.13.4.4](#coroutine.handle.export.import) Export/import [[coroutine.handle.export.import]](coroutine.handle.export.import) [🔗](#lib:address,coroutine_handle) `constexpr void* address() const noexcept; ` [1](#coroutine.handle.export.import-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L5976) *Returns*: ptr[.](#coroutine.handle.export.import-1.sentence-1) [🔗](#lib:from_address,coroutine_handle) `static constexpr coroutine_handle<> coroutine_handle<>::from_address(void* addr); ` [2](#coroutine.handle.export.import-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L5987) *Preconditions*: addr was obtained via a prior call to address on an object whose type is a specialization of coroutine_handle[.](#coroutine.handle.export.import-2.sentence-1) [3](#coroutine.handle.export.import-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L5992) *Postconditions*: from_address(address()) == *this[.](#coroutine.handle.export.import-3.sentence-1) [🔗](#lib:from_address,coroutine_handle_) `static constexpr coroutine_handle coroutine_handle::from_address(void* addr); ` [4](#coroutine.handle.export.import-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L6003) *Preconditions*: addr was obtained via a prior call to address on an object of type cv coroutine_handle[.](#coroutine.handle.export.import-4.sentence-1) [5](#coroutine.handle.export.import-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L6008) *Postconditions*: from_address(address()) == *this[.](#coroutine.handle.export.import-5.sentence-1) #### [17.13.4.5](#coroutine.handle.observers) Observers [[coroutine.handle.observers]](coroutine.handle.observers) [🔗](#lib:operator_bool,coroutine_handle) `constexpr explicit operator bool() const noexcept; ` [1](#coroutine.handle.observers-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L6021) *Returns*: address() != nullptr[.](#coroutine.handle.observers-1.sentence-1) [🔗](#lib:done,coroutine_handle) `bool done() const; ` [2](#coroutine.handle.observers-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L6032) *Preconditions*: *this refers to a suspended coroutine[.](#coroutine.handle.observers-2.sentence-1) [3](#coroutine.handle.observers-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L6036) *Returns*: true if the coroutine is suspended at its final suspend point, otherwise false[.](#coroutine.handle.observers-3.sentence-1) #### [17.13.4.6](#coroutine.handle.resumption) Resumption [[coroutine.handle.resumption]](coroutine.handle.resumption) [1](#coroutine.handle.resumption-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L6044) Resuming a coroutine via resume, operator(), or destroy on an execution agent other than the one on which it was suspended has implementation-defined behavior unless each execution agent either is an instance of std​::​thread or std​::​jthread, or is the thread that executes main[.](#coroutine.handle.resumption-1.sentence-1) [*Note [1](#coroutine.handle.resumption-note-1)*: A coroutine that is resumed on a different execution agent should avoid relying on consistent thread identity throughout, such as holding a mutex object across a suspend point[.](#coroutine.handle.resumption-1.sentence-2) — *end note*] [*Note [2](#coroutine.handle.resumption-note-2)*: A concurrent resumption of the coroutine can result in a data race[.](#coroutine.handle.resumption-1.sentence-3) — *end note*] [🔗](#lib:operator(),coroutine_handle) `void operator()() const; void resume() const; ` [2](#coroutine.handle.resumption-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L6069) *Preconditions*: *this refers to a suspended coroutine[.](#coroutine.handle.resumption-2.sentence-1) The coroutine is not suspended at its final suspend point[.](#coroutine.handle.resumption-2.sentence-2) [3](#coroutine.handle.resumption-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L6074) *Effects*: Resumes the execution of the coroutine[.](#coroutine.handle.resumption-3.sentence-1) [🔗](#lib:destroy,coroutine_handle) `void destroy() const; ` [4](#coroutine.handle.resumption-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L6085) *Preconditions*: *this refers to a suspended coroutine[.](#coroutine.handle.resumption-4.sentence-1) [5](#coroutine.handle.resumption-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L6089) *Effects*: Destroys the coroutine ([[dcl.fct.def.coroutine]](dcl.fct.def.coroutine "9.6.4 Coroutine definitions"))[.](#coroutine.handle.resumption-5.sentence-1) #### [17.13.4.7](#coroutine.handle.promise) Promise access [[coroutine.handle.promise]](coroutine.handle.promise) [🔗](#lib:promise,coroutine_handle) `Promise& promise() const; ` [1](#coroutine.handle.promise-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L6102) *Preconditions*: *this refers to a coroutine[.](#coroutine.handle.promise-1.sentence-1) [2](#coroutine.handle.promise-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L6106) *Returns*: A reference to the promise of the coroutine[.](#coroutine.handle.promise-2.sentence-1) #### [17.13.4.8](#coroutine.handle.compare) Comparison operators [[coroutine.handle.compare]](coroutine.handle.compare) [🔗](#lib:operator==,coroutine_handle) `constexpr bool operator==(coroutine_handle<> x, coroutine_handle<> y) noexcept; ` [1](#coroutine.handle.compare-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L6120) *Returns*: x.address() == y.address()[.](#coroutine.handle.compare-1.sentence-1) [🔗](#lib:operator%3c=%3e,coroutine_handle) `constexpr strong_ordering operator<=>(coroutine_handle<> x, coroutine_handle<> y) noexcept; ` [2](#coroutine.handle.compare-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L6131) *Returns*: compare_three_way()(x.address(), y.address())[.](#coroutine.handle.compare-2.sentence-1) #### [17.13.4.9](#coroutine.handle.hash) Hash support [[coroutine.handle.hash]](coroutine.handle.hash) [🔗](#lib:hash,coroutine_handle) `template struct hash>; ` [1](#coroutine.handle.hash-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L6144) The specialization is enabled ([[unord.hash]](unord.hash "22.10.19 Class template hash"))[.](#coroutine.handle.hash-1.sentence-1) ### [17.13.5](#coroutine.noop) No-op coroutines [[coroutine.noop]](coroutine.noop) #### [17.13.5.1](#coroutine.promise.noop) Class noop_coroutine_promise [[coroutine.promise.noop]](coroutine.promise.noop) [🔗](#lib:noop_coroutine_promise) `struct noop_coroutine_promise {}; ` [1](#coroutine.promise.noop-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L6158) The class noop_coroutine_promise defines the promise type for the coroutine referred to by noop_coroutine_handle ([[coroutine.syn]](#coroutine.syn "17.13.2 Header synopsis"))[.](#coroutine.promise.noop-1.sentence-1) #### [17.13.5.2](#coroutine.handle.noop) Class coroutine_handle [[coroutine.handle.noop]](coroutine.handle.noop) #### [17.13.5.2.1](#coroutine.handle.noop.general) General [[coroutine.handle.noop.general]](coroutine.handle.noop.general) [🔗](#lib:coroutine_handle%3cnoop_coroutine_promise%3e) namespace std {template<>struct coroutine_handle{// [[coroutine.handle.noop.conv]](#coroutine.handle.noop.conv "17.13.5.2.2 Conversion"), conversionconstexpr operator coroutine_handle<>() const noexcept; // [[coroutine.handle.noop.observers]](#coroutine.handle.noop.observers "17.13.5.2.3 Observers"), observersconstexpr explicit operator bool() const noexcept; constexpr bool done() const noexcept; // [[coroutine.handle.noop.resumption]](#coroutine.handle.noop.resumption "17.13.5.2.4 Resumption"), resumptionconstexpr void operator()() const noexcept; constexpr void resume() const noexcept; constexpr void destroy() const noexcept; // [[coroutine.handle.noop.promise]](#coroutine.handle.noop.promise "17.13.5.2.5 Promise access"), promise access noop_coroutine_promise& promise() const noexcept; // [[coroutine.handle.noop.address]](#coroutine.handle.noop.address "17.13.5.2.6 Address"), addressconstexpr void* address() const noexcept; private: coroutine_handle(*unspecified*); void* ptr; // *exposition only*};} #### [17.13.5.2.2](#coroutine.handle.noop.conv) Conversion [[coroutine.handle.noop.conv]](coroutine.handle.noop.conv) [🔗](#lib:operator_coroutine_handle%3c%3e,coroutine_handle%3cnoop_coroutine_promise%3e) `constexpr operator coroutine_handle<>() const noexcept; ` [1](#coroutine.handle.noop.conv-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L6206) *Effects*: Equivalent to: return coroutine_handle<>​::​from_address(address()); #### [17.13.5.2.3](#coroutine.handle.noop.observers) Observers [[coroutine.handle.noop.observers]](coroutine.handle.noop.observers) [🔗](#lib:operator_bool,coroutine_handle%3cnoop_coroutine_promise%3e) `constexpr explicit operator bool() const noexcept; ` [1](#coroutine.handle.noop.observers-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L6219) *Returns*: true[.](#coroutine.handle.noop.observers-1.sentence-1) [🔗](#lib:done,coroutine_handle%3cnoop_coroutine_promise%3e) `constexpr bool done() const noexcept; ` [2](#coroutine.handle.noop.observers-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L6230) *Returns*: false[.](#coroutine.handle.noop.observers-2.sentence-1) #### [17.13.5.2.4](#coroutine.handle.noop.resumption) Resumption [[coroutine.handle.noop.resumption]](coroutine.handle.noop.resumption) [🔗](#lib:operator(),coroutine_handle%3cnoop_coroutine_promise%3e) `constexpr void operator()() const noexcept; constexpr void resume() const noexcept; constexpr void destroy() const noexcept; ` [1](#coroutine.handle.noop.resumption-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L6247) *Effects*: None[.](#coroutine.handle.noop.resumption-1.sentence-1) [2](#coroutine.handle.noop.resumption-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L6251) *Remarks*: If noop_coroutine_handle is converted to coroutine_handle<>, calls to operator(), resume and destroy on that handle will also have no observable effects[.](#coroutine.handle.noop.resumption-2.sentence-1) #### [17.13.5.2.5](#coroutine.handle.noop.promise) Promise access [[coroutine.handle.noop.promise]](coroutine.handle.noop.promise) [🔗](#lib:promise,coroutine_handle%3cnoop_coroutine_promise%3e) `noop_coroutine_promise& promise() const noexcept; ` [1](#coroutine.handle.noop.promise-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L6266) *Returns*: A reference to the promise object associated with this coroutine handle[.](#coroutine.handle.noop.promise-1.sentence-1) #### [17.13.5.2.6](#coroutine.handle.noop.address) Address [[coroutine.handle.noop.address]](coroutine.handle.noop.address) [🔗](#lib:address,coroutine_handle%3cnoop_coroutine_promise%3e) `constexpr void* address() const noexcept; ` [1](#coroutine.handle.noop.address-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L6280) *Returns*: ptr[.](#coroutine.handle.noop.address-1.sentence-1) [2](#coroutine.handle.noop.address-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L6284) *Remarks*: A noop_coroutine_handle's ptr is always a non-null pointer value[.](#coroutine.handle.noop.address-2.sentence-1) #### [17.13.5.3](#coroutine.noop.coroutine) Function noop_coroutine [[coroutine.noop.coroutine]](coroutine.noop.coroutine) [🔗](#lib:noop_coroutine) `noop_coroutine_handle noop_coroutine() noexcept; ` [1](#coroutine.noop.coroutine-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L6298) *Returns*: A handle to a coroutine that has no observable effects when resumed or destroyed[.](#coroutine.noop.coroutine-1.sentence-1) [2](#coroutine.noop.coroutine-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L6303) *Remarks*: A handle returned from noop_coroutine may or may not compare equal to a handle returned from another invocation of noop_coroutine[.](#coroutine.noop.coroutine-2.sentence-1) ### [17.13.6](#coroutine.trivial.awaitables) Trivial awaitables [[coroutine.trivial.awaitables]](coroutine.trivial.awaitables) [🔗](#lib:suspend_never) namespace std {struct suspend_never {constexpr bool await_ready() const noexcept { return true; }constexpr void await_suspend(coroutine_handle<>) const noexcept {}constexpr void await_resume() const noexcept {}}; struct suspend_always {constexpr bool await_ready() const noexcept { return false; }constexpr void await_suspend(coroutine_handle<>) const noexcept {}constexpr void await_resume() const noexcept {}};} [1](#coroutine.trivial.awaitables-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L6335) [*Note [1](#coroutine.trivial.awaitables-note-1)*: The types suspend_never and suspend_always can be used to indicate that an [*await-expression*](expr.await#nt:await-expression "7.6.2.4 Await [expr.await]") either never suspends or always suspends, and in either case does not produce a value[.](#coroutine.trivial.awaitables-1.sentence-1) — *end note*]