1// <coroutine> -*- C++ -*-
2
3// Copyright (C) 2019-2021 Free Software Foundation, Inc.
4//
5// This file is part of the GNU ISO C++ Library. This library is free
6// software; you can redistribute it and/or modify it under the
7// terms of the GNU General Public License as published by the
8// Free Software Foundation; either version 3, or (at your option)
9// any later version.
10
11// This library is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// Under Section 7 of GPL version 3, you are granted additional
17// permissions described in the GCC Runtime Library Exception, version
18// 3.1, as published by the Free Software Foundation.
19
20// You should have received a copy of the GNU General Public License and
21// a copy of the GCC Runtime Library Exception along with this program;
22// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23// <http://www.gnu.org/licenses/>.
24
25/** @file include/coroutine
26 * This is a Standard C++ Library header.
27 */
28
29#ifndef _GLIBCXX_COROUTINE
30#define _GLIBCXX_COROUTINE 1
31
32#pragma GCC system_header
33
34// It is very likely that earlier versions would work, but they are untested.
35#if __cplusplus >= 201402L
36
37#include <bits/c++config.h>
38
39/**
40 * @defgroup coroutines Coroutines
41 *
42 * Components for supporting coroutine implementations.
43 */
44
45#if __cplusplus > 201703L && __cpp_impl_three_way_comparison >= 201907L
46# include <compare>
47# define _COROUTINES_USE_SPACESHIP 1
48#else
49# include <bits/stl_function.h> // for std::less
50# define _COROUTINES_USE_SPACESHIP 0
51#endif
52
53namespace std _GLIBCXX_VISIBILITY (default)
54{
55_GLIBCXX_BEGIN_NAMESPACE_VERSION
56
57#if __cpp_impl_coroutine
58
59#define __cpp_lib_coroutine 201902L
60
61 inline namespace __n4861 {
62
63 // 17.12.2 coroutine traits
64 /// [coroutine.traits]
65 /// [coroutine.traits.primary]
66 /// If _Result::promise_type is valid and denotes a type then the traits
67 /// have a single publicly accessible member, otherwise they are empty.
68 template <typename _Result, typename = void>
69 struct __coroutine_traits_impl {};
70
71 template <typename _Result>
72 struct __coroutine_traits_impl<_Result,
73 __void_t<typename _Result::promise_type>>
74 {
75 using promise_type = typename _Result::promise_type;
76 };
77
78 template <typename _Result, typename...>
79 struct coroutine_traits : __coroutine_traits_impl<_Result> {};
80
81 // 17.12.3 Class template coroutine_handle
82 /// [coroutine.handle]
83 template <typename _Promise = void>
84 struct coroutine_handle;
85
86 template <> struct
87 coroutine_handle<void>
88 {
89 public:
90 // [coroutine.handle.con], construct/reset
91 constexpr coroutine_handle() noexcept : _M_fr_ptr(0) {}
92
93 constexpr coroutine_handle(std::nullptr_t __h) noexcept
94 : _M_fr_ptr(__h)
95 {}
96
97 coroutine_handle& operator=(std::nullptr_t) noexcept
98 {
99 _M_fr_ptr = nullptr;
100 return *this;
101 }
102
103 public:
104 // [coroutine.handle.export.import], export/import
105 constexpr void* address() const noexcept { return _M_fr_ptr; }
106
107 constexpr static coroutine_handle from_address(void* __a) noexcept
108 {
109 coroutine_handle __self;
110 __self._M_fr_ptr = __a;
111 return __self;
112 }
113
114 public:
115 // [coroutine.handle.observers], observers
116 constexpr explicit operator bool() const noexcept
117 {
118 return bool(_M_fr_ptr);
119 }
120
121 bool done() const noexcept { return __builtin_coro_done(_M_fr_ptr); }
122
123 // [coroutine.handle.resumption], resumption
124 void operator()() const { resume(); }
125
126 void resume() const { __builtin_coro_resume(_M_fr_ptr); }
127
128 void destroy() const { __builtin_coro_destroy(_M_fr_ptr); }
129
130 protected:
131 void* _M_fr_ptr;
132 };
133
134 // [coroutine.handle.compare], comparison operators
135
136 constexpr bool
137 operator==(coroutine_handle<> __a, coroutine_handle<> __b) noexcept
138 {
139 return __a.address() == __b.address();
140 }
141
142#if _COROUTINES_USE_SPACESHIP
143 constexpr strong_ordering
144 operator<=>(coroutine_handle<> __a, coroutine_handle<> __b) noexcept
145 {
146 return std::compare_three_way()(__a.address(), __b.address());
147 }
148#else
149 // These are to enable operation with std=c++14,17.
150 constexpr bool
151 operator!=(coroutine_handle<> __a, coroutine_handle<> __b) noexcept
152 {
153 return !(__a == __b);
154 }
155
156 constexpr bool
157 operator<(coroutine_handle<> __a, coroutine_handle<> __b) noexcept
158 {
159 return less<void*>()(__a.address(), __b.address());
160 }
161
162 constexpr bool
163 operator>(coroutine_handle<> __a, coroutine_handle<> __b) noexcept
164 {
165 return __b < __a;
166 }
167
168 constexpr bool
169 operator<=(coroutine_handle<> __a, coroutine_handle<> __b) noexcept
170 {
171 return !(__a > __b);
172 }
173
174 constexpr bool
175 operator>=(coroutine_handle<> __a, coroutine_handle<> __b) noexcept
176 {
177 return !(__a < __b);
178 }
179#endif
180
181 template <typename _Promise>
182 struct coroutine_handle
183 {
184 // [coroutine.handle.con], construct/reset
185
186 constexpr coroutine_handle() noexcept { }
187
188 constexpr coroutine_handle(nullptr_t) noexcept { }
189
190 static coroutine_handle
191 from_promise(_Promise& __p)
192 {
193 coroutine_handle __self;
194 __self._M_fr_ptr
195 = __builtin_coro_promise((char*) &__p, __alignof(_Promise), true);
196 return __self;
197 }
198
199 coroutine_handle& operator=(nullptr_t) noexcept
200 {
201 _M_fr_ptr = nullptr;
202 return *this;
203 }
204
205 // [coroutine.handle.export.import], export/import
206
207 constexpr void* address() const noexcept { return _M_fr_ptr; }
208
209 constexpr static coroutine_handle from_address(void* __a) noexcept
210 {
211 coroutine_handle __self;
212 __self._M_fr_ptr = __a;
213 return __self;
214 }
215
216 // [coroutine.handle.conv], conversion
217 constexpr operator coroutine_handle<>() const noexcept
218 { return coroutine_handle<>::from_address(address()); }
219
220 // [coroutine.handle.observers], observers
221 constexpr explicit operator bool() const noexcept
222 {
223 return bool(_M_fr_ptr);
224 }
225
226 bool done() const noexcept { return __builtin_coro_done(_M_fr_ptr); }
227
228 // [coroutine.handle.resumption], resumption
229 void operator()() const { resume(); }
230
231 void resume() const { __builtin_coro_resume(_M_fr_ptr); }
232
233 void destroy() const { __builtin_coro_destroy(_M_fr_ptr); }
234
235 // [coroutine.handle.promise], promise access
236 _Promise& promise() const
237 {
238 void* __t
239 = __builtin_coro_promise (_M_fr_ptr, __alignof(_Promise), false);
240 return *static_cast<_Promise*>(__t);
241 }
242
243 private:
244 void* _M_fr_ptr = nullptr;
245 };
246
247 /// [coroutine.noop]
248 struct noop_coroutine_promise
249 {
250 };
251
252 // 17.12.4.1 Class noop_coroutine_promise
253 /// [coroutine.promise.noop]
254 template <>
255 struct coroutine_handle<noop_coroutine_promise>
256 {
257 // _GLIBCXX_RESOLVE_LIB_DEFECTS
258 // 3460. Unimplementable noop_coroutine_handle guarantees
259 // [coroutine.handle.noop.conv], conversion
260 constexpr operator coroutine_handle<>() const noexcept
261 { return coroutine_handle<>::from_address(address()); }
262
263 // [coroutine.handle.noop.observers], observers
264 constexpr explicit operator bool() const noexcept { return true; }
265
266 constexpr bool done() const noexcept { return false; }
267
268 // [coroutine.handle.noop.resumption], resumption
269 void operator()() const noexcept {}
270
271 void resume() const noexcept {}
272
273 void destroy() const noexcept {}
274
275 // [coroutine.handle.noop.promise], promise access
276 noop_coroutine_promise& promise() const noexcept
277 { return _S_fr.__p; }
278
279 // [coroutine.handle.noop.address], address
280 constexpr void* address() const noexcept { return _M_fr_ptr; }
281
282 private:
283 friend coroutine_handle noop_coroutine() noexcept;
284
285 struct __frame
286 {
287 static void __dummy_resume_destroy() { }
288
289 void (*__r)() = __dummy_resume_destroy;
290 void (*__d)() = __dummy_resume_destroy;
291 struct noop_coroutine_promise __p;
292 };
293
294 static __frame _S_fr;
295
296 explicit coroutine_handle() noexcept = default;
297
298 void* _M_fr_ptr = &_S_fr;
299 };
300
301 using noop_coroutine_handle = coroutine_handle<noop_coroutine_promise>;
302
303 inline noop_coroutine_handle::__frame
304 noop_coroutine_handle::_S_fr{};
305
306 inline noop_coroutine_handle noop_coroutine() noexcept
307 {
308 return noop_coroutine_handle();
309 }
310
311 // 17.12.5 Trivial awaitables
312 /// [coroutine.trivial.awaitables]
313 struct suspend_always
314 {
315 constexpr bool await_ready() const noexcept { return false; }
316
317 constexpr void await_suspend(coroutine_handle<>) const noexcept {}
318
319 constexpr void await_resume() const noexcept {}
320 };
321
322 struct suspend_never
323 {
324 constexpr bool await_ready() const noexcept { return true; }
325
326 constexpr void await_suspend(coroutine_handle<>) const noexcept {}
327
328 constexpr void await_resume() const noexcept {}
329 };
330
331 } // namespace __n4861
332
333#else
334#error "the coroutine header requires -fcoroutines"
335#endif
336
337 _GLIBCXX_END_NAMESPACE_VERSION
338} // namespace std
339
340#endif // C++14 (we are allowing use from at least this)
341
342#endif // _GLIBCXX_COROUTINE
343

source code of include/c++/11/coroutine