Hi Jonathan

The SVN commit IDs that relate to the amendments are noted in the
revised patch header below.

Jonathan Wakely <jwak...@redhat.com> wrote:

> On 17/11/19 10:27 +0000, Iain Sandoe wrote:

>>      * include/Makefile.in: Regnerated.
> 
> "Regnerated" typo.
Fixed,

>>      ${experimental_srcdir}/chrono \
>> +    ${experimental_srcdir}/coroutine \
> 
> The experimental dir is (currently) only used for TS headers. All
> C++20 support is currently experimental, so adding <coroutines> where
> <concepts> and <ranges> have been added would be OK.
> 
> But I'm not really clear if this is an implementation of the TS or the
> C++20 feature.  If it's a hybrid, putting it in
> <experimental/coroutines> is fine.

Mea culpa;
this began life as a TS and when it was included in the WD (and then CD)
I failed to move the header and update.

My intention is that the facility will work with at least C++14 as a GNU
extension (as do the impls. in clang and EDG).  In fact, I can’t see any
real reason that it wouldn’t work with C++11 - but time is too short for
that experiment.

> When the final <coroutines> header is added it will need to be in
> libsupc++ so that it's included for freestanding builds (and at that
> point it won't be able to use <bits/stl_function.h>, but that will be
> OK as the final header will be C++20-only and can rely on <compare>
> unconditionally, which is also freestanding).

Well, for the reason above, I have made this not depend on the availability
of <compare> or spaceship.

