From: Jonathan Wakely Date: Wed, 4 May 2016 12:08:45 +0000 (+0100) Subject: libstdc++/70940 Start fixing polymorphic memory resources X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=d9cb3e7598f8a9450fcd9a05500e5480631a3bfc;p=gcc.git 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 --- 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/memory_resource/1.cc b/libstdc++-v3/testsuite/experimental/memory_resource/1.cc new file mode 100644 index 00000000000..38cbd2762f2 --- /dev/null +++ b/libstdc++-v3/testsuite/experimental/memory_resource/1.cc @@ -0,0 +1,161 @@ +// { dg-options "-std=gnu++14" } + +// Copyright (C) 2015-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 +#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; + 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; + +void clear() +{ + CountedResource::alloc_count = 0; + CountedResource::dalloc_count = 0; + A::ctor_count = 0; + A::dtor_count = 0; +} + +// memory resource +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); + 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() +{ + bool test __attribute((unused)) = false; + + 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() +{ + bool test __attribute((unused)) = false; + + 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() +{ + bool test __attribute((unused)) = false; + + 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(); +} diff --git a/libstdc++-v3/testsuite/experimental/memory_resource/null_memory_resource.cc b/libstdc++-v3/testsuite/experimental/memory_resource/null_memory_resource.cc new file mode 100644 index 00000000000..c84436a2eba --- /dev/null +++ b/libstdc++-v3/testsuite/experimental/memory_resource/null_memory_resource.cc @@ -0,0 +1,52 @@ +// { 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 + +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; + + memory_resource* r = null_memory_resource(); + 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() +{ + 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(); +} diff --git a/libstdc++-v3/testsuite/experimental/type_erased_allocator/1.cc b/libstdc++-v3/testsuite/experimental/type_erased_allocator/1.cc deleted file mode 100644 index 924d728aa4e..00000000000 --- a/libstdc++-v3/testsuite/experimental/type_erased_allocator/1.cc +++ /dev/null @@ -1,146 +0,0 @@ -// { dg-options "-std=gnu++14" } - -// Copyright (C) 2015-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 -#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 deleted file mode 100644 index ce45dbf7c2f..00000000000 --- a/libstdc++-v3/testsuite/experimental/type_erased_allocator/1_neg.cc +++ /dev/null @@ -1,36 +0,0 @@ -// { dg-do run { xfail *-*-* } } -// { dg-options "-std=gnu++14" } - -// Copyright (C) 2015-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::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(); -}