Commit e70359b3 by Jonathan Wakely Committed by Jonathan Wakely

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
parent c1456656
2018-06-20 Jonathan Wakely <jwakely@redhat.com> 2018-06-20 Jonathan Wakely <jwakely@redhat.com>
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 * testsuite/20_util/duration/arithmetic/dr3050.cc: Add new test
missed from recent commit. missed from recent commit.
......
...@@ -33,7 +33,6 @@ ...@@ -33,7 +33,6 @@
#include <new> #include <new>
#include <atomic> #include <atomic>
#include <cstddef> #include <cstddef>
#include <bits/alloc_traits.h>
#include <experimental/bits/lfts_config.h> #include <experimental/bits/lfts_config.h>
namespace std { namespace std {
...@@ -258,6 +257,22 @@ namespace pmr { ...@@ -258,6 +257,22 @@ namespace pmr {
template <typename _Alloc> template <typename _Alloc>
class __resource_adaptor_imp : public memory_resource class __resource_adaptor_imp : public memory_resource
{ {
static_assert(is_same<char,
typename allocator_traits<_Alloc>::value_type>::value,
"Allocator's value_type is char");
static_assert(is_same<char*,
typename allocator_traits<_Alloc>::pointer>::value,
"Allocator's pointer type is value_type*");
static_assert(is_same<const char*,
typename allocator_traits<_Alloc>::const_pointer>::value,
"Allocator's const_pointer type is value_type const*");
static_assert(is_same<void*,
typename allocator_traits<_Alloc>::void_pointer>::value,
"Allocator's void_pointer type is void*");
static_assert(is_same<const void*,
typename allocator_traits<_Alloc>::const_void_pointer>::value,
"Allocator's const_void_pointer type is void const*");
public: public:
using allocator_type = _Alloc; using allocator_type = _Alloc;
...@@ -276,7 +291,7 @@ namespace pmr { ...@@ -276,7 +291,7 @@ namespace pmr {
__resource_adaptor_imp& __resource_adaptor_imp&
operator=(const __resource_adaptor_imp&) = default; operator=(const __resource_adaptor_imp&) = default;
allocator_type get_allocator() const { return _M_alloc; } allocator_type get_allocator() const noexcept { return _M_alloc; }
protected: protected:
virtual void* virtual void*
...@@ -311,13 +326,13 @@ namespace pmr { ...@@ -311,13 +326,13 @@ namespace pmr {
private: private:
// Calculate Aligned Size // Calculate Aligned Size
// Returns a size that is larger than or equal to __size and divisible // 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 static size_t
_S_aligned_size(size_t __size, size_t __alignment) _S_aligned_size(size_t __size, size_t __alignment)
{ return ((__size - 1)|(__alignment - 1)) + 1; } { return ((__size - 1)|(__alignment - 1)) + 1; }
// Determine whether alignment meets one of those preconditions: // Determine whether alignment meets one of those preconditions:
// 1. Equals to Zero // 1. Equal to Zero
// 2. Is power of two // 2. Is power of two
static bool static bool
_S_supported (size_t __x) _S_supported (size_t __x)
...@@ -337,34 +352,33 @@ namespace pmr { ...@@ -337,34 +352,33 @@ namespace pmr {
inline memory_resource* inline memory_resource*
new_delete_resource() noexcept new_delete_resource() noexcept
{ {
static resource_adaptor<std::allocator<char>> __r; using type = resource_adaptor<std::allocator<char>>;
return static_cast<memory_resource*>(&__r); alignas(type) static unsigned char __buf[sizeof(type)];
static type* __r = new(__buf) type;
return __r;
} }
template <typename _Alloc> inline memory_resource*
class __null_memory_resource : private memory_resource null_memory_resource() noexcept
{
class type final : public memory_resource
{ {
protected:
void* void*
do_allocate(size_t, size_t) do_allocate(size_t, size_t) override
{ std::__throw_bad_alloc(); } { std::__throw_bad_alloc(); }
void void
do_deallocate(void*, size_t, size_t) noexcept do_deallocate(void*, size_t, size_t) noexcept override
{ } { }
bool bool
do_is_equal(const memory_resource& __other) const noexcept do_is_equal(const memory_resource& __other) const noexcept override
{ return this == &__other; } { return this == &__other; }
friend memory_resource* null_memory_resource() noexcept;
}; };
inline memory_resource* alignas(type) static unsigned char __buf[sizeof(type)];
null_memory_resource() noexcept static type* __r = new(__buf) type;
{ return __r;
static __null_memory_resource<void> __r;
return static_cast<memory_resource*>(&__r);
} }
// The default memory resource // The default memory resource
......
// 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
// <http://www.gnu.org/licenses/>.
// { dg-do run { target c++14 } }
#include <experimental/memory_resource>
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();
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment