1// <coroutine> -*- C++ -*-
2
3// Copyright (C) 2019-2020 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      // 17.12.3.1, 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      // 17.12.3.2, 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      // 17.12.3.3, 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      // 17.12.3.4, 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  // 17.12.3.6 Comparison operators
135  /// [coroutine.handle.compare]
136  constexpr bool operator==(coroutine_handle<> __a,
137			    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  { return std::compare_three_way()(__a.address(), __b.address()); }
146#else
147  // These are to enable operation with std=c++14,17.
148  constexpr bool operator!=(coroutine_handle<> __a,
149			    coroutine_handle<> __b) noexcept
150  {
151    return !(__a == __b);
152  }
153
154  constexpr bool operator<(coroutine_handle<> __a,
155			   coroutine_handle<> __b) noexcept
156  {
157    return less<void*>()(__a.address(), __b.address());
158  }
159
160  constexpr bool operator>(coroutine_handle<> __a,
161			   coroutine_handle<> __b) noexcept
162  {
163    return __b < __a;
164  }
165
166  constexpr bool operator<=(coroutine_handle<> __a,
167			    coroutine_handle<> __b) noexcept
168  {
169    return !(__a > __b);
170  }
171
172  constexpr bool operator>=(coroutine_handle<> __a,
173			    coroutine_handle<> __b) noexcept
174  {
175    return !(__a < __b);
176  }
177#endif
178
179  template <typename _Promise>
180    struct coroutine_handle : coroutine_handle<>
181    {
182      // 17.12.3.1, construct/reset
183      using coroutine_handle<>::coroutine_handle;
184
185      static coroutine_handle from_promise(_Promise& p)
186      {
187	coroutine_handle __self;
188	__self._M_fr_ptr
189	  = __builtin_coro_promise((char*) &p, __alignof(_Promise), true);
190	return __self;
191      }
192
193      coroutine_handle& operator=(std::nullptr_t) noexcept
194      {
195	coroutine_handle<>::operator=(nullptr);
196	return *this;
197      }
198
199    // 17.12.3.2, export/import
200    constexpr static coroutine_handle from_address(void* __a) noexcept
201    {
202      coroutine_handle __self;
203      __self._M_fr_ptr = __a;
204      return __self;
205    }
206
207    // 17.12.3.5, promise accesss
208    _Promise& promise() const
209    {
210      void* __t
211	= __builtin_coro_promise (this->_M_fr_ptr, __alignof(_Promise), false);
212      return *static_cast<_Promise*>(__t);
213    }
214  };
215
216  /// [coroutine.noop]
217  struct noop_coroutine_promise
218  {
219  };
220
221  void __dummy_resume_destroy() __attribute__((__weak__));
222  void __dummy_resume_destroy() {}
223
224  struct __noop_coro_frame
225  {
226    void (*__r)() = __dummy_resume_destroy;
227    void (*__d)() = __dummy_resume_destroy;
228    struct noop_coroutine_promise __p;
229  } __noop_coro_fr __attribute__((__weak__));
230
231  // 17.12.4.1 Class noop_coroutine_promise
232  /// [coroutine.promise.noop]
233  template <>
234    struct coroutine_handle<noop_coroutine_promise> : public coroutine_handle<>
235    {
236      using _Promise = noop_coroutine_promise;
237
238    public:
239      // 17.12.4.2.1, observers
240      constexpr explicit operator bool() const noexcept { return true; }
241
242      constexpr bool done() const noexcept { return false; }
243
244      // 17.12.4.2.2, resumption
245      void operator()() const noexcept {}
246
247      void resume() const noexcept {}
248
249      void destroy() const noexcept {}
250
251      // 17.12.4.2.3, promise access
252      _Promise& promise() const
253      {
254	return *static_cast<_Promise*>(
255	  __builtin_coro_promise(this->_M_fr_ptr, __alignof(_Promise), false));
256      }
257
258      // 17.12.4.2.4, address
259    private:
260      friend coroutine_handle<noop_coroutine_promise> noop_coroutine() noexcept;
261
262      coroutine_handle() noexcept { this->_M_fr_ptr = (void*) &__noop_coro_fr; }
263    };
264
265  using noop_coroutine_handle = coroutine_handle<noop_coroutine_promise>;
266
267  inline noop_coroutine_handle noop_coroutine() noexcept
268  {
269    return noop_coroutine_handle();
270  }
271
272  // 17.12.5 Trivial awaitables
273  /// [coroutine.trivial.awaitables]
274  struct suspend_always
275  {
276    constexpr bool await_ready() const noexcept { return false; }
277
278    constexpr void await_suspend(coroutine_handle<>) const noexcept {}
279
280    constexpr void await_resume() const noexcept {}
281  };
282
283  struct suspend_never
284  {
285    constexpr bool await_ready() const noexcept { return true; }
286
287    constexpr void await_suspend(coroutine_handle<>) const noexcept {}
288
289    constexpr void await_resume() const noexcept {}
290  };
291
292  } // namespace __n4861
293
294#else
295#error "the coroutine header requires -fcoroutines"
296#endif
297
298  _GLIBCXX_END_NAMESPACE_VERSION
299} // namespace std
300
301#endif // C++14 (we are allowing use from at least this)
302
303#endif // _GLIBCXX_COROUTINE
304