From patchwork Sun Nov 17 10:27:11 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Iain Sandoe X-Patchwork-Id: 1196347 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-513823-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=sandoe.co.uk Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="ZKrIpfQG"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 47G7ZY170Bz9sP6 for ; Sun, 17 Nov 2019 21:27:48 +1100 (AEDT) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :content-type:content-transfer-encoding:mime-version:subject :date:references:to:in-reply-to:message-id; q=dns; s=default; b= mnOKj3rZIJDUKTLKZbAz6mwvS9WxaztUiZJSqsUnL7bCau02yUVKwR0hozVMfnUN MoVj5lHX3u0xaCdFHpZcVSPHXZQyOvVjoVK3eaQApLqMM7OWuQkZqKs+CxkzTXxd xQPp7KLYbL/MmkpE3ga//ccwTpDubbs59lHMpIzax6U= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :content-type:content-transfer-encoding:mime-version:subject :date:references:to:in-reply-to:message-id; s=default; bh=JH0U/0 M1dg9AdELBZuhoCMdt3/E=; b=ZKrIpfQGZ/HYnbF51CVd4DVUmcWv6CSSmzL9Cl pZMG6xau4Z0ASmW0MK5nQDeiUmPAOrSSDm+R0a0FKLXJdWkQkx4U4M6WY65mcbkS fc5d7PLOWEFu+JnSAhOKBIplGw8uj2J6Xwf8qjjrbm5iWkcJ/G8QWQbRWoVDsfVn sEiOA= Received: (qmail 32148 invoked by alias); 17 Nov 2019 10:27:31 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 32135 invoked by uid 89); 17 Nov 2019 10:27:31 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-22.6 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_COUK, KAM_SHORT, RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 spammy=granted, executor, correspondence X-HELO: smtp1.wavenetuk.net Received: from smtp.wavenetuk.net (HELO smtp1.wavenetuk.net) (195.26.36.10) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Sun, 17 Nov 2019 10:27:15 +0000 Received: from [192.168.1.212] (host81-138-1-83.in-addr.btopenworld.com [81.138.1.83]) by smtp1.wavenetuk.net (Postfix) with ESMTPA id F2DEB120062C; Sun, 17 Nov 2019 10:27:11 +0000 (GMT) From: Iain Sandoe Mime-Version: 1.0 (Mac OS X Mail 10.3 \(3273\)) Subject: [C++ coroutines 5/6] Standard library header. Date: Sun, 17 Nov 2019 10:27:11 +0000 References: <285E6AA6-17E6-4E7F-9F37-852707896DA1@sandoe.co.uk> To: GCC Patches , libstdc++ In-Reply-To: Message-Id: <3D9E9C45-F7A2-42E4-B0B0-51B03A1041F0@sandoe.co.uk> 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. libstdc++-v3/ChangeLog: 2019-11-17 Iain Sandoe * include/Makefile.am: Add coroutine to the experimental set. * include/Makefile.in: Regnerated. * include/experimental/coroutine: New file. --- libstdc++-v3/include/Makefile.am | 1 + libstdc++-v3/include/Makefile.in | 1 + libstdc++-v3/include/experimental/coroutine | 268 ++++++++++++++++++++++++++++ 3 files changed, 270 insertions(+) create mode 100644 libstdc++-v3/include/experimental/coroutine diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am index 49fd413..4ffe209 100644 --- a/libstdc++-v3/include/Makefile.am +++ b/libstdc++-v3/include/Makefile.am @@ -708,6 +708,7 @@ experimental_headers = \ ${experimental_srcdir}/array \ ${experimental_srcdir}/buffer \ ${experimental_srcdir}/chrono \ + ${experimental_srcdir}/coroutine \ ${experimental_srcdir}/deque \ ${experimental_srcdir}/executor \ ${experimental_srcdir}/forward_list \ diff --git a/libstdc++-v3/include/Makefile.in b/libstdc++-v3/include/Makefile.in index acc4fe5..fdb7d3d 100644 --- a/libstdc++-v3/include/Makefile.in +++ b/libstdc++-v3/include/Makefile.in @@ -1052,6 +1052,7 @@ experimental_headers = \ ${experimental_srcdir}/array \ ${experimental_srcdir}/buffer \ ${experimental_srcdir}/chrono \ + ${experimental_srcdir}/coroutine \ ${experimental_srcdir}/deque \ ${experimental_srcdir}/executor \ ${experimental_srcdir}/forward_list \ diff --git a/libstdc++-v3/include/experimental/coroutine b/libstdc++-v3/include/experimental/coroutine new file mode 100644 index 0000000..d903352 --- /dev/null +++ b/libstdc++-v3/include/experimental/coroutine @@ -0,0 +1,268 @@ +// -*- C++ -*- + +// Copyright (C) 2019 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 +// . + +/** @file experimental/coroutine + * This is an experimental C++ Library header against the C++20 CD n4835. + * @ingroup coroutine-ts + */ + +#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 + +#if __cplusplus > 201703L && __cpp_impl_three_way_comparison >= 201907L +# include +# define THE_SPACESHIP_HAS_LANDED 1 +#else +# include +# define THE_SPACESHIP_HAS_LANDED 0 +#endif + +namespace std _GLIBCXX_VISIBILITY (default) +{ + _GLIBCXX_BEGIN_NAMESPACE_VERSION + +#if __cpp_coroutines + + namespace experimental { + inline namespace coroutines_n4835 { + + // [coroutine.traits] + // [coroutine.traits.primary] + // 17.12.2 coroutine traits + template struct coroutine_traits + { + using promise_type = typename _R::promise_type; + }; + + // 17.12.3 Class template coroutine_handle + // [coroutine.handle] + template struct coroutine_handle; + + template <> struct coroutine_handle + { + public: + // 17.12.3.1, construct/reset + constexpr coroutine_handle () noexcept : __fr_ptr (0) {} + constexpr coroutine_handle (decltype (nullptr) __h) noexcept + : __fr_ptr (__h) + {} + coroutine_handle &operator= (decltype (nullptr)) noexcept + { + __fr_ptr = nullptr; + return *this; + } + + public: + // 17.12.3.2, export/import + constexpr void *address () const noexcept { return __fr_ptr; } + constexpr static coroutine_handle from_address (void *__a) noexcept + { + coroutine_handle __self; + __self.__fr_ptr = __a; + return __self; + } + + public: + // 17.12.3.3, observers + constexpr explicit operator bool () const noexcept + { + return bool(__fr_ptr); + } + bool done () const noexcept { return __builtin_coro_done (__fr_ptr); } + // 17.12.3.4, resumption + void operator() () const { resume (); } + void resume () const { __builtin_coro_resume (__fr_ptr); } + void destroy () const { __builtin_coro_destroy (__fr_ptr); } + + protected: + void *__fr_ptr; + }; + + // [coroutine.handle.compare] + // 17.12.3.6 Comparison operators + constexpr bool operator== (coroutine_handle<> __a, + coroutine_handle<> __b) noexcept + { + return __a.address () == __b.address (); + } + +#if THE_SPACESHIP_HAS_LANDED + constexpr strong_ordering + operator<=> (coroutine_handle<> __a, coroutine_handle<> __b) noexcept; +#else + // These are from the TS. + 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 () (__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 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.__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.__fr_ptr = __a; + return __self; + } + // 17.12.3.5, promise accesss + _Promise &promise () const + { + void *__t + = __builtin_coro_promise (this->__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__)); + + // [coroutine.promise.noop] + // 17.12.4.1 Class noop_coroutine_promise + template <> + class coroutine_handle : 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->__fr_ptr, __alignof(_Promise), false)); + } + + // 17.12.4.2.4, address + // constexpr void* address() const noexcept; + private: + friend coroutine_handle noop_coroutine () noexcept; + + coroutine_handle () noexcept { this->__fr_ptr = (void *) &__noop_coro_fr; } + }; + + using noop_coroutine_handle = coroutine_handle; + + inline noop_coroutine_handle noop_coroutine () noexcept + { + return noop_coroutine_handle (); + } + + // [coroutine.trivial.awaitables] + // 17.12.5 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 coroutines_n4835 + } // namespace experimental + +#else +#error "the coroutine header requires -fcoroutines" +#endif + + _GLIBCXX_END_NAMESPACE_VERSION +} // namespace std_GLIBCXX_VISIBILITY(default) + +#endif // C++14 + +#endif // _GLIBCXX_EXPERIMENTAL_COROUTINE