From d9cb3e7598f8a9450fcd9a05500e5480631a3bfc Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Wed, 4 May 2016 13:08:45 +0100 Subject: [PATCH] libstdc++/70940 Start fixing polymorphic memory resources PR libstdc++/70940 * include/experimental/memory_resource (__resource_adaptor_imp::do_allocate): Do not default-construct rebound allocator. (__resource_adaptor_imp::do_deallocate): Likewise. Use allocator_traits to get pointer type. (__null_memory_resource::do_allocate): Remove unused parameters. (__null_memory_resource::do_deallocate): Likewise. (__null_memory_resource::do_is_equal): Likewise. Add return statement. * testsuite/experimental/type_erased_allocator/1.cc: Combine with ... * testsuite/experimental/type_erased_allocator/1_neg.cc: This, and move to ... * testsuite/experimental/memory_resource/1.cc: Here. * testsuite/experimental/memory_resource/null_memory_resource.cc: New. * testsuite/experimental/memory_resource/resource_adaptor.cc: New. From-SVN: r235868 --- libstdc++-v3/ChangeLog | 18 ++++ .../include/experimental/memory_resource | 18 ++-- .../1.cc | 41 ++++++--- .../null_memory_resource.cc} | 34 ++++++-- .../memory_resource/resource_adaptor.cc | 87 +++++++++++++++++++ 5 files changed, 167 insertions(+), 31 deletions(-) rename libstdc++-v3/testsuite/experimental/{type_erased_allocator => memory_resource}/1.cc (88%) rename libstdc++-v3/testsuite/experimental/{type_erased_allocator/1_neg.cc => memory_resource/null_memory_resource.cc} (67%) create mode 100644 libstdc++-v3/testsuite/experimental/memory_resource/resource_adaptor.cc diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 39d599291cd..89e4d1b2272 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,21 @@ +2016-05-04 Jonathan Wakely + + PR libstdc++/70940 + * include/experimental/memory_resource + (__resource_adaptor_imp::do_allocate): Do not default-construct + rebound allocator. + (__resource_adaptor_imp::do_deallocate): Likewise. Use + allocator_traits to get pointer type. + (__null_memory_resource::do_allocate): Remove unused parameters. + (__null_memory_resource::do_deallocate): Likewise. + (__null_memory_resource::do_is_equal): Likewise. Add return statement. + * testsuite/experimental/type_erased_allocator/1.cc: Combine with ... + * testsuite/experimental/type_erased_allocator/1_neg.cc: This, and + move to ... + * testsuite/experimental/memory_resource/1.cc: Here. + * testsuite/experimental/memory_resource/null_memory_resource.cc: New. + * testsuite/experimental/memory_resource/resource_adaptor.cc: New. + 2016-04-29 Chris Gregory * config/*: Remove trailing whitespace. diff --git a/libstdc++-v3/include/experimental/memory_resource b/libstdc++-v3/include/experimental/memory_resource index ccdf5e66b01..ea8afb89e02 100644 --- a/libstdc++-v3/include/experimental/memory_resource +++ b/libstdc++-v3/include/experimental/memory_resource @@ -282,7 +282,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION size_t __new_size = _S_aligned_size(__bytes, _S_supported(__alignment) ? __alignment : _S_max_align); - return _Aligned_alloc().allocate(__new_size); + return _Aligned_alloc(_M_alloc).allocate(__new_size); } virtual void @@ -292,9 +292,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION size_t __new_size = _S_aligned_size(__bytes, _S_supported(__alignment) ? __alignment : _S_max_align); - _Aligned_alloc().deallocate(static_cast(__p), - __new_size); + using _Ptr = typename allocator_traits<_Aligned_alloc>::pointer; + _Aligned_alloc(_M_alloc).deallocate(static_cast<_Ptr>(__p), + __new_size); } virtual bool @@ -306,8 +306,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION 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. + // Returns a size that is larger than or equal to __size and divisible + // 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; } @@ -342,16 +342,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { protected: void* - do_allocate(size_t __bytes, size_t __alignment) + do_allocate(size_t, size_t) { std::__throw_bad_alloc(); } void - do_deallocate(void* __p, size_t __bytes, size_t __alignment) + do_deallocate(void*, size_t, size_t) noexcept { } bool do_is_equal(const memory_resource& __other) const noexcept - { } + { return this == &__other; } friend memory_resource* null_memory_resource() noexcept; }; diff --git a/libstdc++-v3/testsuite/experimental/type_erased_allocator/1.cc b/libstdc++-v3/testsuite/experimental/memory_resource/1.cc similarity index 88% rename from libstdc++-v3/testsuite/experimental/type_erased_allocator/1.cc rename to libstdc++-v3/testsuite/experimental/memory_resource/1.cc index 924d728aa4e..38cbd2762f2 100644 --- a/libstdc++-v3/testsuite/experimental/type_erased_allocator/1.cc +++ b/libstdc++-v3/testsuite/experimental/memory_resource/1.cc @@ -17,9 +17,9 @@ // with this library; see the file COPYING3. If not see // . -#include #include #include +#include #include #include @@ -36,6 +36,7 @@ struct A static int ctor_count; static int dtor_count; }; + int A::ctor_count = 0; int A::dtor_count = 0; @@ -43,7 +44,7 @@ struct CountedResource : public memory_resource { public: CountedResource() = default; - ~ CountedResource() = default; + ~CountedResource() = default; static size_t get_alloc_count() { return alloc_count; } static size_t get_dalloc_count() { return dalloc_count; } @@ -54,23 +55,23 @@ protected: void* do_allocate(size_t bytes, size_t alignment) { alloc_count += bytes; - if (auto ptr = std::malloc(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); + std::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; + +size_t CountedResource::alloc_count = 0; +size_t CountedResource::dalloc_count = 0; void clear() { @@ -81,8 +82,11 @@ void clear() } // memory resource -void test01() +void +test01() { + bool test __attribute((unused)) = false; + memory_resource* r = new_delete_resource(); VERIFY(get_default_resource() == r); void *p = get_default_resource()->allocate(5); @@ -101,8 +105,11 @@ void test01() } // polymorphic_allocator -void test02() +void +test02() { + bool test __attribute((unused)) = false; + clear(); { CountedResource cr; @@ -115,7 +122,11 @@ void test02() VERIFY(CountedResource::get_dalloc_count() == 5); } -void test03() { +void +test03() +{ + bool test __attribute((unused)) = false; + clear(); CountedResource cr; polymorphic_allocator pa(&cr); @@ -129,7 +140,11 @@ void test03() { VERIFY(CountedResource::get_dalloc_count() == 1); } -void test04() { +void +test04() +{ + bool test __attribute((unused)) = false; + polymorphic_allocator pa1(get_default_resource()); polymorphic_allocator pa2(get_default_resource()); VERIFY(pa1 == pa2); @@ -137,10 +152,10 @@ void test04() { VERIFY(pa1 == pa3); } -int main() { +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/memory_resource/null_memory_resource.cc similarity index 67% rename from libstdc++-v3/testsuite/experimental/type_erased_allocator/1_neg.cc rename to libstdc++-v3/testsuite/experimental/memory_resource/null_memory_resource.cc index ce45dbf7c2f..c84436a2eba 100644 --- a/libstdc++-v3/testsuite/experimental/type_erased_allocator/1_neg.cc +++ b/libstdc++-v3/testsuite/experimental/memory_resource/null_memory_resource.cc @@ -1,7 +1,6 @@ -// { dg-do run { xfail *-*-* } } // { dg-options "-std=gnu++14" } -// Copyright (C) 2015-2016 Free Software Foundation, Inc. +// Copyright (C) 2016 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 @@ -20,17 +19,34 @@ #include #include -#include -using std::experimental::pmr::polymorphic_allocator; -using std::experimental::pmr::null_memory_resource; using std::experimental::pmr::memory_resource; +using std::experimental::pmr::null_memory_resource; +using std::experimental::pmr::new_delete_resource; + +// null_memory_resource +void +test06() +{ + bool test __attribute((unused)) = false; -void test01() { memory_resource* r = null_memory_resource(); - auto p = r->allocate(1); + bool caught = false; + + void* p = nullptr; + try { + p = r->allocate(1); + } catch (const std::bad_alloc&) { + caught = true; + } + VERIFY( caught ); + + VERIFY( *r == *r ); + VERIFY( r->is_equal(*r) ); + VERIFY( !r->is_equal(*new_delete_resource()) ); } -int main() { - test01(); +int main() +{ + test06(); } diff --git a/libstdc++-v3/testsuite/experimental/memory_resource/resource_adaptor.cc b/libstdc++-v3/testsuite/experimental/memory_resource/resource_adaptor.cc new file mode 100644 index 00000000000..299bb72ea4b --- /dev/null +++ b/libstdc++-v3/testsuite/experimental/memory_resource/resource_adaptor.cc @@ -0,0 +1,87 @@ +// { dg-options "-std=gnu++14" } + +// Copyright (C) 2016 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 + +using std::experimental::pmr::memory_resource; +using std::experimental::pmr::resource_adaptor; + +template + struct Allocator : __gnu_test::SimpleAllocator + { + Allocator(int) { } // not default constructible + + template + Allocator(const Allocator&) { } + }; + +template + bool aligned(void* p) + { + return (reinterpret_cast(p) % alignof(T)) == 0; + } + +// resource_adaptor +void +test05() +{ + bool test __attribute((unused)) = false; + using std::max_align_t; + using std::uintptr_t; + void* p = nullptr; + + Allocator a1(1), a2(2); // minimal interface allocators + resource_adaptor r1(a1), r2(a2); + VERIFY( r1 == r1 ); + VERIFY( r1 == r2 ); + p = r1.allocate(1); + VERIFY( aligned(p) ); + r1.deallocate(p, 1); + p = r1.allocate(1, alignof(short)); + VERIFY( aligned(p) ); + r1.deallocate(p, 1, alignof(short)); + p = r1.allocate(1, alignof(long)); + VERIFY( aligned(p) ); + r1.deallocate(p, 1, alignof(long)); + + __gnu_test::uneq_allocator a3(3), a4(4); // non-equal allocators + resource_adaptor r3(a3), r4(a4); + VERIFY( r3 == r3 ); + VERIFY( r4 == r4 ); + VERIFY( r3 != r4 ); + p = r3.allocate(1); + VERIFY( aligned(p) ); + r3.deallocate(p, 1); + p = r3.allocate(1, alignof(short)); + VERIFY( aligned(p) ); + r3.deallocate(p, 1, alignof(short)); + p = r3.allocate(1, alignof(long)); + VERIFY( aligned(p) ); + r3.deallocate(p, 1, alignof(long)); + + // TODO test with an allocator that doesn't use new or malloc, so + // returns pointers that are not suitably aligned for any type. +} + +int main() +{ + test05(); +} -- 2.30.2