301 lines
11 KiB
Markdown
301 lines
11 KiB
Markdown
[coroutine.handle]
|
||
|
||
# 17 Language support library [[support]](./#support)
|
||
|
||
## 17.13 Coroutines [[support.coroutine]](support.coroutine#coroutine.handle)
|
||
|
||
### 17.13.4 Class template coroutine_handle [coroutine.handle]
|
||
|
||
#### [17.13.4.1](#general) General [[coroutine.handle.general]](coroutine.handle.general)
|
||
|
||
[ð](#lib:coroutine_handle)
|
||
|
||
namespace std {template<>struct coroutine_handle<void>{// [[coroutine.handle.con]](#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]](#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]](#observers "17.13.4.5 Observers"), observersconstexpr explicit operator bool() const noexcept; bool done() const; // [[coroutine.handle.resumption]](#resumption "17.13.4.6 Resumption"), resumptionvoid operator()() const; void resume() const; void destroy() const; private:void* ptr; // *exposition only*}; template<class Promise>struct coroutine_handle {// [[coroutine.handle.con]](#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]](#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]](#conv "17.13.4.3 Conversion"), conversionconstexpr operator coroutine_handle<>() const noexcept; // [[coroutine.handle.observers]](#observers "17.13.4.5 Observers"), observersconstexpr explicit operator bool() const noexcept; bool done() const; // [[coroutine.handle.resumption]](#resumption "17.13.4.6 Resumption"), resumptionvoid operator()() const; void resume() const; void destroy() const; // [[coroutine.handle.promise]](#promise "17.13.4.7 Promise access"), promise access Promise& promise() const; private:void* ptr; // *exposition only*};}
|
||
|
||
[1](#general-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L5892)
|
||
|
||
An object of typecoroutine_handle<T> is called a [*coroutine handle*](#def:coroutine_handle) and can be used to refer to a suspended or executing coroutine[.](#general-1.sentence-1)
|
||
|
||
A coroutine_handle object whose
|
||
member address() returns a null pointer value
|
||
does not refer to any
|
||
coroutine[.](#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[.](#general-1.sentence-3)
|
||
|
||
[2](#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[.](#general-2.sentence-1)
|
||
|
||
#### [17.13.4.2](#con) Construct/reset [[coroutine.handle.con]](coroutine.handle.con)
|
||
|
||
[ð](#lib:coroutine_handle,constructor)
|
||
|
||
`constexpr coroutine_handle() noexcept;
|
||
constexpr coroutine_handle(nullptr_t) noexcept;
|
||
`
|
||
|
||
[1](#con-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L5916)
|
||
|
||
*Postconditions*: address() == nullptr[.](#con-1.sentence-1)
|
||
|
||
[ð](#lib:from_promise,coroutine_handle)
|
||
|
||
`static coroutine_handle from_promise(Promise& p);
|
||
`
|
||
|
||
[2](#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[.](#con-2.sentence-1)
|
||
|
||
[3](#con-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L5931)
|
||
|
||
*Postconditions*: addressof(h.promise()) == addressof(p)[.](#con-3.sentence-1)
|
||
|
||
[4](#con-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L5935)
|
||
|
||
*Returns*: A coroutine handle h referring to the coroutine[.](#con-4.sentence-1)
|
||
|
||
[ð](#lib:operator=,coroutine_handle)
|
||
|
||
`coroutine_handle& operator=(nullptr_t) noexcept;
|
||
`
|
||
|
||
[5](#con-5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L5946)
|
||
|
||
*Postconditions*: address() == nullptr[.](#con-5.sentence-1)
|
||
|
||
[6](#con-6)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L5950)
|
||
|
||
*Returns*: *this[.](#con-6.sentence-1)
|
||
|
||
#### [17.13.4.3](#conv) Conversion [[coroutine.handle.conv]](coroutine.handle.conv)
|
||
|
||
[ð](#lib:operator_coroutine_handle%3c%3e,coroutine_handle)
|
||
|
||
`constexpr operator coroutine_handle<>() const noexcept;
|
||
`
|
||
|
||
[1](#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](#export.import) Export/import [[coroutine.handle.export.import]](coroutine.handle.export.import)
|
||
|
||
[ð](#lib:address,coroutine_handle)
|
||
|
||
`constexpr void* address() const noexcept;
|
||
`
|
||
|
||
[1](#export.import-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L5976)
|
||
|
||
*Returns*: ptr[.](#export.import-1.sentence-1)
|
||
|
||
[ð](#lib:from_address,coroutine_handle)
|
||
|
||
`static constexpr coroutine_handle<> coroutine_handle<>::from_address(void* addr);
|
||
`
|
||
|
||
[2](#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[.](#export.import-2.sentence-1)
|
||
|
||
[3](#export.import-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L5992)
|
||
|
||
*Postconditions*: from_address(address()) == *this[.](#export.import-3.sentence-1)
|
||
|
||
[ð](#lib:from_address,coroutine_handle_)
|
||
|
||
`static constexpr coroutine_handle<Promise> coroutine_handle<Promise>::from_address(void* addr);
|
||
`
|
||
|
||
[4](#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<Promise>[.](#export.import-4.sentence-1)
|
||
|
||
[5](#export.import-5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L6008)
|
||
|
||
*Postconditions*: from_address(address()) == *this[.](#export.import-5.sentence-1)
|
||
|
||
#### [17.13.4.5](#observers) Observers [[coroutine.handle.observers]](coroutine.handle.observers)
|
||
|
||
[ð](#lib:operator_bool,coroutine_handle)
|
||
|
||
`constexpr explicit operator bool() const noexcept;
|
||
`
|
||
|
||
[1](#observers-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L6021)
|
||
|
||
*Returns*: address() != nullptr[.](#observers-1.sentence-1)
|
||
|
||
[ð](#lib:done,coroutine_handle)
|
||
|
||
`bool done() const;
|
||
`
|
||
|
||
[2](#observers-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L6032)
|
||
|
||
*Preconditions*: *this refers to a suspended coroutine[.](#observers-2.sentence-1)
|
||
|
||
[3](#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[.](#observers-3.sentence-1)
|
||
|
||
#### [17.13.4.6](#resumption) Resumption [[coroutine.handle.resumption]](coroutine.handle.resumption)
|
||
|
||
[1](#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[.](#resumption-1.sentence-1)
|
||
|
||
[*Note [1](#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[.](#resumption-1.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[*Note [2](#resumption-note-2)*:
|
||
|
||
A concurrent resumption of the coroutine can result in a data race[.](#resumption-1.sentence-3)
|
||
|
||
â *end note*]
|
||
|
||
[ð](#lib:operator(),coroutine_handle)
|
||
|
||
`void operator()() const;
|
||
void resume() const;
|
||
`
|
||
|
||
[2](#resumption-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L6069)
|
||
|
||
*Preconditions*: *this refers to a suspended coroutine[.](#resumption-2.sentence-1)
|
||
|
||
The coroutine is not suspended at its final suspend point[.](#resumption-2.sentence-2)
|
||
|
||
[3](#resumption-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L6074)
|
||
|
||
*Effects*: Resumes the execution of the coroutine[.](#resumption-3.sentence-1)
|
||
|
||
[ð](#lib:destroy,coroutine_handle)
|
||
|
||
`void destroy() const;
|
||
`
|
||
|
||
[4](#resumption-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L6085)
|
||
|
||
*Preconditions*: *this refers to a suspended coroutine[.](#resumption-4.sentence-1)
|
||
|
||
[5](#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"))[.](#resumption-5.sentence-1)
|
||
|
||
#### [17.13.4.7](#promise) Promise access [[coroutine.handle.promise]](coroutine.handle.promise)
|
||
|
||
[ð](#lib:promise,coroutine_handle)
|
||
|
||
`Promise& promise() const;
|
||
`
|
||
|
||
[1](#promise-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L6102)
|
||
|
||
*Preconditions*: *this refers to a coroutine[.](#promise-1.sentence-1)
|
||
|
||
[2](#promise-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L6106)
|
||
|
||
*Returns*: A reference to the promise of the coroutine[.](#promise-2.sentence-1)
|
||
|
||
#### [17.13.4.8](#compare) Comparison operators [[coroutine.handle.compare]](coroutine.handle.compare)
|
||
|
||
[ð](#lib:operator==,coroutine_handle)
|
||
|
||
`constexpr bool operator==(coroutine_handle<> x, coroutine_handle<> y) noexcept;
|
||
`
|
||
|
||
[1](#compare-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L6120)
|
||
|
||
*Returns*: x.address() == y.address()[.](#compare-1.sentence-1)
|
||
|
||
[ð](#lib:operator%3c=%3e,coroutine_handle)
|
||
|
||
`constexpr strong_ordering operator<=>(coroutine_handle<> x, coroutine_handle<> y) noexcept;
|
||
`
|
||
|
||
[2](#compare-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L6131)
|
||
|
||
*Returns*: compare_three_way()(x.address(), y.address())[.](#compare-2.sentence-1)
|
||
|
||
#### [17.13.4.9](#hash) Hash support [[coroutine.handle.hash]](coroutine.handle.hash)
|
||
|
||
[ð](#lib:hash,coroutine_handle)
|
||
|
||
`template<class P> struct hash<coroutine_handle<P>>;
|
||
`
|
||
|
||
[1](#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"))[.](#hash-1.sentence-1)
|