]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
PR libstdc++/70966 make pmr::new_delete_resource() immortal
authorJonathan Wakely <jwakely@redhat.com>
Fri, 12 Oct 2018 13:04:24 +0000 (14:04 +0100)
committerJonathan Wakely <redi@gcc.gnu.org>
Fri, 12 Oct 2018 13:04:24 +0000 (14:04 +0100)
Construct the program-wide resource objects using placement new. This
means they have dynamic storage duration and won't be destroyed during
termination.

Backport from mainline
2018-07-24  Jonathan Wakely  <jwakely@redhat.com>

PR libstdc++/70966
* include/experimental/memory_resource (__get_default_resource): Use
placement new to create an object with dynamic storage duration.

Backport from mainline
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.

From-SVN: r265097

libstdc++-v3/ChangeLog
libstdc++-v3/include/experimental/memory_resource
libstdc++-v3/testsuite/experimental/memory_resource/70966.cc [new file with mode: 0644]

index 325a07bb70abe05eeeaee25e8a83e2b64c205cc5..51c7c1a36d36262064534b3e0eb075fbbf8303f2 100644 (file)
@@ -1,3 +1,24 @@
+2018-10-12  Jonathan Wakely  <jwakely@redhat.com>
+
+       Backport from mainline
+       2018-07-24  Jonathan Wakely  <jwakely@redhat.com>
+
+       PR libstdc++/70966
+       * include/experimental/memory_resource (__get_default_resource): Use
+       placement new to create an object with dynamic storage duration.
+
+       Backport from mainline
+       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.
+
 2018-10-12  Jonathan Wakely  <jwakely@redhat.com>
 
        PR libstdc++/77854
index 52e0b0316538a3bdf432b361147a1cb43cc6281b..d2d51bf6fd0c1cd1aecba5a4ae263c192ed5fd37 100644 (file)
@@ -33,7 +33,6 @@
 #include <new>
 #include <atomic>
 #include <cstddef>
-#include <bits/alloc_traits.h>
 #include <experimental/bits/lfts_config.h>
 
 namespace std {
@@ -256,6 +255,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template <typename _Alloc>
     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:
       using allocator_type = _Alloc;
 
@@ -274,7 +289,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       __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*
@@ -309,13 +324,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     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)
@@ -325,47 +340,50 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     };
 
   // Global memory resources
-  inline std::atomic<memory_resource*>&
-  __get_default_resource()
-  {
-    static atomic<memory_resource*> _S_default_resource(new_delete_resource());
-    return _S_default_resource;
-  }
 
   inline memory_resource*
   new_delete_resource() noexcept
   {
-    static resource_adaptor<std::allocator<char>> __r;
-    return static_cast<memory_resource*>(&__r);
+    using type = resource_adaptor<std::allocator<char>>;
+    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
+  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<void> __r;
-    return static_cast<memory_resource*>(&__r);
+    alignas(type) static unsigned char __buf[sizeof(type)];
+    static type* __r = new(__buf) type;
+    return __r;
   }
 
   // The default memory resource
+
+  inline std::atomic<memory_resource*>&
+  __get_default_resource()
+  {
+    using type = atomic<memory_resource*>;
+    alignas(type) static unsigned char __buf[sizeof(type)];
+    static type* __r = new(__buf) type(new_delete_resource());
+    return *__r;
+  }
+
   inline memory_resource*
   get_default_resource() noexcept
   { return __get_default_resource().load(); }
diff --git a/libstdc++-v3/testsuite/experimental/memory_resource/70966.cc b/libstdc++-v3/testsuite/experimental/memory_resource/70966.cc
new file mode 100644 (file)
index 0000000..c0173ff
--- /dev/null
@@ -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();
+}