From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 55856 invoked by alias); 11 Nov 2015 20:01:45 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 55837 invoked by uid 89); 11 Nov 2015 20:01:44 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.0 required=5.0 tests=AWL,BAYES_40,RP_MATCHES_RCVD,SPF_HELO_PASS autolearn=ham version=3.3.2 X-Spam-User: qpsmtpd, 2 recipients X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Wed, 11 Nov 2015 20:01:39 +0000 Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) by mx1.redhat.com (Postfix) with ESMTPS id C8FF0C02C6A7; Wed, 11 Nov 2015 20:01:37 +0000 (UTC) Received: from localhost (ovpn-116-102.ams2.redhat.com [10.36.116.102]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id tABK1aZC016981; Wed, 11 Nov 2015 15:01:36 -0500 Date: Wed, 11 Nov 2015 20:01:00 -0000 From: Jonathan Wakely To: Fan You Cc: libstdc++@gcc.gnu.org, gcc-patches@gcc.gnu.org, Tim Shen Subject: [v3 patch] GSoC: implement polymorphic memory resources Message-ID: <20151111200135.GQ2937@redhat.com> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="9Iq5ULCa7nGtWwZS" Content-Disposition: inline X-Clacks-Overhead: GNU Terry Pratchett User-Agent: Mutt/1.5.24 (2015-08-30) X-SW-Source: 2015-11/txt/msg01419.txt.bz2 --9Iq5ULCa7nGtWwZS Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-length: 643 The first patch is the work of Fan You, who implemented the "polymorphic memory resources" feature from the C++ Library Fundamentals TS as a Google Summer of Code project. Thanks very much to Fan You for contributing this work, and to Tim Shen for mentoring the work, and Google for sponsoring it. The second patch adds a few little pieces missing from Fan You's patch. Tested powerpc64le-linux. Apart from one minor change to the definition of the std::uses_allocator trait (which will have no effect on any existing code) this only makes changes inside namespace std::experimental. I intend to commit these patches before stage 1 ends. --9Iq5ULCa7nGtWwZS Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="patch1.txt" Content-length: 29099 commit 8ed54c84edbdebe30cb16ab97b54a4d157be67c2 Author: Jonathan Wakely Date: Wed Nov 11 18:58:51 2015 +0000 Implement C++ LFTSv1 polymorphic memory resources 2015-11-11 Fan You * include/Makefile.am: Add new headers. * include/Makefile.in: Regenerate. * include/bits/uses_allocator.h (__erased_type): Define. (__uses_allocator_helper): Check for __erased_type. * include/experimental/memory_resource: New. * include/experimental/utlity: New. * testsuite/experimental/type_erased_allocator/1.cc: New. * testsuite/experimental/type_erased_allocator/1_neg.cc: New. * testsuite/experimental/type_erased_allocator/2.cc: New. * testsuite/experimental/type_erased_allocator/uses_allocator.cc: New. diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am index 2dc0d01..ee9b6d8 100644 --- a/libstdc++-v3/include/Makefile.am +++ b/libstdc++-v3/include/Makefile.am @@ -656,6 +656,7 @@ experimental_headers = \ ${experimental_srcdir}/list \ ${experimental_srcdir}/map \ ${experimental_srcdir}/memory \ + ${experimental_srcdir}/memory_resource \ ${experimental_srcdir}/numeric \ ${experimental_srcdir}/optional \ ${experimental_srcdir}/propagate_const \ @@ -668,6 +669,7 @@ experimental_headers = \ ${experimental_srcdir}/type_traits \ ${experimental_srcdir}/unordered_map \ ${experimental_srcdir}/unordered_set \ + ${experimental_srcdir}/utility \ ${experimental_srcdir}/vector \ ${experimental_filesystem_headers} diff --git a/libstdc++-v3/include/bits/uses_allocator.h b/libstdc++-v3/include/bits/uses_allocator.h index a0f084d..f7566a2 100644 --- a/libstdc++-v3/include/bits/uses_allocator.h +++ b/libstdc++-v3/include/bits/uses_allocator.h @@ -35,6 +35,12 @@ namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION + struct __erased_type { }; + + template + using __is_erased_or_convertible + = __or_, is_convertible<_Alloc, _Tp>>; + /// [allocator.tag] struct allocator_arg_t { explicit allocator_arg_t() = default; }; @@ -47,7 +53,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template struct __uses_allocator_helper<_Tp, _Alloc, __void_t> - : is_convertible<_Alloc, typename _Tp::allocator_type>::type + : __is_erased_or_convertible<_Alloc, typename _Tp::allocator_type>::type { }; /// [allocator.uses.trait] diff --git a/libstdc++-v3/include/experimental/memory_resource b/libstdc++-v3/include/experimental/memory_resource new file mode 100644 index 0000000..5c8cbd6 --- /dev/null +++ b/libstdc++-v3/include/experimental/memory_resource @@ -0,0 +1,383 @@ +// -*- C++ -*- + +// Copyright (C) 2015 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/memory_resource + * This is a TS C++ Library header. + */ + +#ifndef _GLIBCXX_EXPERIMENTAL_MEMORY_RESOURCE +#define _GLIBCXX_EXPERIMENTAL_MEMORY_RESOURCE 1 + +#include +#include +#include +#include +#include + +namespace std { +namespace experimental { +inline namespace fundamentals_v2 { +namespace pmr { +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + class memory_resource; + + template + class polymorphic_allocator; + + template + class __resource_adaptor_imp; + + template + using resource_adaptor = __resource_adaptor_imp< + typename allocator_traits<_Alloc>::template rebind_alloc>; + + template + struct __uses_allocator_construction_helper; + + // Global memory resources + memory_resource* new_delete_resource() noexcept; + memory_resource* null_memory_resource() noexcept; + + // The default memory resource + memory_resource* get_default_resource() noexcept; + memory_resource* set_default_resource(memory_resource* __r) noexcept; + + // Standard memory resources + + // 8.5 Class memory_resource + class memory_resource + { + static constexpr size_t _S_max_align = alignof(max_align_t); + + public: + virtual ~memory_resource() { } + + void* + allocate(size_t __bytes, size_t __alignment = _S_max_align) + { return do_allocate(__bytes, __alignment); } + + void + deallocate(void* __p, size_t __bytes, size_t __alignment = _S_max_align) + { return do_deallocate(__p, __bytes, __alignment); } + + bool + is_equal(const memory_resource& __other) const noexcept + { return do_is_equal(__other); } + + protected: + virtual void* + do_allocate(size_t __bytes, size_t __alignment) = 0; + + virtual void + do_deallocate(void* __p, size_t __bytes, size_t __alignment) = 0; + + virtual bool + do_is_equal(const memory_resource& __other) const noexcept = 0; + }; + + inline bool + operator==(const memory_resource& __a, + const memory_resource& __b) noexcept + { return &__a == &__b || __a.is_equal(__b); } + + inline bool + operator!=(const memory_resource& __a, + const memory_resource& __b) noexcept + { return !(__a == __b); } + + + // 8.6 Class template polymorphic_allocator + template + class polymorphic_allocator + { + using __uses_alloc1_ = __uses_alloc1; + using __uses_alloc2_ = __uses_alloc2; + + template + void + _M_construct(__uses_alloc0, _Tp1* __p, _Args&&... __args) + { ::new(__p) _Tp1(std::forward<_Args>(__args)...); } + + template + void + _M_construct(__uses_alloc1_, _Tp1* __p, _Args&&... __args) + { ::new(__p) _Tp1(allocator_arg, this->resource(), + std::forward<_Args>(__args)...); } + + template + void + _M_construct(__uses_alloc2_, _Tp1* __p, _Args&&... __args) + { ::new(__p) _Tp1(std::forward<_Args>(__args)..., + this->resource()); } + + public: + using value_type = _Tp; + + polymorphic_allocator() noexcept + : _M_resource(get_default_resource()) + { } + + polymorphic_allocator(memory_resource* __r) + : _M_resource(__r) + { _GLIBCXX_DEBUG_ASSERT(__r); } + + polymorphic_allocator(const polymorphic_allocator& __other) = default; + + template + polymorphic_allocator(const polymorphic_allocator<_Up>& + __other) noexcept + : _M_resource(__other.resource()) + { } + + polymorphic_allocator& + operator=(const polymorphic_allocator& __rhs) = default; + + _Tp* allocate(size_t __n) + { return static_cast<_Tp*>(_M_resource->allocate(__n * sizeof(_Tp), + alignof(_Tp))); } + + void deallocate(_Tp* __p, size_t __n) + { _M_resource->deallocate(__p, __n * sizeof(_Tp), alignof(_Tp)); } + + template //used here + void construct(_Tp1* __p, _Args&&... __args) + { + auto __use_tag = __use_alloc<_Tp1, memory_resource*, + _Args...>(this->resource()); + _M_construct(__use_tag, __p, std::forward<_Args>(__args)...); + } + + // Specializations for pair using piecewise construction + template + void construct(pair<_Tp1, _Tp2>* __p, piecewise_construct_t, + tuple<_Args1...> __x, + tuple<_Args2...> __y) + { + auto __x_use_tag = + __use_alloc<_Tp1, memory_resource*, _Args1...>(this->resource()); + auto __y_use_tag = + __use_alloc<_Tp2, memory_resource*, _Args2...>(this->resource()); + + ::new(__p) std::pair<_Tp1, _Tp2>(piecewise_construct, + _M_construct_p(__x_use_tag, __x), + _M_construct_p(__y_use_tag, __y)); + } + + template + void construct(pair<_Tp1,_Tp2>* __p) + { this->construct(__p, piecewise_construct, tuple<>(), tuple<>()); } + + template + void construct(pair<_Tp1,_Tp2>* __p, _Up&& __x, _Vp&& __y) + { this->construct(__p, piecewise_construct, + forward_as_tuple(std::forward<_Up>(__x)), + forward_as_tuple(std::forward<_Vp>(__y))); } + + template + void construct(pair<_Tp1,_Tp2>* __p, const std::pair<_Up, _Vp>& __pr) + { this->construct(__p, piecewise_construct, forward_as_tuple(__pr.first), + forward_as_tuple(__pr.second)); } + + template + void construct(pair<_Tp1,_Tp2>* __p, pair<_Up, _Vp>&& __pr) + { this->construct(__p, piecewise_construct, + forward_as_tuple(std::forward<_Up>(__pr.first)), + forward_as_tuple(std::forward<_Vp>(__pr.second))); } + + template + void destroy(_Up* __p) + { __p->~_Up(); } + + // Return a default-constructed allocator (no allocator propagation) + polymorphic_allocator select_on_container_copy_construction() const + { return polymorphic_allocator(); } + + memory_resource* resource() const + { return _M_resource; } + + private: + template + _Tuple&& + _M_construct_p(__uses_alloc0, _Tuple& __t) + { return std::move(__t); } + + template + decltype(auto) + _M_construct_p(__uses_alloc1_ __ua, tuple<_Args...>& __t) + { return tuple_cat(make_tuple(allocator_arg, *(__ua._M_a)), + std::move(__t)); } + + template + decltype(auto) + _M_construct_p(__uses_alloc2_ __ua, tuple<_Args...>& __t) + { return tuple_cat(std::move(__t), make_tuple(*(__ua._M_a))); } + + memory_resource* _M_resource; + }; + + template + bool operator==(const polymorphic_allocator<_Tp1>& __a, + const polymorphic_allocator<_Tp2>& __b) noexcept + { return *__a.resource() == *__b.resource(); } + + template + bool operator!=(const polymorphic_allocator<_Tp1>& __a, + const polymorphic_allocator<_Tp2>& __b) noexcept + { return !(__a == __b); } + + // 8.7.1 __resource_adaptor_imp + template + class __resource_adaptor_imp : public memory_resource + { + public: + using allocator_type = _Alloc; + + __resource_adaptor_imp() = default; + __resource_adaptor_imp(const __resource_adaptor_imp&) = default; + __resource_adaptor_imp(__resource_adaptor_imp&&) = default; + + explicit __resource_adaptor_imp(const _Alloc& __a2) + : _M_alloc(__a2) + { } + + explicit __resource_adaptor_imp(_Alloc&& __a2) + : _M_alloc(std::move(__a2)) + { } + + __resource_adaptor_imp& + operator=(const __resource_adaptor_imp&) = default; + + allocator_type get_allocator() const { return _M_alloc; } + + protected: + virtual void* + do_allocate(size_t __bytes, size_t __alignment) + { + using _Aligned_alloc = std::__alloc_rebind<_Alloc, char>; + size_t __new_size = _S_aligned_size(__bytes, + _S_supported(__alignment) ? + __alignment : _S_max_align); + return _Aligned_alloc().allocate(__new_size); + } + + virtual void + do_deallocate(void* __p, size_t __bytes, size_t __alignment) + { + using _Aligned_alloc = std::__alloc_rebind<_Alloc, char>; + size_t __new_size = _S_aligned_size(__bytes, + _S_supported(__alignment) ? + __alignment : _S_max_align); + _Aligned_alloc().deallocate(static_cast(__p), + __new_size); + } + + virtual bool + do_is_equal(const memory_resource& __other) const noexcept + { + auto __p = dynamic_cast(&__other); + return __p ? (_M_alloc == __p->_M_alloc) : false; + } + + private: + // Calculate Aligned Size + // Returns a size that is larger than or equal to __size and divided by + // __alignment, where __alignment is required to be the power of 2. + static size_t + _S_aligned_size(size_t __size, size_t __alignment) + { return ((__size - 1)|(__alignment - 1)) + 1; } + + // Determine whether alignment meets one of those preconditions: + // 1. Equals to Zero + // 2. Is power of two + static bool + _S_supported (size_t __x) + { return ((__x != 0) && !(__x & (__x - 1))); } + + _Alloc _M_alloc; + }; + + // Global memory resources + inline std::atomic& + __get_default_resource() + { + static atomic _S_default_resource(new_delete_resource()); + return _S_default_resource; + } + + inline memory_resource* + new_delete_resource() noexcept + { + static resource_adaptor> __r; + return static_cast(&__r); + } + + template + class __null_memory_resource : private memory_resource + { + protected: + void* + do_allocate(size_t __bytes, size_t __alignment) + { std::__throw_bad_alloc(); } + + void + do_deallocate(void* __p, size_t __bytes, size_t __alignment) + { } + + bool + do_is_equal(const memory_resource& __other) const noexcept + { } + + friend memory_resource* null_memory_resource() noexcept; + }; + + inline memory_resource* + null_memory_resource() noexcept + { + static __null_memory_resource __r; + return static_cast(&__r); + } + + // The default memory resource + inline memory_resource* + get_default_resource() noexcept + { return __get_default_resource().load(); } + + inline memory_resource* + set_default_resource(memory_resource* __r) noexcept + { + if (__r == nullptr) + __r = new_delete_resource(); + return __get_default_resource().exchange(__r); + } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace pmr +} // namespace fundamentals_v2 +} // namespace experimental +} // namespace std + +#endif diff --git a/libstdc++-v3/include/experimental/utility b/libstdc++-v3/include/experimental/utility new file mode 100644 index 0000000..b1aacee --- /dev/null +++ b/libstdc++-v3/include/experimental/utility @@ -0,0 +1,48 @@ +// -*- C++ -*- + +// Copyright (C) 2015 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/utility + * This is a TS C++ Library header. + */ + +#ifndef _GLIBCXX_EXPERIMENTAL_UTILITY +#define _GLIBCXX_EXPERIMENTAL_UTILITY 1 + +#include +#include + +namespace std { +namespace experimental { +inline namespace fundamentals_v2 { +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // 3.1.2, erased-type placeholder + using erased_type = std::__erased_type; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace fundamentals_v2 +} // namespace experimental +} // namespace std + +#endif diff --git a/libstdc++-v3/testsuite/experimental/type_erased_allocator/1.cc b/libstdc++-v3/testsuite/experimental/type_erased_allocator/1.cc new file mode 100644 index 0000000..9545edf --- /dev/null +++ b/libstdc++-v3/testsuite/experimental/type_erased_allocator/1.cc @@ -0,0 +1,147 @@ +// { dg-options "-std=gnu++14" } + +// Copyright (C) 2015 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. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +#include +#include +#include +#include +#include +#include + +using std::experimental::pmr::polymorphic_allocator; +using std::experimental::pmr::memory_resource; +using std::experimental::pmr::new_delete_resource; +using std::experimental::pmr::get_default_resource; +using std::experimental::pmr::set_default_resource; + +struct A +{ + A() { ++ctor_count; } + ~A() { ++dtor_count; } + static int ctor_count; + static int dtor_count; +}; +int A::ctor_count = 0; +int A::dtor_count = 0; + +struct CountedResource : public memory_resource +{ +public: + CountedResource() = default; + ~ CountedResource() = default; + + static size_t get_alloc_count() { return alloc_count; } + static size_t get_dalloc_count() { return dalloc_count; } + + static size_t alloc_count; + static size_t dalloc_count; +protected: + void* do_allocate(size_t bytes, size_t alignment) + { + alloc_count += bytes; + if (auto ptr = std::malloc(bytes)) { + return ptr; + } + throw std::bad_alloc(); + } + + void do_deallocate(void *p, size_t bytes, size_t alignment) + { + dalloc_count += bytes; + free(p); + } + + bool do_is_equal(const memory_resource& __other) const noexcept + { return this == &__other; } +}; + size_t CountedResource::alloc_count = 0; + size_t CountedResource::dalloc_count = 0; + +void clear() +{ + CountedResource::alloc_count = 0; + CountedResource::dalloc_count = 0; + A::ctor_count = 0; + A::dtor_count = 0; +} + +// memory resource +void test01() +{ + memory_resource* r = new_delete_resource(); + VERIFY(get_default_resource() == r); + void *p = get_default_resource()->allocate(5); + VERIFY(p); + get_default_resource()->deallocate(p, 5); + + clear(); + CountedResource* cr = new CountedResource(); + set_default_resource(cr); + VERIFY(get_default_resource() == cr); + void *pc = get_default_resource()->allocate(5); + VERIFY(pc); + get_default_resource()->deallocate(pc, 5); + VERIFY(CountedResource::get_alloc_count() == 5); + VERIFY(CountedResource::get_dalloc_count() == 5); +} + +// polymorphic_allocator +void test02() +{ + clear(); + { + CountedResource cr; + polymorphic_allocator pa(&cr); + std::vector> v(5, A(), pa); + } + VERIFY(A::ctor_count == 1); + VERIFY(A::dtor_count == 6); + VERIFY(CountedResource::get_alloc_count() == 5); + VERIFY(CountedResource::get_dalloc_count() == 5); +} + +void test03() { + clear(); + CountedResource cr; + polymorphic_allocator pa(&cr); + A* p = pa.allocate(1); + pa.construct(p); + pa.destroy(p); + pa.deallocate(p, 1); + VERIFY(A::ctor_count == 1); + VERIFY(A::dtor_count == 1); + VERIFY(CountedResource::get_alloc_count() == 1); + VERIFY(CountedResource::get_dalloc_count() == 1); +} + +void test04() { + polymorphic_allocator pa1(get_default_resource()); + polymorphic_allocator pa2(get_default_resource()); + VERIFY(pa1 == pa2); + polymorphic_allocator pa3 = pa2.select_on_container_copy_construction(); + VERIFY(pa1 == pa3); +} + +int main() { + test01(); + test02(); + test03(); + test04(); + return 0; +} diff --git a/libstdc++-v3/testsuite/experimental/type_erased_allocator/1_neg.cc b/libstdc++-v3/testsuite/experimental/type_erased_allocator/1_neg.cc new file mode 100644 index 0000000..b85e0ea --- /dev/null +++ b/libstdc++-v3/testsuite/experimental/type_erased_allocator/1_neg.cc @@ -0,0 +1,37 @@ +// { dg-do run { xfail *-*-* } } +// { dg-options "-std=gnu++14" } + +// Copyright (C) 2015 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. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +#include +#include +#include +#include + +using std::experimental::pmr::polymorphic_allocator; +using std::experimental::pmr::null_memory_resource; +using std::experimental::pmr::memory_resource; + +void test01() { + memory_resource* r = null_memory_resource(); + auto p = r->allocate(1); +} + +int main() { + test01(); +} diff --git a/libstdc++-v3/testsuite/experimental/type_erased_allocator/2.cc b/libstdc++-v3/testsuite/experimental/type_erased_allocator/2.cc new file mode 100644 index 0000000..014c357 --- /dev/null +++ b/libstdc++-v3/testsuite/experimental/type_erased_allocator/2.cc @@ -0,0 +1,202 @@ +// { dg-options "-std=gnu++14" } + +// Copyright (C) 2015 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. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +#include +#include +#include +#include +#include +#include + +using std::experimental::pmr::polymorphic_allocator; +using std::experimental::pmr::memory_resource; +using std::experimental::pmr::new_delete_resource; +using std::experimental::pmr::get_default_resource; +using std::experimental::pmr::set_default_resource; +using std::allocator_arg_t; + +enum CtorType { Default, Copy, Move, Other, Tuple, Piecewise_Default, Piecewise_Copy}; + +// type that takes a memory_resource before other ctor args +struct A +{ + using allocator_type = std::experimental::erased_type; + + CtorType type; + memory_resource* alloc = nullptr; + + A() : type(Default) { } + A(allocator_arg_t, memory_resource* a) : type(Default), alloc(a) { } + A(const A&) : type(Copy) { } + A(allocator_arg_t, memory_resource* a, const A&) : type(Copy), alloc(a) { } + A(A&&) : type (Move) { } + A(allocator_arg_t, memory_resource* a, A&&) : type (Move), alloc(a) { } + A(int) : type(Other) { } + A(allocator_arg_t, memory_resource* a, int) : type(Other), alloc(a) { } +}; + +// type that takes a memory_resource after other ctor args +struct B +{ + using allocator_type = std::experimental::erased_type; + + CtorType type; + memory_resource* alloc = nullptr; + + B() : type(Default) { } + B(memory_resource* a) : type(Default), alloc(a) { } + B(const B&) : type(Copy) { } + B(const B&, memory_resource* a) : type(Copy), alloc(a) { } + B(B&&) : type (Move) { } + B(B&&, memory_resource* a) : type(Move), alloc(a) { } + B(int) : type(Other) { } + B(int, memory_resource* a) : type(Other), alloc(a) { } +}; + +// type that takes no memory_resource +struct C +{ + CtorType type; + C() : type(Default) { } + C(const C&) : type(Copy) { } + C(C&&) : type(Move) { } + C(int) : type(Other) { } +}; + +// test construct for type that +// uses memory_resource* as allocator +template +void test_uses_alloc() { + polymorphic_allocator pa; + A* p = pa.allocate(1); + A a; + + pa.construct(p); + VERIFY(p->alloc == get_default_resource()); + VERIFY(p->type == Default); + pa.destroy(p); + + pa.construct(p, a); + VERIFY(p->type == Copy); + pa.destroy(p); + + pa.construct(p, A()); + VERIFY(p->type == Move); + pa.destroy(p); + + pa.construct(p, 1); + VERIFY(p->type == Other); + pa.destroy(p); + + pa.deallocate(p, 1); +} + +// test construct for type that not using allocator +template +void test_non_alloc() { + polymorphic_allocator pa; + C* p = pa.allocate(1); + C b; + + pa.construct(p); + VERIFY(p->type == Default); + pa.destroy(p); + + pa.construct(p, b); + VERIFY(p->type == Copy); + pa.destroy(p); + + pa.construct(p, C()); + VERIFY(p->type == Move); + pa.destroy(p); + + pa.construct(p, 1); + VERIFY(p->type == Other); + pa.destroy(p); + + pa.deallocate(p, 1); +} + +// test piecewise_construct +template +void test_pair() { + polymorphic_allocator> pa; + std::pair* p = pa.allocate(1); + std::tuple<> t; + + // construct(pair* p, piecewise_construct_t, tuple<...>, tuple<...>) + pa.construct(p, std::piecewise_construct, t, t); + VERIFY(p->first.type == Default); + VERIFY(p->second.type == Default); + pa.destroy(p); + + // construct(pair* __p) + pa.construct(p); + VERIFY(p->first.type == Default); + VERIFY(p->second.type == Default); + pa.destroy(p); + + // construct(pair* p, U&& x, V&& y) + A a; B b; + pa.construct(p, a, b); + VERIFY(p->first.type == Copy); + VERIFY(p->second.type == Copy); + pa.destroy(p); + + pa.construct(p, A(), B()); + VERIFY(p->first.type == Move); + VERIFY(p->second.type == Move); + auto pp = *p; + pa.destroy(p); + + // construct(pair* p, const pair& x) + pa.construct(p, pp); + VERIFY(p->first.type == Copy); + VERIFY(p->second.type == Copy); + pa.destroy(p); + + // construct(pair* p, pair&& x) + pa.construct(p, std::move(pp)); + VERIFY(p->first.type == Move); + VERIFY(p->second.type == Move); + pa.destroy(p); + pa.deallocate(p, 1); +} + +void test01() { + test_uses_alloc(); + test_uses_alloc(); + test_non_alloc(); +} + +void test02() { + test_pair(); + test_pair(); + test_pair(); + test_pair(); + test_pair(); + test_pair(); + test_pair(); +} + + +int main() { + test01(); + test02(); +} diff --git a/libstdc++-v3/testsuite/experimental/type_erased_allocator/uses_allocator.cc b/libstdc++-v3/testsuite/experimental/type_erased_allocator/uses_allocator.cc new file mode 100644 index 0000000..fc8acf1 --- /dev/null +++ b/libstdc++-v3/testsuite/experimental/type_erased_allocator/uses_allocator.cc @@ -0,0 +1,22 @@ +#include +#include +#include +#include + +using std::vector; +using std::allocator; +using std::uses_allocator; + +struct A { + using allocator_type = std::experimental::erased_type; +}; + +void test01() { + static_assert(uses_allocator, allocator>()); + static_assert(uses_allocator>()); +} + +int main() { + test01(); + return 0; +} --9Iq5ULCa7nGtWwZS Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="patch2.txt" Content-length: 12943 commit 1517d0b9bf4a246302a156d2f648799c62d7e784 Author: Jonathan Wakely Date: Wed Nov 11 19:28:40 2015 +0000 Define alias templates using polymorphic memory resources * include/Makefile.am: Add new header. * include/Makefile.in: Regenerate. * include/experimental/memory_resource: Add feature-test macro. * include/experimental/regex: New. * include/experimental/deque: Add alias template using PMR. * include/experimental/forward_list: Likewise. * include/experimental/list: Likewise. * include/experimental/map: Likewise. * include/experimental/set: Likewise. * include/experimental/string: Likewise. * include/experimental/unordered_map: Likewise. * include/experimental/unordered_set: Likewise. * include/experimental/vector: Likewise. diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am index ee9b6d8..67d8379 100644 --- a/libstdc++-v3/include/Makefile.am +++ b/libstdc++-v3/include/Makefile.am @@ -661,6 +661,7 @@ experimental_headers = \ ${experimental_srcdir}/optional \ ${experimental_srcdir}/propagate_const \ ${experimental_srcdir}/ratio \ + ${experimental_srcdir}/regex \ ${experimental_srcdir}/set \ ${experimental_srcdir}/string \ ${experimental_srcdir}/string_view \ diff --git a/libstdc++-v3/include/experimental/deque b/libstdc++-v3/include/experimental/deque index 8d3d895..7214993 100644 --- a/libstdc++-v3/include/experimental/deque +++ b/libstdc++-v3/include/experimental/deque @@ -37,6 +37,7 @@ #include #include +#include namespace std _GLIBCXX_VISIBILITY(default) { @@ -63,6 +64,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } _GLIBCXX_END_NAMESPACE_VERSION + +namespace pmr { +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + template + using deque = std::deque<_Tp, polymorphic_allocator<_Tp>>; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace pmr + } // namespace fundamentals_v2 } // namespace experimental } // namespace std diff --git a/libstdc++-v3/include/experimental/forward_list b/libstdc++-v3/include/experimental/forward_list index e7e6b33..bceaccc 100644 --- a/libstdc++-v3/include/experimental/forward_list +++ b/libstdc++-v3/include/experimental/forward_list @@ -36,6 +36,7 @@ #else #include +#include namespace std _GLIBCXX_VISIBILITY(default) { @@ -59,6 +60,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } _GLIBCXX_END_NAMESPACE_VERSION + +namespace pmr { +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + template + using forward_list = std::forward_list<_Tp, polymorphic_allocator<_Tp>>; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace pmr + } // namespace fundamentals_v2 } // namespace experimental } // namespace std diff --git a/libstdc++-v3/include/experimental/list b/libstdc++-v3/include/experimental/list index 41d6e1d..4209d0e 100644 --- a/libstdc++-v3/include/experimental/list +++ b/libstdc++-v3/include/experimental/list @@ -36,6 +36,7 @@ #else #include +#include namespace std _GLIBCXX_VISIBILITY(default) { @@ -59,6 +60,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } _GLIBCXX_END_NAMESPACE_VERSION + +namespace pmr { +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + template + using list = std::list<_Tp, polymorphic_allocator<_Tp>>; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace pmr + } // namespace fundamentals_v2 } // namespace experimental } // namespace std diff --git a/libstdc++-v3/include/experimental/map b/libstdc++-v3/include/experimental/map index 89bf260..757065a 100644 --- a/libstdc++-v3/include/experimental/map +++ b/libstdc++-v3/include/experimental/map @@ -37,6 +37,7 @@ #include #include +#include namespace std _GLIBCXX_VISIBILITY(default) { @@ -59,6 +60,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { __detail::__erase_nodes_if(__cont, __pred); } _GLIBCXX_END_NAMESPACE_VERSION + +namespace pmr { +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + template> + using map + = std::map<_Key, _Tp, _Compare, + polymorphic_allocator>>; + + template> + using multimap + = std::multimap<_Key, _Tp, _Compare, + polymorphic_allocator>>; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace pmr + } // namespace fundamentals_v2 } // namespace experimental } // namespace std diff --git a/libstdc++-v3/include/experimental/memory_resource b/libstdc++-v3/include/experimental/memory_resource index 5c8cbd6..983b211 100644 --- a/libstdc++-v3/include/experimental/memory_resource +++ b/libstdc++-v3/include/experimental/memory_resource @@ -41,6 +41,8 @@ inline namespace fundamentals_v2 { namespace pmr { _GLIBCXX_BEGIN_NAMESPACE_VERSION +#define __cpp_lib_experimental_memory_resources 201402L + class memory_resource; template diff --git a/libstdc++-v3/include/experimental/regex b/libstdc++-v3/include/experimental/regex new file mode 100644 index 0000000..44ebf68 --- /dev/null +++ b/libstdc++-v3/include/experimental/regex @@ -0,0 +1,72 @@ +// -*- C++ -*- + +// Copyright (C) 2015 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/regex + * This is a TS C++ Library header. + */ + +#ifndef _GLIBCXX_EXPERIMENTAL_REGEX +#define _GLIBCXX_EXPERIMENTAL_REGEX 1 + +#pragma GCC system_header + +#if __cplusplus <= 201103L +# include +#else + +#include +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +namespace experimental +{ +inline namespace fundamentals_v2 +{ +namespace pmr +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION +_GLIBCXX_BEGIN_NAMESPACE_CXX11 + + template + using match_results + = std::match_results<_BidirectionalIterator, polymorphic_allocator< + sub_match<_BidirectionalIterator>>>; + + typedef match_results cmatch; + typedef match_results wcmatch; + typedef match_results smatch; + typedef match_results wsmatch; + +_GLIBCXX_END_NAMESPACE_CXX11 +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace pmr + +} // namespace fundamentals_v2 +} // namespace experimental +} // namespace std + +#endif // C++14 + +#endif // _GLIBCXX_EXPERIMENTAL_REGEX diff --git a/libstdc++-v3/include/experimental/set b/libstdc++-v3/include/experimental/set index 709fe32..be2f213 100644 --- a/libstdc++-v3/include/experimental/set +++ b/libstdc++-v3/include/experimental/set @@ -37,6 +37,7 @@ #include #include +#include namespace std _GLIBCXX_VISIBILITY(default) { @@ -59,6 +60,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { __detail::__erase_nodes_if(__cont, __pred); } _GLIBCXX_END_NAMESPACE_VERSION + +namespace pmr { +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + template> + using set = std::set<_Key, _Compare, polymorphic_allocator<_Key>>; + + template> + using multiset = std::multiset<_Key, _Compare, + polymorphic_allocator<_Key>>; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace pmr + } // namespace fundamentals_v2 } // namespace experimental } // namespace std diff --git a/libstdc++-v3/include/experimental/string b/libstdc++-v3/include/experimental/string index 2a04ce0d..3549c09 100644 --- a/libstdc++-v3/include/experimental/string +++ b/libstdc++-v3/include/experimental/string @@ -37,6 +37,7 @@ #include #include +#include namespace std _GLIBCXX_VISIBILITY(default) { @@ -64,6 +65,27 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } _GLIBCXX_END_NAMESPACE_VERSION + +namespace pmr { +_GLIBCXX_BEGIN_NAMESPACE_VERSION +_GLIBCXX_BEGIN_NAMESPACE_CXX11 + + // basic_string using polymorphic allocator in namespace pmr + template> + using basic_string = + std::basic_string<_CharT, _Traits, polymorphic_allocator<_CharT>>; + + // basic_string typedef names using polymorphic allocator in namespace + // std::experimental::pmr + typedef basic_string string; + typedef basic_string u16string; + typedef basic_string u32string; + typedef basic_string wstring; + +_GLIBCXX_END_NAMESPACE_CXX11 +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace pmr + } // namespace fundamentals_v2 } // namespace experimental } // namespace std diff --git a/libstdc++-v3/include/experimental/unordered_map b/libstdc++-v3/include/experimental/unordered_map index c80c382..9fb14e7 100644 --- a/libstdc++-v3/include/experimental/unordered_map +++ b/libstdc++-v3/include/experimental/unordered_map @@ -37,6 +37,7 @@ #include #include +#include namespace std _GLIBCXX_VISIBILITY(default) { @@ -61,6 +62,25 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { __detail::__erase_nodes_if(__cont, __pred); } _GLIBCXX_END_NAMESPACE_VERSION + +namespace pmr { +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + template, + typename _Pred = equal_to<_Key>> + using unordered_map + = std::unordered_map<_Key, _Tp, _Hash, _Pred, + polymorphic_allocator>>; + + template, + typename _Pred = equal_to<_Key>> + using unordered_multimap + = std::unordered_multimap<_Key, _Tp, _Hash, _Pred, + polymorphic_allocator>>; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace pmr + } // namespace fundamentals_v2 } // namespace experimental } // namespace std diff --git a/libstdc++-v3/include/experimental/unordered_set b/libstdc++-v3/include/experimental/unordered_set index 8461f9c..038d234 100644 --- a/libstdc++-v3/include/experimental/unordered_set +++ b/libstdc++-v3/include/experimental/unordered_set @@ -37,6 +37,7 @@ #include #include +#include namespace std _GLIBCXX_VISIBILITY(default) { @@ -61,6 +62,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { __detail::__erase_nodes_if(__cont, __pred); } _GLIBCXX_END_NAMESPACE_VERSION + +namespace pmr { +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + template, + typename _Pred = equal_to<_Key>> + using unordered_set + = std::unordered_set<_Key, _Hash, _Pred, polymorphic_allocator<_Key>>; + + template, + typename _Pred = equal_to<_Key>> + using unordered_multiset + = std::unordered_multiset<_Key, _Hash, _Pred, + polymorphic_allocator<_Key>>; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace pmr + } // namespace fundamentals_v2 } // namespace experimental } // namespace std diff --git a/libstdc++-v3/include/experimental/vector b/libstdc++-v3/include/experimental/vector index 37645a1..cddb747 100644 --- a/libstdc++-v3/include/experimental/vector +++ b/libstdc++-v3/include/experimental/vector @@ -37,6 +37,7 @@ #include #include +#include namespace std _GLIBCXX_VISIBILITY(default) { @@ -65,6 +66,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } _GLIBCXX_END_NAMESPACE_VERSION + +namespace pmr { +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + template + using vector = std::vector<_Tp, polymorphic_allocator<_Tp>>; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace pmr + } // namespace fundamentals_v2 } // namespace experimental } // namespace std --9Iq5ULCa7nGtWwZS--