mirror of git://gcc.gnu.org/git/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
This commit is contained in:
parent
c145665684
commit
e70359b3de
|
|
@ -1,5 +1,14 @@
|
||||||
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 @@
|
||||||
#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 {
|
||||||
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 {
|
||||||
__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 {
|
||||||
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 {
|
||||||
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>
|
|
||||||
class __null_memory_resource : private memory_resource
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
void*
|
|
||||||
do_allocate(size_t, size_t)
|
|
||||||
{ std::__throw_bad_alloc(); }
|
|
||||||
|
|
||||||
void
|
|
||||||
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;
|
|
||||||
};
|
|
||||||
|
|
||||||
inline memory_resource*
|
inline memory_resource*
|
||||||
null_memory_resource() noexcept
|
null_memory_resource() noexcept
|
||||||
{
|
{
|
||||||
static __null_memory_resource<void> __r;
|
class type final : public memory_resource
|
||||||
return static_cast<memory_resource*>(&__r);
|
{
|
||||||
|
void*
|
||||||
|
do_allocate(size_t, size_t) override
|
||||||
|
{ std::__throw_bad_alloc(); }
|
||||||
|
|
||||||
|
void
|
||||||
|
do_deallocate(void*, size_t, size_t) noexcept override
|
||||||
|
{ }
|
||||||
|
|
||||||
|
bool
|
||||||
|
do_is_equal(const memory_resource& __other) const noexcept override
|
||||||
|
{ return this == &__other; }
|
||||||
|
};
|
||||||
|
|
||||||
|
alignas(type) static unsigned char __buf[sizeof(type)];
|
||||||
|
static type* __r = new(__buf) type;
|
||||||
|
return __r;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The default memory resource
|
// The default memory resource
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
// <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();
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue