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