Async++ unknown
Async (co_await/co_return) code for C++
Loading...
Searching...
No Matches
std_import.h
Go to the documentation of this file.
1#pragma once
7#if __has_include(<coroutine>) && __cpp_impl_coroutine
8// This is perfect
9#include <coroutine>
10namespace asyncpp {
11 using std::coroutine_handle;
12 using std::noop_coroutine;
13 using std::suspend_always;
14 using std::suspend_never;
15} // namespace asyncpp
16#elif __has_include(<experimental/coroutine>)
17// We might hit some bugs
18#include <experimental/coroutine>
19namespace asyncpp {
20 using std::experimental::coroutine_handle;
21 using std::experimental::noop_coroutine;
22 using std::experimental::suspend_always;
23 using std::experimental::suspend_never;
24} // namespace asyncpp
25#else
26// We are all going to die
27#include <cassert>
28#include <cstddef>
29#include <functional>
30#include <memory> // for hash<T*>
31#include <new>
32#include <type_traits>
33
34namespace std::experimental {
35 inline namespace coroutines_v1 {
36
37 template<class>
38 struct __void_t {
39 typedef void type;
40 };
41
42 template<class _Tp, class = void>
43 struct __coroutine_traits_sfinae {};
44
45 template<class _Tp>
46 struct __coroutine_traits_sfinae<_Tp, typename __void_t<typename _Tp::promise_type>::type> {
47 using promise_type = typename _Tp::promise_type;
48 };
49
50 template<typename _Ret, typename... _Args>
51 struct coroutine_traits : public __coroutine_traits_sfinae<_Ret> {};
52
53 template<typename _Promise = void>
54 class __attribute__((__visibility__("default"))) coroutine_handle;
55
56 template<>
57 class __attribute__((__visibility__("default"))) coroutine_handle<void> {
58 public:
59 __attribute__((__visibility__("hidden")))
60 __attribute__((__always_inline__)) constexpr coroutine_handle() noexcept
61 : __handle_(nullptr) {}
62
63 __attribute__((__visibility__("hidden")))
64 __attribute__((__always_inline__)) constexpr coroutine_handle(nullptr_t) noexcept
65 : __handle_(nullptr) {}
66
67 __attribute__((__visibility__("hidden"))) __attribute__((__always_inline__)) coroutine_handle&
68 operator=(nullptr_t) noexcept {
69 __handle_ = nullptr;
70 return *this;
71 }
72
73 __attribute__((__visibility__("hidden"))) __attribute__((__always_inline__)) constexpr void*
74 address() const noexcept {
75 return __handle_;
76 }
77
78 __attribute__((__visibility__("hidden"))) __attribute__((__always_inline__)) constexpr explicit
79 operator bool() const noexcept {
80 return __handle_;
81 }
82
83 __attribute__((__visibility__("hidden"))) __attribute__((__always_inline__)) void operator()() const {
84 resume();
85 }
86
87 __attribute__((__visibility__("hidden"))) __attribute__((__always_inline__)) void resume() const {
88 assert(__is_suspended());
89 assert(!done());
90 __builtin_coro_resume(__handle_);
91 }
92
93 __attribute__((__visibility__("hidden"))) __attribute__((__always_inline__)) void destroy() const {
94 assert(__is_suspended());
95 __builtin_coro_destroy(__handle_);
96 }
97
98 __attribute__((__visibility__("hidden"))) __attribute__((__always_inline__)) bool done() const noexcept {
99 assert(__is_suspended());
100 return __builtin_coro_done(__handle_);
101 }
102
103 public:
104 __attribute__((__visibility__("hidden"))) __attribute__((__always_inline__)) static coroutine_handle
105 from_address(void* __addr) noexcept {
106 coroutine_handle __tmp;
107 __tmp.__handle_ = __addr;
108 return __tmp;
109 }
110
111 // FIXME: Should from_address(nullptr) be allowed?
112 __attribute__((__visibility__("hidden"))) __attribute__((__always_inline__)) static coroutine_handle
113 from_address(nullptr_t) noexcept {
114 return coroutine_handle(nullptr);
115 }
116
117 template<class _Tp, bool _CallIsValid = false>
118 static coroutine_handle from_address(_Tp*) {
119 static_assert(_CallIsValid, "coroutine_handle<void>::from_address cannot be called with "
120 "non-void pointers");
121 }
122
123 private:
124 bool __is_suspended() const noexcept {
125 // FIXME actually implement a check for if the coro is suspended.
126 return __handle_;
127 }
128
129 template<class _PromiseT>
130 friend class coroutine_handle;
131 void* __handle_;
132 };
133
134 // 18.11.2.7 comparison operators:
135 inline __attribute__((__visibility__("hidden"))) __attribute__((__always_inline__)) bool
136 operator==(coroutine_handle<> __x, coroutine_handle<> __y) noexcept {
137 return __x.address() == __y.address();
138 }
139 inline __attribute__((__visibility__("hidden"))) __attribute__((__always_inline__)) bool
140 operator!=(coroutine_handle<> __x, coroutine_handle<> __y) noexcept {
141 return !(__x == __y);
142 }
143 inline __attribute__((__visibility__("hidden"))) __attribute__((__always_inline__)) bool
144 operator<(coroutine_handle<> __x, coroutine_handle<> __y) noexcept {
145 return less<void*>()(__x.address(), __y.address());
146 }
147 inline __attribute__((__visibility__("hidden"))) __attribute__((__always_inline__)) bool
148 operator>(coroutine_handle<> __x, coroutine_handle<> __y) noexcept {
149 return __y < __x;
150 }
151 inline __attribute__((__visibility__("hidden"))) __attribute__((__always_inline__)) bool
152 operator<=(coroutine_handle<> __x, coroutine_handle<> __y) noexcept {
153 return !(__x > __y);
154 }
155 inline __attribute__((__visibility__("hidden"))) __attribute__((__always_inline__)) bool
156 operator>=(coroutine_handle<> __x, coroutine_handle<> __y) noexcept {
157 return !(__x < __y);
158 }
159
160 template<typename _Promise>
161 class __attribute__((__visibility__("default"))) coroutine_handle : public coroutine_handle<> {
162 using _Base = coroutine_handle<>;
163
164 public:
165 // 18.11.2.1 construct/reset
166 using coroutine_handle<>::coroutine_handle;
167 __attribute__((__visibility__("hidden"))) __attribute__((__always_inline__)) coroutine_handle&
168 operator=(nullptr_t) noexcept {
169 _Base::operator=(nullptr);
170 return *this;
171 }
172
173 __attribute__((__visibility__("hidden"))) __attribute__((__always_inline__)) _Promise& promise() const {
174 return *static_cast<_Promise*>(__builtin_coro_promise(this->__handle_, alignof(_Promise), false));
175 }
176
177 public:
178 __attribute__((__visibility__("hidden"))) __attribute__((__always_inline__)) static coroutine_handle
179 from_address(void* __addr) noexcept {
180 coroutine_handle __tmp;
181 __tmp.__handle_ = __addr;
182 return __tmp;
183 }
184
185 // NOTE: this overload isn't required by the standard but is needed so
186 // the deleted _Promise* overload doesn't make from_address(nullptr)
187 // ambiguous.
188 // FIXME: should from_address work with nullptr?
189 __attribute__((__visibility__("hidden"))) __attribute__((__always_inline__)) static coroutine_handle
190 from_address(nullptr_t) noexcept {
191 return coroutine_handle(nullptr);
192 }
193
194 template<class _Tp, bool _CallIsValid = false>
195 static coroutine_handle from_address(_Tp*) {
196 static_assert(_CallIsValid, "coroutine_handle<promise_type>::from_address cannot be called with "
197 "non-void pointers");
198 }
199
200 template<bool _CallIsValid = false>
201 static coroutine_handle from_address(_Promise*) {
202 static_assert(_CallIsValid, "coroutine_handle<promise_type>::from_address cannot be used with "
203 "pointers to the coroutine's promise type; use 'from_promise' instead");
204 }
205
206 __attribute__((__visibility__("hidden"))) __attribute__((__always_inline__)) static coroutine_handle
207 from_promise(_Promise& __promise) noexcept {
208 typedef typename remove_cv<_Promise>::type _RawPromise;
209 coroutine_handle __tmp;
210 __tmp.__handle_ = __builtin_coro_promise(std::addressof(const_cast<_RawPromise&>(__promise)),
211 alignof(_Promise), true);
212 return __tmp;
213 }
214 };
215
216#if __has_builtin(__builtin_coro_noop)
217 struct noop_coroutine_promise {};
218
219 template<>
220 class __attribute__((__visibility__("default")))
221 coroutine_handle<noop_coroutine_promise> : public coroutine_handle<> {
222 using _Base = coroutine_handle<>;
223 using _Promise = noop_coroutine_promise;
224
225 public:
226 __attribute__((__visibility__("hidden"))) __attribute__((__always_inline__)) _Promise& promise() const {
227 return *static_cast<_Promise*>(__builtin_coro_promise(this->__handle_, alignof(_Promise), false));
228 }
229
230 constexpr explicit operator bool() const noexcept { return true; }
231 constexpr bool done() const noexcept { return false; }
232
233 constexpr void operator()() const noexcept {}
234 constexpr void resume() const noexcept {}
235 constexpr void destroy() const noexcept {}
236
237 private:
238 __attribute__((__visibility__("hidden")))
239 __attribute__((__always_inline__)) friend coroutine_handle<noop_coroutine_promise>
240 noop_coroutine() noexcept;
241
242 __attribute__((__visibility__("hidden"))) __attribute__((__always_inline__)) coroutine_handle() noexcept {
243 this->__handle_ = __builtin_coro_noop();
244 }
245 };
246
247 using noop_coroutine_handle = coroutine_handle<noop_coroutine_promise>;
248
249 inline __attribute__((__visibility__("hidden"))) __attribute__((__always_inline__)) noop_coroutine_handle
250 noop_coroutine() noexcept {
251 return noop_coroutine_handle();
252 }
253#endif // __has_builtin(__builtin_coro_noop)
254
255 struct suspend_never {
256 __attribute__((__visibility__("hidden"))) __attribute__((__always_inline__)) bool
257 await_ready() const noexcept {
258 return true;
259 }
260 __attribute__((__visibility__("hidden"))) __attribute__((__always_inline__)) void
261 await_suspend(coroutine_handle<>) const noexcept {}
262 __attribute__((__visibility__("hidden"))) __attribute__((__always_inline__)) void
263 await_resume() const noexcept {}
264 };
265
266 struct suspend_always {
267 __attribute__((__visibility__("hidden"))) __attribute__((__always_inline__)) bool
268 await_ready() const noexcept {
269 return false;
270 }
271 __attribute__((__visibility__("hidden"))) __attribute__((__always_inline__)) void
272 await_suspend(coroutine_handle<>) const noexcept {}
273 __attribute__((__visibility__("hidden"))) __attribute__((__always_inline__)) void
274 await_resume() const noexcept {}
275 };
276
277 } // namespace coroutines_v1
278} // namespace std::experimental
279
280namespace std {
281 template<class _Tp>
282 struct hash<std::experimental::coroutine_handle<_Tp>> {
283 using __arg_type = std::experimental::coroutine_handle<_Tp>;
284 __attribute__((__visibility__("hidden"))) __attribute__((__always_inline__)) size_t
285 operator()(__arg_type const& __v) const noexcept {
286 return hash<void*>()(__v.address());
287 }
288 };
289} // namespace std
290
291namespace asyncpp {
292 using std::experimental::coroutine_handle;
293 using std::experimental::noop_coroutine;
294 using std::experimental::suspend_always;
295 using std::experimental::suspend_never;
296} // namespace asyncpp
297
298#endif