From: Jonathan Wakely Date: Wed, 20 Jun 2018 19:34:53 +0000 (+0100) Subject: PR libstdc++/70966 make pmr::new_delete_resource() immortal X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=e70359b3de997b4c582345ab7da8cccb253cc6d9;p=gcc.git PR libstdc++/70966 make pmr::new_delete_resource() immortal Construct the program-wide resource objects using placement new. This means they have dynamic storage duration and won't be destroyed during termination. PR libstdc++/70966 * include/experimental/memory_resource (__resource_adaptor_imp): Add static assertions to enforce requirements on pointer types. (__resource_adaptor_imp::get_allocator()): Add noexcept. (new_delete_resource, null_memory_resource): Return address of an object with dynamic storage duration. (__null_memory_resource): Remove. * testsuite/experimental/memory_resource/70966.cc: New. From-SVN: r261818 --- diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index bed558032c9..83bf2b92e0b 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,5 +1,14 @@ 2018-06-20 Jonathan Wakely + PR libstdc++/70966 + * include/experimental/memory_resource (__resource_adaptor_imp): Add + static assertions to enforce requirements on pointer types. + (__resource_adaptor_imp::get_allocator()): Add noexcept. + (new_delete_resource, null_memory_resource): Return address of an + object with dynamic storage duration. + (__null_memory_resource): Remove. + * testsuite/experimental/memory_resource/70966.cc: New. + * testsuite/20_util/duration/arithmetic/dr3050.cc: Add new test missed from recent commit. diff --git a/libstdc++-v3/include/experimental/memory_resource b/libstdc++-v3/include/experimental/memory_resource index b8480c2a17b..670a2210804 100644 --- a/libstdc++-v3/include/experimental/memory_resource +++ b/libstdc++-v3/include/experimental/memory_resource @@ -33,7 +33,6 @@ #include #include #include -#include #include namespace std { @@ -258,6 +257,22 @@ namespace pmr { template class __resource_adaptor_imp : public memory_resource { + static_assert(is_same::value_type>::value, + "Allocator's value_type is char"); + static_assert(is_same::pointer>::value, + "Allocator's pointer type is value_type*"); + static_assert(is_same::const_pointer>::value, + "Allocator's const_pointer type is value_type const*"); + static_assert(is_same::void_pointer>::value, + "Allocator's void_pointer type is void*"); + static_assert(is_same::const_void_pointer>::value, + "Allocator's const_void_pointer type is void const*"); + public: using allocator_type = _Alloc; @@ -276,7 +291,7 @@ namespace pmr { __resource_adaptor_imp& operator=(const __resource_adaptor_imp&) = default; - allocator_type get_allocator() const { return _M_alloc; } + allocator_type get_allocator() const noexcept { return _M_alloc; } protected: virtual void* @@ -311,13 +326,13 @@ namespace pmr { private: // Calculate Aligned Size // 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. + // by __alignment, where __alignment is required to be a 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 + // 1. Equal to Zero // 2. Is power of two static bool _S_supported (size_t __x) @@ -337,34 +352,33 @@ namespace pmr { inline memory_resource* new_delete_resource() noexcept { - static resource_adaptor> __r; - return static_cast(&__r); + using type = resource_adaptor>; + alignas(type) static unsigned char __buf[sizeof(type)]; + static type* __r = new(__buf) type; + return __r; } - template - class __null_memory_resource : private memory_resource + inline memory_resource* + null_memory_resource() noexcept + { + class type final : public memory_resource { - protected: void* - do_allocate(size_t, size_t) + do_allocate(size_t, size_t) override { std::__throw_bad_alloc(); } void - do_deallocate(void*, size_t, size_t) noexcept + do_deallocate(void*, size_t, size_t) noexcept override { } bool - do_is_equal(const memory_resource& __other) const noexcept + do_is_equal(const memory_resource& __other) const noexcept override { return this == &__other; } - - friend memory_resource* null_memory_resource() noexcept; }; - inline memory_resource* - null_memory_resource() noexcept - { - static __null_memory_resource __r; - return static_cast(&__r); + alignas(type) static unsigned char __buf[sizeof(type)]; + static type* __r = new(__buf) type; + return __r; } // The default memory resource diff --git a/libstdc++-v3/testsuite/experimental/memory_resource/70966.cc b/libstdc++-v3/testsuite/experimental/memory_resource/70966.cc new file mode 100644 index 00000000000..c0173ffa7a9 --- /dev/null +++ b/libstdc++-v3/testsuite/experimental/memory_resource/70966.cc @@ -0,0 +1,56 @@ +// Copyright (C) 2018 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 +// . + +// { dg-do run { target c++14 } } + +#include + +namespace pmr = std::experimental::pmr; + +struct X +{ + pmr::memory_resource* res = nullptr; + void* ptr = nullptr; + static constexpr std::size_t n = 64; + + constexpr X() { } + + explicit + X(pmr::memory_resource* r) : res(r), ptr(r->allocate(n)) { } + + ~X() { if (ptr) res->deallocate(ptr, n); } +}; + +void +swap(X& lhs, X& rhs) { + std::swap(lhs.res, rhs.res); + std::swap(lhs.ptr, rhs.ptr); +} + +void +test01() +{ + static X x1; + X x2(pmr::new_delete_resource()); + swap(x1, x2); + // Now x1 will deallocate the memory during destruction of static objects. +} + +int main() +{ + test01(); +}