On 11/06/14 09:17 +0200, François Dumont wrote:
Hi

Here is the patch to reuse allocated nodes in the _Rb_tree implementation like it is done in the _Hashtable. I have associated it to bugzilla 29988 even if my patch also cover the new C++11 move assign operator and assignment from initialization list. I took a look to the code proposed in 29988 and it is more or less what I have done even if I benefit from C++11 lambdas to reuse more code.

I have changed propagating_allocator so that we can combine it with any other allocator. I combined it with the tracker_allocator so that I can control propagation of the allocator and at the same time track allocations.


Here are some comments on the testsuite changes, I'm still reviewing
the rest.



Property changes on: testsuite/23_containers/map/allocator/init-list.cc
___________________________________________________________________
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property

Several files are executable, please correct that.


Index: testsuite/util/testsuite_allocator.h
===================================================================
--- testsuite/util/testsuite_allocator.h        (revision 211388)
+++ testsuite/util/testsuite_allocator.h        (working copy)
@@ -244,26 +244,30 @@
    }
  };

-  template<typename Tp>
+  template<typename Tp, typename _Alloc = std::allocator<Tp> >
    class uneq_allocator
-    : private uneq_allocator_base
+    : private uneq_allocator_base,
+      public _Alloc
    {
    public:
-      typedef std::size_t                         size_type;
-      typedef std::ptrdiff_t                      difference_type;
-      typedef Tp*                                 pointer;
-      typedef const Tp*                           const_pointer;
-      typedef Tp&                                 reference;
-      typedef const Tp&                           const_reference;
-      typedef Tp                                  value_type;
+      typedef typename _Alloc::size_type       size_type;
+      typedef typename _Alloc::difference_type difference_type;
+      typedef typename _Alloc::pointer         pointer;
+      typedef typename _Alloc::const_pointer   const_pointer;
+      typedef typename _Alloc::reference       reference;
+      typedef typename _Alloc::const_reference const_reference;
+      typedef typename _Alloc::value_type      value_type;

For a C++11 allocator is no guarantee any of these members is present
except value_type.

Use __gnu_cxx::__alloc_traits to access those members in a way that
works for both C++03 and C++11 allocators.

Please try using uneq_allocator<int, SimpleAllocator<int>> and fix
everything that fails.

You can use the __gnu_test::SimpleAlloc to verify you do not depend on
anything that is not mandatory for allocators. It might be useful to
have a function in testsuite_allocator.h that checks the minimal
allocator requirements, and maybe call it from the constructor of the
various test allocators to ensure our test allocators are valid.


#if __cplusplus >= 201103L
-      typedef std::true_type                      propagate_on_container_swap;
+      typedef std::true_type                   propagate_on_container_swap;
#endif

      template<typename Tp1>
-        struct rebind
-       { typedef uneq_allocator<Tp1> other; };
+       struct rebind
+       {
+         typedef uneq_allocator<Tp1,
+                       typename _Alloc::template rebind<Tp1>::other> other;
+       };

      uneq_allocator() _GLIBCXX_USE_NOEXCEPT
      : personality(0) { }
@@ -272,7 +276,9 @@
      : personality(person) { }
template<typename Tp1>
-        uneq_allocator(const uneq_allocator<Tp1>& b) _GLIBCXX_USE_NOEXCEPT
+       uneq_allocator(const uneq_allocator<Tp1,
+                      typename _Alloc::template rebind<Tp1>::other>& b)
+       _GLIBCXX_USE_NOEXCEPT
        : personality(b.get_personality()) { }

      ~uneq_allocator() _GLIBCXX_USE_NOEXCEPT

This is an invalid use of rebind.

You cannot rely on the presence of a nested rebind member, you need to
use __gnu_cxx::__alloc_traits::rebind instead.


@@ -281,20 +287,9 @@
      int get_personality() const { return personality; }
pointer
-      address(reference x) const _GLIBCXX_NOEXCEPT
-      { return std::__addressof(x); }
- - const_pointer
-      address(const_reference x) const _GLIBCXX_NOEXCEPT
-      { return std::__addressof(x); }
-
-      pointer
-      allocate(size_type n, const void* = 0)
+      allocate(size_type n, const void* hint = 0)
{ - if (__builtin_expect(n > this->max_size(), false))
-         std::__throw_bad_alloc();
-       
-       pointer p = static_cast<Tp*>(::operator new(n * sizeof(Tp)));
+       pointer p = _Alloc::allocate(n, hint);
        try
          {
            get_map().insert(map_type::value_type(reinterpret_cast<void*>(p),

@@ -364,15 +339,14 @@
      swap(uneq_allocator& a, uneq_allocator& b)
{ std::swap(a.personality, b.personality); } - template<typename Tp1>
-        friend inline bool
-        operator==(const uneq_allocator& a, const uneq_allocator<Tp1>& b)
-        { return a.personality == b.personality; }
+      friend inline bool
+      operator==(const uneq_allocator& a,
+                const uneq_allocator& b)
+      { return a.personality == b.personality; }

-      template<typename Tp1>
-        friend inline bool
-        operator!=(const uneq_allocator& a, const uneq_allocator<Tp1>& b)
-        { return !(a == b); }
+      friend inline bool
+      operator!=(const uneq_allocator& a, const uneq_allocator& b)
+      { return !(a == b); }
int personality;
    };

This looks wrong, unless I'm mistaken this would no longer work:

   uneq_allocator<A> a;
   uneq_allocator<B> b;
   a == b;

That is required by the Allocator requirements.



@@ -393,7 +367,11 @@
      // default allocator_traits::rebind_alloc would select
      // uneq_allocator::rebind so we must define rebind here
      template<typename Up>
-       struct rebind { typedef propagating_allocator<Up, Propagate> other; };
+       struct rebind
+       {
+         typedef propagating_allocator<Up, Propagate,
+               typename _Alloc::template rebind<Up>::other> other;
+       };

      propagating_allocator(int i) noexcept
      : base_alloc(i)
@@ -400,8 +378,9 @@
      { }

      template<typename Up>
-       propagating_allocator(const propagating_allocator<Up, Propagate>& a)
-               noexcept
+       propagating_allocator(const propagating_allocator<Up, Propagate,
+                             typename _Alloc::template rebind<Up>::other>& a)
+       noexcept
        : base_alloc(a)
        { }

Invalid use of rebind.


Property changes on: testsuite/23_containers/set/allocator/init-list.cc
___________________________________________________________________
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property


Property changes on: testsuite/23_containers/multimap/allocator/init-list.cc
___________________________________________________________________
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property


Property changes on: testsuite/23_containers/multiset/allocator/init-list.cc
___________________________________________________________________
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property

More executable files.

Reply via email to