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

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