Warning: This file is not a C or C++ file. It does not have highlighting.
1 | //===----------------------------------------------------------------------===// |
---|---|
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #ifndef _LIBCPP___COROUTINE_COROUTINE_HANDLE_H |
10 | #define _LIBCPP___COROUTINE_COROUTINE_HANDLE_H |
11 | |
12 | #include <__assert> |
13 | #include <__config> |
14 | #include <__cstddef/nullptr_t.h> |
15 | #include <__cstddef/size_t.h> |
16 | #include <__functional/hash.h> |
17 | #include <__memory/addressof.h> |
18 | #include <__type_traits/remove_cv.h> |
19 | #include <compare> |
20 | |
21 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
22 | # pragma GCC system_header |
23 | #endif |
24 | |
25 | #if _LIBCPP_STD_VER >= 20 |
26 | |
27 | _LIBCPP_BEGIN_NAMESPACE_STD |
28 | |
29 | // [coroutine.handle] |
30 | template <class _Promise = void> |
31 | struct coroutine_handle; |
32 | |
33 | template <> |
34 | struct coroutine_handle<void> { |
35 | public: |
36 | // [coroutine.handle.con], construct/reset |
37 | constexpr coroutine_handle() noexcept = default; |
38 | |
39 | _LIBCPP_HIDE_FROM_ABI constexpr coroutine_handle(nullptr_t) noexcept {} |
40 | |
41 | _LIBCPP_HIDE_FROM_ABI coroutine_handle& operator=(nullptr_t) noexcept { |
42 | __handle_ = nullptr; |
43 | return *this; |
44 | } |
45 | |
46 | // [coroutine.handle.export.import], export/import |
47 | _LIBCPP_HIDE_FROM_ABI constexpr void* address() const noexcept { return __handle_; } |
48 | |
49 | _LIBCPP_HIDE_FROM_ABI static constexpr coroutine_handle from_address(void* __addr) noexcept { |
50 | coroutine_handle __tmp; |
51 | __tmp.__handle_ = __addr; |
52 | return __tmp; |
53 | } |
54 | |
55 | // [coroutine.handle.observers], observers |
56 | _LIBCPP_HIDE_FROM_ABI constexpr explicit operator bool() const noexcept { return __handle_ != nullptr; } |
57 | |
58 | _LIBCPP_HIDE_FROM_ABI bool done() const { |
59 | _LIBCPP_ASSERT_VALID_EXTERNAL_API_CALL(__is_suspended(), "done() can be called only on suspended coroutines"); |
60 | return __builtin_coro_done(__handle_); |
61 | } |
62 | |
63 | // [coroutine.handle.resumption], resumption |
64 | _LIBCPP_HIDE_FROM_ABI void operator()() const { resume(); } |
65 | |
66 | _LIBCPP_HIDE_FROM_ABI void resume() const { |
67 | _LIBCPP_ASSERT_VALID_EXTERNAL_API_CALL(__is_suspended(), "resume() can be called only on suspended coroutines"); |
68 | _LIBCPP_ASSERT_VALID_EXTERNAL_API_CALL(!done(), "resume() has undefined behavior when the coroutine is done"); |
69 | __builtin_coro_resume(__handle_); |
70 | } |
71 | |
72 | _LIBCPP_HIDE_FROM_ABI void destroy() const { |
73 | _LIBCPP_ASSERT_VALID_EXTERNAL_API_CALL(__is_suspended(), "destroy() can be called only on suspended coroutines"); |
74 | __builtin_coro_destroy(__handle_); |
75 | } |
76 | |
77 | private: |
78 | _LIBCPP_HIDE_FROM_ABI bool __is_suspended() const { |
79 | // FIXME actually implement a check for if the coro is suspended. |
80 | return __handle_ != nullptr; |
81 | } |
82 | |
83 | void* __handle_ = nullptr; |
84 | }; |
85 | |
86 | // [coroutine.handle.compare] |
87 | inline _LIBCPP_HIDE_FROM_ABI constexpr bool operator==(coroutine_handle<> __x, coroutine_handle<> __y) noexcept { |
88 | return __x.address() == __y.address(); |
89 | } |
90 | inline _LIBCPP_HIDE_FROM_ABI constexpr strong_ordering |
91 | operator<=>(coroutine_handle<> __x, coroutine_handle<> __y) noexcept { |
92 | return compare_three_way()(__x.address(), __y.address()); |
93 | } |
94 | |
95 | template <class _Promise> |
96 | struct coroutine_handle { |
97 | public: |
98 | // [coroutine.handle.con], construct/reset |
99 | constexpr coroutine_handle() noexcept = default; |
100 | |
101 | _LIBCPP_HIDE_FROM_ABI constexpr coroutine_handle(nullptr_t) noexcept {} |
102 | |
103 | _LIBCPP_HIDE_FROM_ABI static coroutine_handle from_promise(_Promise& __promise) { |
104 | using _RawPromise = __remove_cv_t<_Promise>; |
105 | coroutine_handle __tmp; |
106 | __tmp.__handle_ = |
107 | __builtin_coro_promise(std::addressof(const_cast<_RawPromise&>(__promise)), alignof(_Promise), true); |
108 | return __tmp; |
109 | } |
110 | |
111 | _LIBCPP_HIDE_FROM_ABI coroutine_handle& operator=(nullptr_t) noexcept { |
112 | __handle_ = nullptr; |
113 | return *this; |
114 | } |
115 | |
116 | // [coroutine.handle.export.import], export/import |
117 | _LIBCPP_HIDE_FROM_ABI constexpr void* address() const noexcept { return __handle_; } |
118 | |
119 | _LIBCPP_HIDE_FROM_ABI static constexpr coroutine_handle from_address(void* __addr) noexcept { |
120 | coroutine_handle __tmp; |
121 | __tmp.__handle_ = __addr; |
122 | return __tmp; |
123 | } |
124 | |
125 | // [coroutine.handle.conv], conversion |
126 | _LIBCPP_HIDE_FROM_ABI constexpr operator coroutine_handle<>() const noexcept { |
127 | return coroutine_handle<>::from_address(address()); |
128 | } |
129 | |
130 | // [coroutine.handle.observers], observers |
131 | _LIBCPP_HIDE_FROM_ABI constexpr explicit operator bool() const noexcept { return __handle_ != nullptr; } |
132 | |
133 | _LIBCPP_HIDE_FROM_ABI bool done() const { |
134 | _LIBCPP_ASSERT_VALID_EXTERNAL_API_CALL(__is_suspended(), "done() can be called only on suspended coroutines"); |
135 | return __builtin_coro_done(__handle_); |
136 | } |
137 | |
138 | // [coroutine.handle.resumption], resumption |
139 | _LIBCPP_HIDE_FROM_ABI void operator()() const { resume(); } |
140 | |
141 | _LIBCPP_HIDE_FROM_ABI void resume() const { |
142 | _LIBCPP_ASSERT_VALID_EXTERNAL_API_CALL(__is_suspended(), "resume() can be called only on suspended coroutines"); |
143 | _LIBCPP_ASSERT_VALID_EXTERNAL_API_CALL(!done(), "resume() has undefined behavior when the coroutine is done"); |
144 | __builtin_coro_resume(__handle_); |
145 | } |
146 | |
147 | _LIBCPP_HIDE_FROM_ABI void destroy() const { |
148 | _LIBCPP_ASSERT_VALID_EXTERNAL_API_CALL(__is_suspended(), "destroy() can be called only on suspended coroutines"); |
149 | __builtin_coro_destroy(__handle_); |
150 | } |
151 | |
152 | // [coroutine.handle.promise], promise access |
153 | _LIBCPP_HIDE_FROM_ABI _Promise& promise() const { |
154 | return *static_cast<_Promise*>(__builtin_coro_promise(this->__handle_, alignof(_Promise), false)); |
155 | } |
156 | |
157 | private: |
158 | _LIBCPP_HIDE_FROM_ABI bool __is_suspended() const { |
159 | // FIXME actually implement a check for if the coro is suspended. |
160 | return __handle_ != nullptr; |
161 | } |
162 | void* __handle_ = nullptr; |
163 | }; |
164 | |
165 | // [coroutine.handle.hash] |
166 | template <class _Tp> |
167 | struct hash<coroutine_handle<_Tp>> { |
168 | _LIBCPP_HIDE_FROM_ABI size_t operator()(const coroutine_handle<_Tp>& __v) const noexcept { |
169 | return hash<void*>()(__v.address()); |
170 | } |
171 | }; |
172 | |
173 | _LIBCPP_END_NAMESPACE_STD |
174 | |
175 | #endif // __LIBCPP_STD_VER >= 20 |
176 | |
177 | #endif // _LIBCPP___COROUTINE_COROUTINE_HANDLE_H |
178 |
Warning: This file is not a C or C++ file. It does not have highlighting.