>> +/** @file experimental/coroutine
>> + *  This is an experimental C++ Library header against the C++20 CD n4835.
>> + *  @ingroup coroutine-ts
> 
> The coroutine-ts doc group should be defined somewhere.

I’ve reworked the doxygen stuff somewhat, although freely admit that it’s 
currently
rather weak as documentation.  I do expect some more editorial changes to the 
std
and documentation could be improved before 10 releases.

>> +  namespace experimental {
>> +  inline namespace coroutines_n4835 {
> 
> This should be a reserved name too, e.g. __coroutines_n4835.
done
>> 
>> +    constexpr coroutine_handle () noexcept : __fr_ptr (0) {}
> 
> The libstdc++ naming convention is _M_xxx for non-static members (both
> data members and member functions) and _S_xxx for static members
> (again, both data member and functions).
> 
> This helps to distinguish members from other uglified names like
> function parameters and local variables.
done.

Hopefully, this amended version is closer and the intent is clearer.
OK for trunk now?
thanks
Iain

———

This provides the interfaces mandated by the standard and implements
the interaction with the coroutine frame by means of inline use of
builtins expanded at compile-time.  There should be a 1:1 correspondence
with the standard sections which are cross-referenced.

There is no runtime content.

At this stage we have the content in an inline namespace "__n4835" for
the current CD.

Squashed commits:

r278724 - Address review comments, GNU naming conventions
r278778 - Address review comments, update doxygen group info.
r279817 - Update copyright year.
r279845 - Address review comments, move coroutine header to std.
r280038 - Correct pathname in the edit header.

libstdc++-v3/ChangeLog:

2020-01-09  Iain Sandoe  <i...@sandoe.co.uk>

        * include/Makefile.am: Add coroutine to the std set.
        * include/Makefile.in: Regenerated.
        * include/std/coroutine: New file.
---
 libstdc++-v3/include/Makefile.am   |   1 +
 libstdc++-v3/include/Makefile.in   |   1 +
 libstdc++-v3/include/std/coroutine | 269 +++++++++++++++++++++++++++++++++++++
 3 files changed, 271 insertions(+)
 create mode 100644 libstdc++-v3/include/std/coroutine

diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am
index b38defcafb..ad4404793b 100644
--- a/libstdc++-v3/include/Makefile.am
+++ b/libstdc++-v3/include/Makefile.am
@@ -38,6 +38,7 @@ std_headers = \
        ${std_srcdir}/complex \
        ${std_srcdir}/concepts \
        ${std_srcdir}/condition_variable \
+       ${std_srcdir}/coroutine \
        ${std_srcdir}/deque \
        ${std_srcdir}/execution \
        ${std_srcdir}/filesystem \
diff --git a/libstdc++-v3/include/Makefile.in b/libstdc++-v3/include/Makefile.in
index ae4a493ea6..f8b5645224 100644
--- a/libstdc++-v3/include/Makefile.in
+++ b/libstdc++-v3/include/Makefile.in
@@ -382,6 +382,7 @@ std_headers = \
        ${std_srcdir}/complex \
        ${std_srcdir}/concepts \
        ${std_srcdir}/condition_variable \
+       ${std_srcdir}/coroutine \
        ${std_srcdir}/deque \
        ${std_srcdir}/execution \
        ${std_srcdir}/filesystem \
diff --git a/libstdc++-v3/include/std/coroutine 
b/libstdc++-v3/include/std/coroutine
new file mode 100644
index 0000000000..9eaffaba12
--- /dev/null
+++ b/libstdc++-v3/include/std/coroutine
@@ -0,0 +1,269 @@
+// <coroutine> -*- C++ -*-
+
+// Copyright (C) 2019-2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file include/coroutine
+ *  This is a Standard C++ Library header.
+ */
+
+#ifndef _GLIBCXX_EXPERIMENTAL_COROUTINE
+#define _GLIBCXX_EXPERIMENTAL_COROUTINE 1
+
+#pragma GCC system_header
+
+// It is very likely that earlier versions would work, but they are untested.
+#if __cplusplus >= 201402L
+
+#include <bits/c++config.h>
+
+/**
+ * @defgroup coroutines Coroutines
+ *
+ * Components for supporting coroutine implementations.
+ */
+
+#if __cplusplus > 201703L && __cpp_impl_three_way_comparison >= 201907L
+#  include <compare>
+#  define _COROUTINES_USE_SPACESHIP 1
+#else
+#  include <bits/stl_function.h>
+#  define _COROUTINES_USE_SPACESHIP 0
+#endif
+
+namespace std _GLIBCXX_VISIBILITY (default)
+{
+  _GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+#if __cpp_coroutines
+  inline namespace __n4835 {
+
+  // 17.12.2 coroutine traits
+  /// [coroutine.traits]
+  /// [coroutine.traits.primary]
+  template <typename _R, typename...> struct coroutine_traits
+  {
+    using promise_type = typename _R::promise_type;
+  };
+
+  // 17.12.3 Class template coroutine_handle
+  /// [coroutine.handle]
+  template <typename _Promise = void> struct coroutine_handle;
+
+  template <> struct coroutine_handle<void>
+  {
+  public:
+    // 17.12.3.1, construct/reset
+    constexpr coroutine_handle () noexcept : _M_fr_ptr (0) {}
+    constexpr coroutine_handle (decltype (nullptr) __h) noexcept
+      : _M_fr_ptr (__h)
+    {}
+    coroutine_handle &operator= (decltype (nullptr)) noexcept
+    {
+      _M_fr_ptr = nullptr;
+      return *this;
+    }
+
+  public:
+    // 17.12.3.2, export/import
+    constexpr void *address () const noexcept { return _M_fr_ptr; }
+    constexpr static coroutine_handle from_address (void *__a) noexcept
+    {
+      coroutine_handle __self;
+      __self._M_fr_ptr = __a;
+      return __self;
+    }
+
+  public:
+    // 17.12.3.3, observers
+    constexpr explicit operator bool () const noexcept
+    {
+      return bool(_M_fr_ptr);
+    }
+    bool done () const noexcept { return __builtin_coro_done (_M_fr_ptr); }
+    // 17.12.3.4, resumption
+    void operator() () const { resume (); }
+    void resume () const { __builtin_coro_resume (_M_fr_ptr); }
+    void destroy () const { __builtin_coro_destroy (_M_fr_ptr); }
+
+  protected:
+    void *_M_fr_ptr;
+  };
+
+  // 17.12.3.6 Comparison operators
+  /// [coroutine.handle.compare]
+  constexpr bool operator== (coroutine_handle<> __a,
+                            coroutine_handle<> __b) noexcept
+  {
+    return __a.address () == __b.address ();
+  }
+
+#if _COROUTINES_USE_SPACESHIP
+  constexpr strong_ordering
+  operator<=> (coroutine_handle<> __a, coroutine_handle<> __b) noexcept;
+#else
+  // These are from the TS to enable operation with std=c++14,17.
+  constexpr bool operator!= (coroutine_handle<> __a,
+                            coroutine_handle<> __b) noexcept
+  {
+    return !(__a == __b);
+  }
+
+  constexpr bool operator< (coroutine_handle<> __a,
+                           coroutine_handle<> __b) noexcept
+  {
+    return less<void *> () (__a.address (), __b.address ());
+  }
+
+  constexpr bool operator> (coroutine_handle<> __a,
+                           coroutine_handle<> __b) noexcept
+  {
+    return __b < __a;
+  }
+
+  constexpr bool operator<= (coroutine_handle<> __a,
+                            coroutine_handle<> __b) noexcept
+  {
+    return !(__a > __b);
+  }
+
+  constexpr bool operator>= (coroutine_handle<> __a,
+                            coroutine_handle<> __b) noexcept
+  {
+    return !(__a < __b);
+  }
+#endif
+
+  template <class _Promise> struct coroutine_handle : coroutine_handle<>
+  {
+    // 17.12.3.1, construct/reset
+    using coroutine_handle<>::coroutine_handle;
+    static coroutine_handle from_promise (_Promise &p)
+    {
+      coroutine_handle __self;
+      __self._M_fr_ptr
+       = __builtin_coro_promise ((char *) &p, __alignof(_Promise), true);
+      return __self;
+    }
+    coroutine_handle &operator= (decltype (nullptr)) noexcept
+    {
+      coroutine_handle<>::operator= (nullptr);
+      return *this;
+    }
+    // 17.12.3.2, export/import
+    constexpr static coroutine_handle from_address (void *__a)
+    {
+      coroutine_handle __self;
+      __self._M_fr_ptr = __a;
+      return __self;
+    }
+    // 17.12.3.5, promise accesss
+    _Promise &promise () const
+    {
+      void *__t
+       = __builtin_coro_promise (this->_M_fr_ptr, __alignof(_Promise), false);
+      return *static_cast<_Promise *> (__t);
+    }
+  };
+
+  /// [coroutine.noop]
+  struct noop_coroutine_promise
+  {
+  };
+
+  void __dummy_resume_destroy () __attribute__ ((__weak__));
+  void __dummy_resume_destroy () {}
+
+  struct __noop_coro_frame
+  {
+    void (*__r) () = __dummy_resume_destroy;
+    void (*__d) () = __dummy_resume_destroy;
+    struct noop_coroutine_promise __p;
+  } __noop_coro_fr __attribute__ ((__weak__));
+
+  // 17.12.4.1 Class noop_coroutine_promise
+  /// [coroutine.promise.noop]
+  template <>
+  class coroutine_handle<noop_coroutine_promise> : public coroutine_handle<>
+  {
+    using _Promise = noop_coroutine_promise;
+
+  public:
+    // 17.12.4.2.1, observers
+    constexpr explicit operator bool () const noexcept { return true; }
+    constexpr bool done () const noexcept { return false; }
+
+    // 17.12.4.2.2, resumption
+    void operator() () const noexcept {}
+    void resume () const noexcept {}
+    void destroy () const noexcept {}
+
+    // 17.12.4.2.3, promise access
+    _Promise &promise () const
+    {
+      return *static_cast<_Promise *> (
+       __builtin_coro_promise (this->_M_fr_ptr, __alignof(_Promise), false));
+    }
+
+    // 17.12.4.2.4, address
+    // constexpr void* address() const noexcept;
+  private:
+    friend coroutine_handle<noop_coroutine_promise> noop_coroutine () noexcept;
+
+    coroutine_handle () noexcept { this->_M_fr_ptr = (void *) &__noop_coro_fr; 
}
+  };
+
+  using noop_coroutine_handle = coroutine_handle<noop_coroutine_promise>;
+
+  inline noop_coroutine_handle noop_coroutine () noexcept
+  {
+    return noop_coroutine_handle ();
+  }
+
+  // 17.12.5 Trivial awaitables
+  /// [coroutine.trivial.awaitables]
+  struct suspend_always
+  {
+    bool await_ready () { return false; }
+    void await_suspend (coroutine_handle<>) {}
+    void await_resume () {}
+  };
+
+  struct suspend_never
+  {
+    bool await_ready () { return true; }
+    void await_suspend (coroutine_handle<>) {}
+    void await_resume () {}
+  };
+
+  } // namespace __n4835
+
+#else
+#error "the coroutine header requires -fcoroutines"
+#endif
+
+  _GLIBCXX_END_NAMESPACE_VERSION
+} // namespace std_GLIBCXX_VISIBILITY(default)
+
+#endif // C++14 (we are allowing use from at least this)
+
+#endif // _GLIBCXX_EXPERIMENTAL_COROUTINE
-- 
2.14.3


Reply via email to