1// <coroutine> -*- C++ -*-
2
3// Copyright (C) 2019-2024 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#define __glibcxx_want_coroutine
35#include <bits/version.h>
36
37#if !__cpp_impl_coroutine
38# error "the <coroutine> header requires -fcoroutines"
39#endif
40
41#ifdef __cpp_lib_coroutine // C++ >= 14 && impl_coroutine
42
43#include <type_traits>
44#if __cplusplus > 201703L
45# include <compare>
46#endif
47
48#if !defined __cpp_lib_three_way_comparison
49# include <bits/stl_function.h> // for std::less
50#endif
51
52/**
53 * @defgroup coroutines Coroutines
54 *
55 * Components for supporting coroutine implementations.
56 *
57 * @since C++20 (and since C++14 as a libstdc++ extension)
58 */
59
60namespace std _GLIBCXX_VISIBILITY (default)
61{
62_GLIBCXX_BEGIN_NAMESPACE_VERSION
63
64 inline namespace __n4861 {
65
66 // C++20 17.12.2 coroutine traits
67 /// [coroutine.traits]
68 /// [coroutine.traits.primary]
69 /// If _Result::promise_type is valid and denotes a type then the traits
70 /// have a single publicly accessible member, otherwise they are empty.
71 template <typename _Result, typename... _ArgTypes>
72 struct coroutine_traits;
73
74 template <typename _Result, typename = void>
75 struct __coroutine_traits_impl {};
76
77 template <typename _Result>
78#if __cpp_concepts
79 requires requires { typename _Result::promise_type; }
80 struct __coroutine_traits_impl<_Result, void>
81#else
82 struct __coroutine_traits_impl<_Result,
83 __void_t<typename _Result::promise_type>>
84#endif
85 {
86 using promise_type = typename _Result::promise_type;
87 };
88
89 template <typename _Result, typename... _ArgTypes>
90 struct coroutine_traits : __coroutine_traits_impl<_Result> {};
91
92 // C++20 17.12.3 Class template coroutine_handle
93 /// [coroutine.handle]
94 template <typename _Promise = void>
95 struct coroutine_handle;
96
97 template <> struct
98 coroutine_handle<void>
99 {
100 public:
101 // [coroutine.handle.con], construct/reset
102 constexpr coroutine_handle() noexcept : _M_fr_ptr(0) {}
103
104 constexpr coroutine_handle(std::nullptr_t __h) noexcept
105 : _M_fr_ptr(__h)
106 {}
107
108 coroutine_handle& operator=(std::nullptr_t) noexcept
109 {
110 _M_fr_ptr = nullptr;
111 return *this;
112 }
113
114 public:
115 // [coroutine.handle.export.import], export/import
116 constexpr void* address() const noexcept { return _M_fr_ptr; }
117
118 constexpr static coroutine_handle from_address(void* __a) noexcept
119 {
120 coroutine_handle __self;
121 __self._M_fr_ptr = __a;
122 return __self;
123 }
124
125 public:
126 // [coroutine.handle.observers], observers
127 constexpr explicit operator bool() const noexcept
128 {
129 return bool(_M_fr_ptr);
130 }
131
132 bool done() const noexcept { return __builtin_coro_done(_M_fr_ptr); }
133
134 // [coroutine.handle.resumption], resumption
135 void operator()() const { resume(); }
136
137 void resume() const { __builtin_coro_resume(_M_fr_ptr); }
138
139 void destroy() const { __builtin_coro_destroy(_M_fr_ptr); }
140
141 protected:
142 void* _M_fr_ptr;
143 };
144
145 // [coroutine.handle.compare], comparison operators
146
147 constexpr bool
148 operator==(coroutine_handle<> __a, coroutine_handle<> __b) noexcept
149 {
150 return __a.address() == __b.address();
151 }
152
153#ifdef __cpp_lib_three_way_comparison
154 constexpr strong_ordering
155 operator<=>(coroutine_handle<> __a, coroutine_handle<> __b) noexcept
156 {
157 return std::compare_three_way()(__a.address(), __b.address());
158 }
159#else
160 // These are to enable operation with std=c++14,17.
161 constexpr bool
162 operator!=(coroutine_handle<> __a, coroutine_handle<> __b) noexcept
163 {
164 return !(__a == __b);
165 }
166
167 constexpr bool
168 operator<(coroutine_handle<> __a, coroutine_handle<> __b) noexcept
169 {
170 return less<void*>()(__a.address(), __b.address());
171 }
172
173 constexpr bool
174 operator>(coroutine_handle<> __a, coroutine_handle<> __b) noexcept
175 {
176 return __b < __a;
177 }
178
179 constexpr bool
180 operator<=(coroutine_handle<> __a, coroutine_handle<> __b) noexcept
181 {
182 return !(__a > __b);
183 }
184
185 constexpr bool
186 operator>=(coroutine_handle<> __a, coroutine_handle<> __b) noexcept
187 {
188 return !(__a < __b);
189 }
190#endif
191
192 template <typename _Promise>
193 struct coroutine_handle
194 {
195 // [coroutine.handle.con], construct/reset
196
197 constexpr coroutine_handle() noexcept { }
198
199 constexpr coroutine_handle(nullptr_t) noexcept { }
200
201 static coroutine_handle
202 from_promise(_Promise& __p)
203 {
204 coroutine_handle __self;
205 __self._M_fr_ptr
206 = __builtin_coro_promise((char*) &__p, __alignof(_Promise), true);
207 return __self;
208 }
209
210 coroutine_handle& operator=(nullptr_t) noexcept
211 {
212 _M_fr_ptr = nullptr;
213 return *this;
214 }
215
216 // [coroutine.handle.export.import], export/import
217
218 constexpr void* address() const noexcept { return _M_fr_ptr; }
219
220 constexpr static coroutine_handle from_address(void* __a) noexcept
221 {
222 coroutine_handle __self;
223 __self._M_fr_ptr = __a;
224 return __self;
225 }
226
227 // [coroutine.handle.conv], conversion
228 constexpr operator coroutine_handle<>() const noexcept
229 { return coroutine_handle<>::from_address(a: address()); }
230
231 // [coroutine.handle.observers], observers
232 constexpr explicit operator bool() const noexcept
233 {
234 return bool(_M_fr_ptr);
235 }
236
237 bool done() const noexcept { return __builtin_coro_done(_M_fr_ptr); }
238
239 // [coroutine.handle.resumption], resumption
240 void operator()() const { resume(); }
241
242 void resume() const { __builtin_coro_resume(_M_fr_ptr); }
243
244 void destroy() const { __builtin_coro_destroy(_M_fr_ptr); }
245
246 // [coroutine.handle.promise], promise access
247 _Promise& promise() const
248 {
249 void* __t
250 = __builtin_coro_promise (_M_fr_ptr, __alignof(_Promise), false);
251 return *static_cast<_Promise*>(__t);
252 }
253
254 private:
255 void* _M_fr_ptr = nullptr;
256 };
257
258 /// [coroutine.noop]
259 struct noop_coroutine_promise
260 {
261 };
262
263 // 17.12.4.1 Class noop_coroutine_promise
264 /// [coroutine.promise.noop]
265 template <>
266 struct coroutine_handle<noop_coroutine_promise>
267 {
268 // _GLIBCXX_RESOLVE_LIB_DEFECTS
269 // 3460. Unimplementable noop_coroutine_handle guarantees
270 // [coroutine.handle.noop.conv], conversion
271 constexpr operator coroutine_handle<>() const noexcept
272 { return coroutine_handle<>::from_address(a: address()); }
273
274 // [coroutine.handle.noop.observers], observers
275 constexpr explicit operator bool() const noexcept { return true; }
276
277 constexpr bool done() const noexcept { return false; }
278
279 // [coroutine.handle.noop.resumption], resumption
280 void operator()() const noexcept {}
281
282 void resume() const noexcept {}
283
284 void destroy() const noexcept {}
285
286 // [coroutine.handle.noop.promise], promise access
287 noop_coroutine_promise& promise() const noexcept
288 { return _S_fr.__p; }
289
290 // [coroutine.handle.noop.address], address
291 constexpr void* address() const noexcept { return _M_fr_ptr; }
292
293 private:
294 friend coroutine_handle noop_coroutine() noexcept;
295
296 struct __frame
297 {
298 static void __dummy_resume_destroy() { }
299
300 void (*__r)() = __dummy_resume_destroy;
301 void (*__d)() = __dummy_resume_destroy;
302 struct noop_coroutine_promise __p;
303 };
304
305 static __frame _S_fr;
306
307 explicit coroutine_handle() noexcept = default;
308
309 void* _M_fr_ptr = &_S_fr;
310 };
311
312 using noop_coroutine_handle = coroutine_handle<noop_coroutine_promise>;
313
314 inline noop_coroutine_handle::__frame
315 noop_coroutine_handle::_S_fr{};
316
317 inline noop_coroutine_handle noop_coroutine() noexcept
318 {
319 return noop_coroutine_handle();
320 }
321
322 // 17.12.5 Trivial awaitables
323 /// [coroutine.trivial.awaitables]
324 struct suspend_always
325 {
326 constexpr bool await_ready() const noexcept { return false; }
327
328 constexpr void await_suspend(coroutine_handle<>) const noexcept {}
329
330 constexpr void await_resume() const noexcept {}
331 };
332
333 struct suspend_never
334 {
335 constexpr bool await_ready() const noexcept { return true; }
336
337 constexpr void await_suspend(coroutine_handle<>) const noexcept {}
338
339 constexpr void await_resume() const noexcept {}
340 };
341
342 } // namespace __n4861
343
344 template<typename _Tp> struct hash;
345
346 template<typename _Promise>
347 struct hash<coroutine_handle<_Promise>>
348 {
349 size_t
350 operator()(const coroutine_handle<_Promise>& __h) const noexcept
351 {
352 return reinterpret_cast<size_t>(__h.address());
353 }
354 };
355
356 _GLIBCXX_END_NAMESPACE_VERSION
357} // namespace std
358
359#endif // __cpp_lib_coroutine
360
361#endif // _GLIBCXX_COROUTINE
362