* testsuite allocators patch
@ 2014-06-20 20:37 François Dumont
2014-06-25 19:48 ` François Dumont
0 siblings, 1 reply; 17+ messages in thread
From: François Dumont @ 2014-06-20 20:37 UTC (permalink / raw)
To: libstdc++, gcc-patches
Hi
I would like to finally propose this patch before the one on
_Rb_tree, as a separate one.
I have adopted the same evolution on the tracker_allocator with
even a perfect forwarding constructor to allow its usage on top of the
uneq_allocator which take a personality parameter. Doing so I realized
that move_assign_neg.cc tests were not accurate enough as they needed a
non move propagating allocator and the uneq_allocator were not
explicitly non propagating.
2014-06-21 François Dumont <fdumont@gcc.gnu.org>
* testsuite/util/testsuite_allocator.h
(tracker_allocator_counter::allocate): Remove new invocation, only
collect information.
(tracker_allocator_counter::deallocate): Remove delete invocation, only
collect information.
(check_inconsistent_alloc_value_type): New.
(tracker_allocator): Transform as a facade for any allocator type.
(uneq_allocator): Likewise.
(propagating_allocator): Likewise.
* testsuite/23_containers/forward_list/debug/move_assign_neg.cc: Use an
explicitly non propagating allocator.
* testsuite/23_containers/map/debug/move_assign_neg.cc: Likewise.
* testsuite/23_containers/multimap/debug/move_assign_neg.cc: likewise.
* testsuite/23_containers/multiset/debug/move_assign_neg.cc: Likewise.
* testsuite/23_containers/set/debug/move_assign_neg.cc: Likewise.
* testsuite/23_containers/unordered_map/debug/move_assign_neg.cc:
Likewise.
* testsuite/23_containers/unordered_multimap/debug/move_assign_neg.cc:
Likewise.
* testsuite/23_containers/unordered_multiset/debug/move_assign_neg.cc:
Likewise.
* testsuite/23_containers/unordered_set/debug/move_assign_neg.cc:
Likewise.
* testsuite/23_containers/vector/debug/move_assign_neg.cc: Likewise.
Tested under Linux x86_64.
Ok to commit ?
François
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: testsuite allocators patch
2014-06-20 20:37 testsuite allocators patch François Dumont
@ 2014-06-25 19:48 ` François Dumont
2014-06-26 10:33 ` Jonathan Wakely
0 siblings, 1 reply; 17+ messages in thread
From: François Dumont @ 2014-06-25 19:48 UTC (permalink / raw)
To: libstdc++, gcc-patches
[-- Attachment #1: Type: text/plain, Size: 1978 bytes --]
Hi
With the patch this time.
>
> I would like to finally propose this patch before the one on
> _Rb_tree, as a separate one.
>
> I have adopted the same evolution on the tracker_allocator with
> even a perfect forwarding constructor to allow its usage on top of the
> uneq_allocator which take a personality parameter. Doing so I
> realized that move_assign_neg.cc tests were not accurate enough as
> they needed a non move propagating allocator and the uneq_allocator
> were not explicitly non propagating.
>
> 2014-06-21 François Dumont <fdumont@gcc.gnu.org>
>
> * testsuite/util/testsuite_allocator.h
> (tracker_allocator_counter::allocate): Remove new invocation, only
> collect information.
> (tracker_allocator_counter::deallocate): Remove delete invocation,
> only
> collect information.
> (check_inconsistent_alloc_value_type): New.
> (tracker_allocator): Transform as a facade for any allocator type.
> (uneq_allocator): Likewise.
> (propagating_allocator): Likewise.
> * testsuite/23_containers/forward_list/debug/move_assign_neg.cc:
> Use an
> explicitly non propagating allocator.
> * testsuite/23_containers/map/debug/move_assign_neg.cc: Likewise.
> * testsuite/23_containers/multimap/debug/move_assign_neg.cc:
> likewise.
> * testsuite/23_containers/multiset/debug/move_assign_neg.cc:
> Likewise.
> * testsuite/23_containers/set/debug/move_assign_neg.cc: Likewise.
> * testsuite/23_containers/unordered_map/debug/move_assign_neg.cc:
> Likewise.
> *
> testsuite/23_containers/unordered_multimap/debug/move_assign_neg.cc:
> Likewise.
> *
> testsuite/23_containers/unordered_multiset/debug/move_assign_neg.cc:
> Likewise.
> * testsuite/23_containers/unordered_set/debug/move_assign_neg.cc:
> Likewise.
> * testsuite/23_containers/vector/debug/move_assign_neg.cc: Likewise.
>
> Tested under Linux x86_64.
>
> Ok to commit ?
>
> François
>
[-- Attachment #2: testsuite_alloc.patch --]
[-- Type: text/x-patch, Size: 21162 bytes --]
Index: testsuite/util/testsuite_allocator.h
===================================================================
--- testsuite/util/testsuite_allocator.h (revision 211713)
+++ testsuite/util/testsuite_allocator.h (working copy)
@@ -29,6 +29,7 @@
#include <tr1/unordered_map>
#include <bits/move.h>
#include <ext/pointer.h>
+#include <ext/alloc_traits.h>
#include <testsuite_hooks.h>
namespace __gnu_test
@@ -38,26 +39,19 @@
public:
typedef std::size_t size_type;
- static void*
+ static void
allocate(size_type blocksize)
- {
- void* p = ::operator new(blocksize);
- allocationCount_ += blocksize;
- return p;
- }
+ { allocationCount_ += blocksize; }
static void
- construct() { constructCount_++; }
+ construct() { ++constructCount_; }
static void
- destroy() { destructCount_++; }
+ destroy() { ++destructCount_; }
static void
- deallocate(void* p, size_type blocksize)
- {
- ::operator delete(p);
- deallocationCount_ += blocksize;
- }
+ deallocate(size_type blocksize)
+ { deallocationCount_ += blocksize; }
static size_type
get_allocation_count() { return allocationCount_; }
@@ -87,103 +81,142 @@
static int destructCount_;
};
- // A simple basic allocator that just forwards to the
+ // Helper to detect inconsistency between type used to instantiate an
+ // allocator and the underlying allocator value_type.
+ template<typename T, typename Alloc,
+ typename = typename Alloc::value_type>
+ struct check_consistent_alloc_value_type;
+
+ template<typename T, typename Alloc>
+ struct check_consistent_alloc_value_type<T, Alloc, T>
+ { typedef T value_type; };
+
+ // An allocator facade that just intercepts some calls and forward them to the
// tracker_allocator_counter to fulfill memory requests. This class
// is templated on the target object type, but tracker isn't.
- template<class T>
- class tracker_allocator
- {
- private:
- typedef tracker_allocator_counter counter_type;
+ template<typename T, typename Alloc = std::allocator<T> >
+ class tracker_allocator : public Alloc
+ {
+ private:
+ typedef tracker_allocator_counter counter_type;
- public:
- typedef T value_type;
- typedef T* pointer;
- typedef const T* const_pointer;
- typedef T& reference;
- typedef const T& const_reference;
- typedef std::size_t size_type;
- typedef std::ptrdiff_t difference_type;
+ typedef __gnu_cxx::__alloc_traits<Alloc> AllocTraits;
+
+ public:
+ typedef typename
+ check_consistent_alloc_value_type<T, Alloc>::value_type value_type;
+ typedef typename AllocTraits::pointer pointer;
+ typedef typename AllocTraits::size_type size_type;
- template<class U> struct rebind { typedef tracker_allocator<U> other; };
+ template<class U>
+ struct rebind
+ {
+ typedef tracker_allocator<U,
+ typename AllocTraits::template rebind<U>::other> other;
+ };
- pointer
- address(reference value) const _GLIBCXX_NOEXCEPT
- { return std::__addressof(value); }
+#if __cplusplus >= 201103L
+ tracker_allocator() = default;
+ tracker_allocator(const tracker_allocator&) = default;
+ tracker_allocator(tracker_allocator&&) = default;
- const_pointer
- address(const_reference value) const _GLIBCXX_NOEXCEPT
- { return std::__addressof(value); }
+ // Perfect forwarding constructor.
+ template<typename... _Args>
+ tracker_allocator(_Args&&... __args)
+ : Alloc(std::forward<_Args>(__args)...)
+ { }
+#else
+ tracker_allocator() _GLIBCXX_USE_NOEXCEPT
+ { }
- tracker_allocator() _GLIBCXX_USE_NOEXCEPT
- { }
+ tracker_allocator(const tracker_allocator&) _GLIBCXX_USE_NOEXCEPT
+ { }
- tracker_allocator(const tracker_allocator&) _GLIBCXX_USE_NOEXCEPT
- { }
-
- template<class U>
- tracker_allocator(const tracker_allocator<U>&) _GLIBCXX_USE_NOEXCEPT
+ ~tracker_allocator() _GLIBCXX_USE_NOEXCEPT
{ }
+#endif
- ~tracker_allocator() _GLIBCXX_USE_NOEXCEPT
- { }
+ template<class U>
+ tracker_allocator(const tracker_allocator<U,
+ typename AllocTraits::template rebind<U>::other>& alloc)
+ _GLIBCXX_USE_NOEXCEPT
+ : Alloc(alloc)
+ { }
- size_type
- max_size() const _GLIBCXX_USE_NOEXCEPT
- { return size_type(-1) / sizeof(T); }
+ pointer
+ allocate(size_type n, const void* = 0)
+ {
+ pointer p = AllocTraits::allocate(*this, n);
+ counter_type::allocate(n * sizeof(T));
+ return p;
+ }
- pointer
- allocate(size_type n, const void* = 0)
- { return static_cast<pointer>(counter_type::allocate(n * sizeof(T))); }
+#if __cplusplus >= 201103L
+ template<typename U, typename... Args>
+ void
+ construct(U* p, Args&&... args)
+ {
+ AllocTraits::construct(*this, p, std::forward<Args>(args)...);
+ counter_type::construct();
+ }
-#if __cplusplus >= 201103L
- template<typename U, typename... Args>
+ template<typename U>
+ void
+ destroy(U* p)
+ {
+ AllocTraits::destroy(*this, p);
+ counter_type::destroy();
+ }
+#else
void
- construct(U* p, Args&&... args)
+ construct(pointer p, const T& value)
{
- ::new((void *)p) U(std::forward<Args>(args)...);
+ AllocTraits::construct(*this, p, value);
counter_type::construct();
}
- template<typename U>
void
- destroy(U* p)
+ destroy(pointer p)
{
- p->~U();
+ AllocTraits::destroy(*this, p);
counter_type::destroy();
}
-#else
- void
- construct(pointer p, const T& value)
- {
- ::new ((void *)p) T(value);
- counter_type::construct();
- }
-
- void
- destroy(pointer p)
- {
- p->~T();
- counter_type::destroy();
- }
#endif
- void
- deallocate(pointer p, size_type num)
- { counter_type::deallocate(p, num * sizeof(T)); }
- };
+ void
+ deallocate(pointer p, size_type num)
+ {
+ counter_type::deallocate(num * sizeof(T));
+ AllocTraits::deallocate(*this, p, num);
+ }
- template<class T1, class T2>
+ // Implement swap for underlying allocators that might need it.
+ friend inline void
+ swap(tracker_allocator& a, tracker_allocator& b)
+ {
+ using std::swap;
+
+ Alloc& aa = a;
+ Alloc& ab = b;
+ swap(aa, ab);
+ }
+ };
+
+ template<class T1, class Alloc1, class T2, class Alloc2>
bool
- operator==(const tracker_allocator<T1>&,
- const tracker_allocator<T2>&) throw()
- { return true; }
+ operator==(const tracker_allocator<T1, Alloc1>& lhs,
+ const tracker_allocator<T2, Alloc2>& rhs) throw()
+ {
+ const Alloc1& alloc1 = lhs;
+ const Alloc2& alloc2 = rhs;
+ return lhs == rhs;
+ }
- template<class T1, class T2>
+ template<class T1, class Alloc1, class T2, class Alloc2>
bool
- operator!=(const tracker_allocator<T1>&,
- const tracker_allocator<T2>&) throw()
- { return false; }
+ operator!=(const tracker_allocator<T1, Alloc1>& lhs,
+ const tracker_allocator<T2, Alloc2>& rhs) throw()
+ { return !(lhs == rhs); }
bool
check_construct_destroy(const char* tag, int expected_c, int expected_d);
@@ -219,7 +252,6 @@
throw;
}
-
// A simple allocator which can be constructed endowed of a given
// "personality" (an integer), queried in operator== to simulate the
// behavior of realworld "unequal" allocators (i.e., not exploiting
@@ -227,7 +259,7 @@
// filled at allocation time with (pointer, personality) pairs, is
// then consulted to enforce the requirements in Table 32 about
// deallocation vs allocator equality. Note that this allocator is
- // swappable, not assignable, consistently with Option 3 of DR 431
+ // swappable, not copy assignable, consistently with Option 3 of DR 431
// (see N1599).
struct uneq_allocator_base
{
@@ -244,26 +276,33 @@
}
};
- template<typename Tp>
+ template<typename Tp, typename Alloc = std::allocator<Tp> >
class uneq_allocator
- : private uneq_allocator_base
+ : private uneq_allocator_base,
+ public Alloc
{
+ typedef __gnu_cxx::__alloc_traits<Alloc> AllocTraits;
+
+ Alloc& base() { return *this; }
+ const Alloc& base() const { return *this; }
+ void swap_base(Alloc& b) { swap(b, this->base()); }
+
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 check_consistent_alloc_value_type<Tp, Alloc>::value_type
+ value_type;
+ typedef typename AllocTraits::size_type size_type;
+ typedef typename AllocTraits::pointer pointer;
#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 AllocTraits::template rebind<Tp1>::other> other;
+ };
uneq_allocator() _GLIBCXX_USE_NOEXCEPT
: personality(0) { }
@@ -272,7 +311,9 @@
: personality(person) { }
template<typename Tp1>
- uneq_allocator(const uneq_allocator<Tp1>& b) _GLIBCXX_USE_NOEXCEPT
+ uneq_allocator(const uneq_allocator<Tp1,
+ typename AllocTraits::template rebind<Tp1>::other>& b)
+ _GLIBCXX_USE_NOEXCEPT
: personality(b.get_personality()) { }
~uneq_allocator() _GLIBCXX_USE_NOEXCEPT
@@ -281,20 +322,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 = AllocTraits::allocate(*this, n);
try
{
get_map().insert(map_type::value_type(reinterpret_cast<void*>(p),
@@ -302,7 +332,7 @@
}
catch(...)
{
- ::operator delete(p);
+ AllocTraits::deallocate(*this, p, n);
__throw_exception_again;
}
return p;
@@ -309,7 +339,7 @@
}
void
- deallocate(pointer p, size_type)
+ deallocate(pointer p, size_type n)
{
bool test __attribute__((unused)) = true;
@@ -323,34 +353,18 @@
VERIFY( it->second == personality );
get_map().erase(it);
- ::operator delete(p);
+ AllocTraits::deallocate(*this, p, n);
}
- size_type
- max_size() const _GLIBCXX_USE_NOEXCEPT
- { return size_type(-1) / sizeof(Tp); }
-
#if __cplusplus >= 201103L
- template<typename U, typename... Args>
- void
- construct(U* p, Args&&... args)
- { ::new((void *)p) U(std::forward<Args>(args)...); }
-
- template<typename U>
- void
- destroy(U* p) { p->~U(); }
-
// Not copy assignable...
uneq_allocator&
operator=(const uneq_allocator&) = delete;
+
+ // ... but still moveable if base allocator is.
+ uneq_allocator&
+ operator=(uneq_allocator&&) = default;
#else
- void
- construct(pointer p, const Tp& val)
- { ::new((void *)p) Tp(val); }
-
- void
- destroy(pointer p) { p->~Tp(); }
-
private:
// Not assignable...
uneq_allocator&
@@ -358,21 +372,27 @@
#endif
private:
-
// ... yet swappable!
friend inline void
swap(uneq_allocator& a, uneq_allocator& b)
- { std::swap(a.personality, b.personality); }
-
+ {
+ std::swap(a.personality, b.personality);
+ a.swap_base(b);
+ }
+
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<Tp1,
+ typename AllocTraits::template rebind<Tp1>::other>& 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<Tp1,
+ typename AllocTraits::template rebind<Tp1>::other>& b)
+ { return !(a == b); }
int personality;
};
@@ -379,10 +399,12 @@
#if __cplusplus >= 201103L
// An uneq_allocator which can be used to test allocator propagation.
- template<typename Tp, bool Propagate>
- class propagating_allocator : public uneq_allocator<Tp>
+ template<typename Tp, bool Propagate, typename Alloc = std::allocator<Tp>>
+ class propagating_allocator : public uneq_allocator<Tp, Alloc>
{
- typedef uneq_allocator<Tp> base_alloc;
+ typedef __gnu_cxx::__alloc_traits<Alloc> AllocTraits;
+
+ typedef uneq_allocator<Tp, Alloc> base_alloc;
base_alloc& base() { return *this; }
const base_alloc& base() const { return *this; }
void swap_base(base_alloc& b) { swap(b, this->base()); }
@@ -393,7 +415,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 AllocTraits::template rebind<Up>::other> other;
+ };
propagating_allocator(int i) noexcept
: base_alloc(i)
@@ -400,8 +426,9 @@
{ }
template<typename Up>
- propagating_allocator(const propagating_allocator<Up, Propagate>& a)
- noexcept
+ propagating_allocator(const propagating_allocator<Up, Propagate,
+ typename AllocTraits::template rebind<Up>::other>& a)
+ noexcept
: base_alloc(a)
{ }
@@ -418,8 +445,8 @@
}
template<bool P2>
- propagating_allocator&
- operator=(const propagating_allocator<Tp, P2>& a) noexcept
+ propagating_allocator&
+ operator=(const propagating_allocator<Tp, P2, Alloc>& a) noexcept
{
static_assert(P2, "assigning propagating_allocator<T, true>");
propagating_allocator(a).swap_base(*this);
Index: testsuite/23_containers/forward_list/debug/move_assign_neg.cc
===================================================================
--- testsuite/23_containers/forward_list/debug/move_assign_neg.cc (revision 211713)
+++ testsuite/23_containers/forward_list/debug/move_assign_neg.cc (working copy)
@@ -25,7 +25,7 @@
{
bool test __attribute__((unused)) = true;
- typedef __gnu_test::uneq_allocator<int> alloc_type;
+ typedef __gnu_test::propagating_allocator<int, false> alloc_type;
typedef __gnu_debug::forward_list<int, alloc_type> test_type;
test_type v1(alloc_type(1));
Index: testsuite/23_containers/map/debug/move_assign_neg.cc
===================================================================
--- testsuite/23_containers/map/debug/move_assign_neg.cc (revision 211713)
+++ testsuite/23_containers/map/debug/move_assign_neg.cc (working copy)
@@ -25,7 +25,8 @@
{
bool test __attribute__((unused)) = true;
- typedef __gnu_test::uneq_allocator<std::pair<const int, int> > alloc_type;
+ typedef __gnu_test::propagating_allocator<std::pair<const int, int>,
+ false> alloc_type;
typedef __gnu_debug::map<int, int, std::less<int>, alloc_type> test_type;
test_type v1(alloc_type(1));
Index: testsuite/23_containers/multimap/debug/move_assign_neg.cc
===================================================================
--- testsuite/23_containers/multimap/debug/move_assign_neg.cc (revision 211713)
+++ testsuite/23_containers/multimap/debug/move_assign_neg.cc (working copy)
@@ -25,7 +25,8 @@
{
bool test __attribute__((unused)) = true;
- typedef __gnu_test::uneq_allocator<std::pair<const int, int> > alloc_type;
+ typedef __gnu_test::propagating_allocator<std::pair<const int, int>,
+ false> alloc_type;
typedef __gnu_debug::multimap<int, int, std::less<int>, alloc_type> test_type;
test_type v1(alloc_type(1));
Index: testsuite/23_containers/multiset/debug/move_assign_neg.cc
===================================================================
--- testsuite/23_containers/multiset/debug/move_assign_neg.cc (revision 211713)
+++ testsuite/23_containers/multiset/debug/move_assign_neg.cc (working copy)
@@ -25,7 +25,7 @@
{
bool test __attribute__((unused)) = true;
- typedef __gnu_test::uneq_allocator<int> alloc_type;
+ typedef __gnu_test::propagating_allocator<int, false> alloc_type;
typedef __gnu_debug::multiset<int, std::less<int>, alloc_type> test_type;
test_type v1(alloc_type(1));
Index: testsuite/23_containers/set/debug/move_assign_neg.cc
===================================================================
--- testsuite/23_containers/set/debug/move_assign_neg.cc (revision 211713)
+++ testsuite/23_containers/set/debug/move_assign_neg.cc (working copy)
@@ -25,7 +25,7 @@
{
bool test __attribute__((unused)) = true;
- typedef __gnu_test::uneq_allocator<int> alloc_type;
+ typedef __gnu_test::propagating_allocator<int, false> alloc_type;
typedef __gnu_debug::set<int, std::less<int>, alloc_type> test_type;
test_type v1(alloc_type(1));
Index: testsuite/23_containers/unordered_map/debug/move_assign_neg.cc
===================================================================
--- testsuite/23_containers/unordered_map/debug/move_assign_neg.cc (revision 211713)
+++ testsuite/23_containers/unordered_map/debug/move_assign_neg.cc (working copy)
@@ -25,7 +25,8 @@
{
bool test __attribute__((unused)) = true;
- typedef __gnu_test::uneq_allocator<std::pair<const int, int> > alloc_type;
+ typedef __gnu_test::propagating_allocator<std::pair<const int, int>,
+ false> alloc_type;
typedef __gnu_debug::unordered_map<int, int,
std::hash<int>, std::equal_to<int>,
alloc_type> test_type;
Index: testsuite/23_containers/unordered_multimap/debug/move_assign_neg.cc
===================================================================
--- testsuite/23_containers/unordered_multimap/debug/move_assign_neg.cc (revision 211713)
+++ testsuite/23_containers/unordered_multimap/debug/move_assign_neg.cc (working copy)
@@ -25,7 +25,8 @@
{
bool test __attribute__((unused)) = true;
- typedef __gnu_test::uneq_allocator<std::pair<const int, int>> alloc_type;
+ typedef __gnu_test::propagating_allocator<std::pair<const int, int>,
+ false> alloc_type;
typedef __gnu_debug::unordered_multimap<int, int, std::hash<int>,
std::equal_to<int>,
alloc_type> test_type;
Index: testsuite/23_containers/unordered_multiset/debug/move_assign_neg.cc
===================================================================
--- testsuite/23_containers/unordered_multiset/debug/move_assign_neg.cc (revision 211713)
+++ testsuite/23_containers/unordered_multiset/debug/move_assign_neg.cc (working copy)
@@ -25,7 +25,7 @@
{
bool test __attribute__((unused)) = true;
- typedef __gnu_test::uneq_allocator<int> alloc_type;
+ typedef __gnu_test::propagating_allocator<int, false> alloc_type;
typedef __gnu_debug::unordered_multiset<int, std::hash<int>,
std::equal_to<int>,
alloc_type> test_type;
Index: testsuite/23_containers/unordered_set/debug/move_assign_neg.cc
===================================================================
--- testsuite/23_containers/unordered_set/debug/move_assign_neg.cc (revision 211713)
+++ testsuite/23_containers/unordered_set/debug/move_assign_neg.cc (working copy)
@@ -25,7 +25,7 @@
{
bool test __attribute__((unused)) = true;
- typedef __gnu_test::uneq_allocator<int> alloc_type;
+ typedef __gnu_test::propagating_allocator<int, false> alloc_type;
typedef __gnu_debug::unordered_set<int, std::hash<int>,
std::equal_to<int>,
alloc_type> test_type;
Index: testsuite/23_containers/vector/debug/move_assign_neg.cc
===================================================================
--- testsuite/23_containers/vector/debug/move_assign_neg.cc (revision 211713)
+++ testsuite/23_containers/vector/debug/move_assign_neg.cc (working copy)
@@ -27,7 +27,7 @@
{
bool test __attribute__((unused)) = true;
- typedef __gnu_test::uneq_allocator<int> alloc_type;
+ typedef __gnu_test::propagating_allocator<int, false> alloc_type;
typedef __gnu_debug::vector<int, alloc_type> test_type;
test_type v1(alloc_type(1));
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: testsuite allocators patch
2014-06-25 19:48 ` François Dumont
@ 2014-06-26 10:33 ` Jonathan Wakely
2014-06-26 20:45 ` François Dumont
0 siblings, 1 reply; 17+ messages in thread
From: Jonathan Wakely @ 2014-06-26 10:33 UTC (permalink / raw)
To: François Dumont; +Cc: libstdc++, gcc-patches
On 25/06/14 21:47 +0200, François Dumont wrote:
>> I would like to finally propose this patch before the one on
>>_Rb_tree, as a separate one.
>>
>> I have adopted the same evolution on the tracker_allocator with
>>even a perfect forwarding constructor to allow its usage on top of
>>the uneq_allocator which take a personality parameter. Doing so I
>>realized that move_assign_neg.cc tests were not accurate enough as
>>they needed a non move propagating allocator and the uneq_allocator
>>were not explicitly non propagating.
Ah, that's good to improve them then.
>Index: testsuite/util/testsuite_allocator.h
>===================================================================
>--- testsuite/util/testsuite_allocator.h (revision 211713)
>+++ testsuite/util/testsuite_allocator.h (working copy)
>@@ -87,103 +81,142 @@
> static int destructCount_;
> };
>
>- // A simple basic allocator that just forwards to the
>+ // Helper to detect inconsistency between type used to instantiate an
>+ // allocator and the underlying allocator value_type.
>+ template<typename T, typename Alloc,
>+ typename = typename Alloc::value_type>
>+ struct check_consistent_alloc_value_type;
>+
>+ template<typename T, typename Alloc>
>+ struct check_consistent_alloc_value_type<T, Alloc, T>
>+ { typedef T value_type; };
>+
>+ // An allocator facade that just intercepts some calls and forward them to the
> // tracker_allocator_counter to fulfill memory requests. This class
This comment is no longer true, tracker_allocator_counter does not
fulfil the memory requests.
> // is templated on the target object type, but tracker isn't.
>- template<class T>
>- class tracker_allocator
>- {
>- private:
>- typedef tracker_allocator_counter counter_type;
>+ template<typename T, typename Alloc = std::allocator<T> >
>+ class tracker_allocator : public Alloc
>+ {
>+ private:
>+ typedef tracker_allocator_counter counter_type;
>
>- public:
>- typedef T value_type;
>- typedef T* pointer;
>- typedef const T* const_pointer;
>- typedef T& reference;
>- typedef const T& const_reference;
>- typedef std::size_t size_type;
>- typedef std::ptrdiff_t difference_type;
>+ typedef __gnu_cxx::__alloc_traits<Alloc> AllocTraits;
>+
>+ public:
>+ typedef typename
>+ check_consistent_alloc_value_type<T, Alloc>::value_type value_type;
>+ typedef typename AllocTraits::pointer pointer;
>+ typedef typename AllocTraits::size_type size_type;
Thanks for doing this - I think it makes the facade more useful if it
uses allocator_traits and so can be combined with SimpleAllocator and
CustomPointerAlloc.
>- template<class U> struct rebind { typedef tracker_allocator<U> other; };
>+ template<class U>
>+ struct rebind
>+ {
>+ typedef tracker_allocator<U,
>+ typename AllocTraits::template rebind<U>::other> other;
>+ };
>
>- pointer
>- address(reference value) const _GLIBCXX_NOEXCEPT
>- { return std::__addressof(value); }
>+#if __cplusplus >= 201103L
>+ tracker_allocator() = default;
>+ tracker_allocator(const tracker_allocator&) = default;
>+ tracker_allocator(tracker_allocator&&) = default;
>
>- const_pointer
>- address(const_reference value) const _GLIBCXX_NOEXCEPT
>- { return std::__addressof(value); }
>+ // Perfect forwarding constructor.
>+ template<typename... _Args>
>+ tracker_allocator(_Args&&... __args)
>+ : Alloc(std::forward<_Args>(__args)...)
>+ { }
>+#else
>+ tracker_allocator() _GLIBCXX_USE_NOEXCEPT
The _GLIBCXX_USE_NOEXCEPT macro expands to nothing in C++03 mode, so
you might as well omit it in the #else branch.
OK for trunk if you make the tracker_allocator comment correct.
Thanks!
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: testsuite allocators patch
2014-06-26 10:33 ` Jonathan Wakely
@ 2014-06-26 20:45 ` François Dumont
2014-06-26 21:24 ` Paolo Carlini
0 siblings, 1 reply; 17+ messages in thread
From: François Dumont @ 2014-06-26 20:45 UTC (permalink / raw)
To: Jonathan Wakely; +Cc: libstdc++, gcc-patches
On 26/06/2014 12:33, Jonathan Wakely wrote:
>
> The _GLIBCXX_USE_NOEXCEPT macro expands to nothing in C++03 mode, so
> you might as well omit it in the #else branch.
>
> OK for trunk if you make the tracker_allocator comment correct.
>
> Thanks!
>
>
Committed with:
// An allocator facade that intercepts
allocate/deallocate/construct/destroy
// calls and track them through the tracker_allocator_counter class. This
// class is templated on the target object type, but tracker isn't.
template<typename T, typename Alloc = std::allocator<T> >
class tracker_allocator : public Alloc
Thanks for feedback.
François
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: testsuite allocators patch
2014-06-26 20:45 ` François Dumont
@ 2014-06-26 21:24 ` Paolo Carlini
2014-06-26 22:39 ` Jonathan Wakely
0 siblings, 1 reply; 17+ messages in thread
From: Paolo Carlini @ 2014-06-26 21:24 UTC (permalink / raw)
To: François Dumont, Jonathan Wakely; +Cc: libstdc++, gcc-patches
Hi,
I'm afraid something went badly wrong with this commit, I'm seeing tens
of fails. See eg:
https://gcc.gnu.org/ml/gcc-testresults/2014-06/msg02439.html
Paolo.
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: testsuite allocators patch
2014-06-26 21:24 ` Paolo Carlini
@ 2014-06-26 22:39 ` Jonathan Wakely
2014-06-27 7:30 ` Paolo Carlini
0 siblings, 1 reply; 17+ messages in thread
From: Jonathan Wakely @ 2014-06-26 22:39 UTC (permalink / raw)
To: Paolo Carlini; +Cc: François Dumont, libstdc++, gcc-patches
On 26/06/14 23:21 +0200, Paolo Carlini wrote:
>Hi,
>
>I'm afraid something went badly wrong with this commit, I'm seeing
>tens of fails. See eg:
>
> https://gcc.gnu.org/ml/gcc-testresults/2014-06/msg02439.html
It seems that uneq_allocator is no longer copy constructible.
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: testsuite allocators patch
2014-06-26 22:39 ` Jonathan Wakely
@ 2014-06-27 7:30 ` Paolo Carlini
2014-06-27 17:33 ` Jonathan Wakely
0 siblings, 1 reply; 17+ messages in thread
From: Paolo Carlini @ 2014-06-27 7:30 UTC (permalink / raw)
To: Jonathan Wakely; +Cc: François Dumont, libstdc++, gcc-patches
Hi,
On 06/27/2014 12:38 AM, Jonathan Wakely wrote:
> On 26/06/14 23:21 +0200, Paolo Carlini wrote:
>> Hi,
>>
>> I'm afraid something went badly wrong with this commit, I'm seeing
>> tens of fails. See eg:
>>
>> https://gcc.gnu.org/ml/gcc-testresults/2014-06/msg02439.html
>
> It seems that uneq_allocator is no longer copy constructible.
Can you spot a quick fix, like a thinko, or do you think Francois has to
look into it? I'm inclined to revert it for now, the noise is quite
annoying...
Thanks,
Paolo.
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: testsuite allocators patch
2014-06-27 7:30 ` Paolo Carlini
@ 2014-06-27 17:33 ` Jonathan Wakely
2014-06-27 19:51 ` Paolo Carlini
0 siblings, 1 reply; 17+ messages in thread
From: Jonathan Wakely @ 2014-06-27 17:33 UTC (permalink / raw)
To: Paolo Carlini
Cc: Jonathan Wakely, François Dumont, libstdc++, gcc-patches
I didn't see an obvious fix (I'm not sure if the templated constructor
can deduce its argument since the change) but have been out all day
and not had a chance to look into it.
On 27 June 2014 08:27, Paolo Carlini <paolo.carlini@oracle.com> wrote:
> Hi,
>
>
> On 06/27/2014 12:38 AM, Jonathan Wakely wrote:
>>
>> On 26/06/14 23:21 +0200, Paolo Carlini wrote:
>>>
>>> Hi,
>>>
>>> I'm afraid something went badly wrong with this commit, I'm seeing tens
>>> of fails. See eg:
>>>
>>> https://gcc.gnu.org/ml/gcc-testresults/2014-06/msg02439.html
>>
>>
>> It seems that uneq_allocator is no longer copy constructible.
>
> Can you spot a quick fix, like a thinko, or do you think Francois has to
> look into it? I'm inclined to revert it for now, the noise is quite
> annoying...
>
> Thanks,
> Paolo.
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: testsuite allocators patch
2014-06-27 17:33 ` Jonathan Wakely
@ 2014-06-27 19:51 ` Paolo Carlini
2014-06-27 21:29 ` François Dumont
2014-07-23 20:46 ` François Dumont
0 siblings, 2 replies; 17+ messages in thread
From: Paolo Carlini @ 2014-06-27 19:51 UTC (permalink / raw)
To: Jonathan Wakely
Cc: Jonathan Wakely, François Dumont, libstdc++, gcc-patches
Hi,
On 06/27/2014 07:33 PM, Jonathan Wakely wrote:
> I didn't see an obvious fix (I'm not sure if the templated constructor
> can deduce its argument since the change) but have been out all day
> and not had a chance to look into it.
Ok, thanks. I'm reverting the last two libstdc++-v3 commits.
Paolo.
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: testsuite allocators patch
2014-06-27 19:51 ` Paolo Carlini
@ 2014-06-27 21:29 ` François Dumont
2014-07-23 20:46 ` François Dumont
1 sibling, 0 replies; 17+ messages in thread
From: François Dumont @ 2014-06-27 21:29 UTC (permalink / raw)
To: Paolo Carlini, Jonathan Wakely; +Cc: Jonathan Wakely, libstdc++, gcc-patches
On 27/06/2014 21:48, Paolo Carlini wrote:
> Hi,
>
> On 06/27/2014 07:33 PM, Jonathan Wakely wrote:
>> I didn't see an obvious fix (I'm not sure if the templated constructor
>> can deduce its argument since the change) but have been out all day
>> and not had a chance to look into it.
> Ok, thanks. I'm reverting the last two libstdc++-v3 commits.
>
> Paolo.
>
It run fine on my side but maybe because of other modifications I have.
I will revert those and reapply the patch to see what is wrong.
Sorry
François
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: testsuite allocators patch
2014-06-27 19:51 ` Paolo Carlini
2014-06-27 21:29 ` François Dumont
@ 2014-07-23 20:46 ` François Dumont
2014-07-24 8:58 ` Jonathan Wakely
2014-07-29 19:42 ` Jonathan Wakely
1 sibling, 2 replies; 17+ messages in thread
From: François Dumont @ 2014-07-23 20:46 UTC (permalink / raw)
To: Paolo Carlini, Jonathan Wakely; +Cc: Jonathan Wakely, libstdc++, gcc-patches
[-- Attachment #1: Type: text/plain, Size: 935 bytes --]
On 27/06/2014 21:48, Paolo Carlini wrote:
> Hi,
>
> On 06/27/2014 07:33 PM, Jonathan Wakely wrote:
>> I didn't see an obvious fix (I'm not sure if the templated constructor
>> can deduce its argument since the change) but have been out all day
>> and not had a chance to look into it.
> Ok, thanks. I'm reverting the last two libstdc++-v3 commits.
>
> Paolo.
>
Hi
Back from vacation, ready to have this patch committed eventually.
Here is the new version with the missing default and copy constructor.
I have a small question regarding some code next to the one I am
modifying in this patch. I can see lines like:
propagating_allocator() noexcept = default;
When using a default implementation shouldn't we let the compiler
decide if it should be noexcept or not depending on the member fields or
base class default constructors ?
Tested under Linux x86_64.
Ok to commit ?
François
[-- Attachment #2: testsuite_alloc.patch --]
[-- Type: text/x-patch, Size: 21616 bytes --]
Index: testsuite/util/testsuite_allocator.h
===================================================================
--- testsuite/util/testsuite_allocator.h (revision 212959)
+++ testsuite/util/testsuite_allocator.h (working copy)
@@ -29,6 +29,7 @@
#include <tr1/unordered_map>
#include <bits/move.h>
#include <ext/pointer.h>
+#include <ext/alloc_traits.h>
#include <testsuite_hooks.h>
namespace __gnu_test
@@ -38,26 +39,19 @@
public:
typedef std::size_t size_type;
- static void*
+ static void
allocate(size_type blocksize)
- {
- void* p = ::operator new(blocksize);
- allocationCount_ += blocksize;
- return p;
- }
+ { allocationCount_ += blocksize; }
static void
- construct() { constructCount_++; }
+ construct() { ++constructCount_; }
static void
- destroy() { destructCount_++; }
+ destroy() { ++destructCount_; }
static void
- deallocate(void* p, size_type blocksize)
- {
- ::operator delete(p);
- deallocationCount_ += blocksize;
- }
+ deallocate(size_type blocksize)
+ { deallocationCount_ += blocksize; }
static size_type
get_allocation_count() { return allocationCount_; }
@@ -87,103 +81,142 @@
static int destructCount_;
};
- // A simple basic allocator that just forwards to the
- // tracker_allocator_counter to fulfill memory requests. This class
- // is templated on the target object type, but tracker isn't.
- template<class T>
- class tracker_allocator
- {
- private:
- typedef tracker_allocator_counter counter_type;
+ // Helper to detect inconsistency between type used to instantiate an
+ // allocator and the underlying allocator value_type.
+ template<typename T, typename Alloc,
+ typename = typename Alloc::value_type>
+ struct check_consistent_alloc_value_type;
- public:
- typedef T value_type;
- typedef T* pointer;
- typedef const T* const_pointer;
- typedef T& reference;
- typedef const T& const_reference;
- typedef std::size_t size_type;
- typedef std::ptrdiff_t difference_type;
-
- template<class U> struct rebind { typedef tracker_allocator<U> other; };
-
- pointer
- address(reference value) const _GLIBCXX_NOEXCEPT
- { return std::__addressof(value); }
+ template<typename T, typename Alloc>
+ struct check_consistent_alloc_value_type<T, Alloc, T>
+ { typedef T value_type; };
- const_pointer
- address(const_reference value) const _GLIBCXX_NOEXCEPT
- { return std::__addressof(value); }
+ // An allocator facade that intercepts allocate/deallocate/construct/destroy
+ // calls and track them through the tracker_allocator_counter class. This
+ // class is templated on the target object type, but tracker isn't.
+ template<typename T, typename Alloc = std::allocator<T> >
+ class tracker_allocator : public Alloc
+ {
+ private:
+ typedef tracker_allocator_counter counter_type;
- tracker_allocator() _GLIBCXX_USE_NOEXCEPT
- { }
+ typedef __gnu_cxx::__alloc_traits<Alloc> AllocTraits;
- tracker_allocator(const tracker_allocator&) _GLIBCXX_USE_NOEXCEPT
- { }
+ public:
+ typedef typename
+ check_consistent_alloc_value_type<T, Alloc>::value_type value_type;
+ typedef typename AllocTraits::pointer pointer;
+ typedef typename AllocTraits::size_type size_type;
- template<class U>
- tracker_allocator(const tracker_allocator<U>&) _GLIBCXX_USE_NOEXCEPT
+ template<class U>
+ struct rebind
+ {
+ typedef tracker_allocator<U,
+ typename AllocTraits::template rebind<U>::other> other;
+ };
+
+#if __cplusplus >= 201103L
+ tracker_allocator() = default;
+ tracker_allocator(const tracker_allocator&) = default;
+ tracker_allocator(tracker_allocator&&) = default;
+
+ // Perfect forwarding constructor.
+ template<typename... _Args>
+ tracker_allocator(_Args&&... __args)
+ : Alloc(std::forward<_Args>(__args)...)
+ { }
+#else
+ tracker_allocator()
{ }
- ~tracker_allocator() _GLIBCXX_USE_NOEXCEPT
- { }
+ tracker_allocator(const tracker_allocator&)
+ { }
- size_type
- max_size() const _GLIBCXX_USE_NOEXCEPT
- { return size_type(-1) / sizeof(T); }
+ ~tracker_allocator()
+ { }
+#endif
- pointer
- allocate(size_type n, const void* = 0)
- { return static_cast<pointer>(counter_type::allocate(n * sizeof(T))); }
+ template<class U>
+ tracker_allocator(const tracker_allocator<U,
+ typename AllocTraits::template rebind<U>::other>& alloc)
+ _GLIBCXX_USE_NOEXCEPT
+ : Alloc(alloc)
+ { }
+ pointer
+ allocate(size_type n, const void* = 0)
+ {
+ pointer p = AllocTraits::allocate(*this, n);
+ counter_type::allocate(n * sizeof(T));
+ return p;
+ }
+
#if __cplusplus >= 201103L
- template<typename U, typename... Args>
+ template<typename U, typename... Args>
+ void
+ construct(U* p, Args&&... args)
+ {
+ AllocTraits::construct(*this, p, std::forward<Args>(args)...);
+ counter_type::construct();
+ }
+
+ template<typename U>
+ void
+ destroy(U* p)
+ {
+ AllocTraits::destroy(*this, p);
+ counter_type::destroy();
+ }
+#else
void
- construct(U* p, Args&&... args)
+ construct(pointer p, const T& value)
{
- ::new((void *)p) U(std::forward<Args>(args)...);
+ AllocTraits::construct(*this, p, value);
counter_type::construct();
}
- template<typename U>
void
- destroy(U* p)
+ destroy(pointer p)
{
- p->~U();
+ AllocTraits::destroy(*this, p);
counter_type::destroy();
}
-#else
- void
- construct(pointer p, const T& value)
- {
- ::new ((void *)p) T(value);
- counter_type::construct();
- }
-
- void
- destroy(pointer p)
- {
- p->~T();
- counter_type::destroy();
- }
#endif
- void
- deallocate(pointer p, size_type num)
- { counter_type::deallocate(p, num * sizeof(T)); }
- };
+ void
+ deallocate(pointer p, size_type num)
+ {
+ counter_type::deallocate(num * sizeof(T));
+ AllocTraits::deallocate(*this, p, num);
+ }
- template<class T1, class T2>
+ // Implement swap for underlying allocators that might need it.
+ friend inline void
+ swap(tracker_allocator& a, tracker_allocator& b)
+ {
+ using std::swap;
+
+ Alloc& aa = a;
+ Alloc& ab = b;
+ swap(aa, ab);
+ }
+ };
+
+ template<class T1, class Alloc1, class T2, class Alloc2>
bool
- operator==(const tracker_allocator<T1>&,
- const tracker_allocator<T2>&) throw()
- { return true; }
+ operator==(const tracker_allocator<T1, Alloc1>& lhs,
+ const tracker_allocator<T2, Alloc2>& rhs) throw()
+ {
+ const Alloc1& alloc1 = lhs;
+ const Alloc2& alloc2 = rhs;
+ return lhs == rhs;
+ }
- template<class T1, class T2>
+ template<class T1, class Alloc1, class T2, class Alloc2>
bool
- operator!=(const tracker_allocator<T1>&,
- const tracker_allocator<T2>&) throw()
- { return false; }
+ operator!=(const tracker_allocator<T1, Alloc1>& lhs,
+ const tracker_allocator<T2, Alloc2>& rhs) throw()
+ { return !(lhs == rhs); }
bool
check_construct_destroy(const char* tag, int expected_c, int expected_d);
@@ -193,7 +226,7 @@
check_deallocate_null()
{
// Let's not core here...
- Alloc a;
+ Alloc a;
a.deallocate(0, 1);
a.deallocate(0, 10);
return true;
@@ -219,7 +252,6 @@
throw;
}
-
// A simple allocator which can be constructed endowed of a given
// "personality" (an integer), queried in operator== to simulate the
// behavior of realworld "unequal" allocators (i.e., not exploiting
@@ -227,7 +259,7 @@
// filled at allocation time with (pointer, personality) pairs, is
// then consulted to enforce the requirements in Table 32 about
// deallocation vs allocator equality. Note that this allocator is
- // swappable, not assignable, consistently with Option 3 of DR 431
+ // swappable, not copy assignable, consistently with Option 3 of DR 431
// (see N1599).
struct uneq_allocator_base
{
@@ -244,26 +276,33 @@
}
};
- template<typename Tp>
+ template<typename Tp, typename Alloc = std::allocator<Tp> >
class uneq_allocator
- : private uneq_allocator_base
+ : private uneq_allocator_base,
+ public Alloc
{
+ typedef __gnu_cxx::__alloc_traits<Alloc> AllocTraits;
+
+ Alloc& base() { return *this; }
+ const Alloc& base() const { return *this; }
+ void swap_base(Alloc& b) { swap(b, this->base()); }
+
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 check_consistent_alloc_value_type<Tp, Alloc>::value_type
+ value_type;
+ typedef typename AllocTraits::size_type size_type;
+ typedef typename AllocTraits::pointer pointer;
#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 AllocTraits::template rebind<Tp1>::other> other;
+ };
uneq_allocator() _GLIBCXX_USE_NOEXCEPT
: personality(0) { }
@@ -270,9 +309,16 @@
uneq_allocator(int person) _GLIBCXX_USE_NOEXCEPT
: personality(person) { }
+
+#if __cplusplus >= 201103L
+ uneq_allocator(const uneq_allocator&) = default;
+ uneq_allocator(uneq_allocator&&) = default;
+#endif
template<typename Tp1>
- uneq_allocator(const uneq_allocator<Tp1>& b) _GLIBCXX_USE_NOEXCEPT
+ uneq_allocator(const uneq_allocator<Tp1,
+ typename AllocTraits::template rebind<Tp1>::other>& b)
+ _GLIBCXX_USE_NOEXCEPT
: personality(b.get_personality()) { }
~uneq_allocator() _GLIBCXX_USE_NOEXCEPT
@@ -281,20 +327,10 @@
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); }
+ allocate(size_type n, const void* hint = 0)
+ {
+ pointer p = AllocTraits::allocate(*this, n);
- pointer
- allocate(size_type n, const void* = 0)
- {
- if (__builtin_expect(n > this->max_size(), false))
- std::__throw_bad_alloc();
-
- pointer p = static_cast<Tp*>(::operator new(n * sizeof(Tp)));
try
{
get_map().insert(map_type::value_type(reinterpret_cast<void*>(p),
@@ -302,14 +338,15 @@
}
catch(...)
{
- ::operator delete(p);
+ AllocTraits::deallocate(*this, p, n);
__throw_exception_again;
}
+
return p;
}
void
- deallocate(pointer p, size_type)
+ deallocate(pointer p, size_type n)
{
bool test __attribute__((unused)) = true;
@@ -323,34 +360,18 @@
VERIFY( it->second == personality );
get_map().erase(it);
- ::operator delete(p);
+ AllocTraits::deallocate(*this, p, n);
}
- size_type
- max_size() const _GLIBCXX_USE_NOEXCEPT
- { return size_type(-1) / sizeof(Tp); }
-
#if __cplusplus >= 201103L
- template<typename U, typename... Args>
- void
- construct(U* p, Args&&... args)
- { ::new((void *)p) U(std::forward<Args>(args)...); }
-
- template<typename U>
- void
- destroy(U* p) { p->~U(); }
-
// Not copy assignable...
uneq_allocator&
operator=(const uneq_allocator&) = delete;
+
+ // ... but still moveable if base allocator is.
+ uneq_allocator&
+ operator=(uneq_allocator&&) = default;
#else
- void
- construct(pointer p, const Tp& val)
- { ::new((void *)p) Tp(val); }
-
- void
- destroy(pointer p) { p->~Tp(); }
-
private:
// Not assignable...
uneq_allocator&
@@ -358,21 +379,27 @@
#endif
private:
-
// ... yet swappable!
friend inline void
swap(uneq_allocator& a, uneq_allocator& b)
- { std::swap(a.personality, b.personality); }
-
+ {
+ std::swap(a.personality, b.personality);
+ a.swap_base(b);
+ }
+
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<Tp1,
+ typename AllocTraits::template rebind<Tp1>::other>& 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<Tp1,
+ typename AllocTraits::template rebind<Tp1>::other>& b)
+ { return !(a == b); }
int personality;
};
@@ -379,10 +406,12 @@
#if __cplusplus >= 201103L
// An uneq_allocator which can be used to test allocator propagation.
- template<typename Tp, bool Propagate>
- class propagating_allocator : public uneq_allocator<Tp>
+ template<typename Tp, bool Propagate, typename Alloc = std::allocator<Tp>>
+ class propagating_allocator : public uneq_allocator<Tp, Alloc>
{
- typedef uneq_allocator<Tp> base_alloc;
+ typedef __gnu_cxx::__alloc_traits<Alloc> AllocTraits;
+
+ typedef uneq_allocator<Tp, Alloc> base_alloc;
base_alloc& base() { return *this; }
const base_alloc& base() const { return *this; }
void swap_base(base_alloc& b) { swap(b, this->base()); }
@@ -393,7 +422,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 AllocTraits::template rebind<Up>::other> other;
+ };
propagating_allocator(int i) noexcept
: base_alloc(i)
@@ -400,8 +433,9 @@
{ }
template<typename Up>
- propagating_allocator(const propagating_allocator<Up, Propagate>& a)
- noexcept
+ propagating_allocator(const propagating_allocator<Up, Propagate,
+ typename AllocTraits::template rebind<Up>::other>& a)
+ noexcept
: base_alloc(a)
{ }
@@ -418,8 +452,8 @@
}
template<bool P2>
- propagating_allocator&
- operator=(const propagating_allocator<Tp, P2>& a) noexcept
+ propagating_allocator&
+ operator=(const propagating_allocator<Tp, P2, Alloc>& a) noexcept
{
static_assert(P2, "assigning propagating_allocator<T, true>");
propagating_allocator(a).swap_base(*this);
Index: testsuite/23_containers/forward_list/debug/move_assign_neg.cc
===================================================================
--- testsuite/23_containers/forward_list/debug/move_assign_neg.cc (revision 212959)
+++ testsuite/23_containers/forward_list/debug/move_assign_neg.cc (working copy)
@@ -25,7 +25,7 @@
{
bool test __attribute__((unused)) = true;
- typedef __gnu_test::uneq_allocator<int> alloc_type;
+ typedef __gnu_test::propagating_allocator<int, false> alloc_type;
typedef __gnu_debug::forward_list<int, alloc_type> test_type;
test_type v1(alloc_type(1));
Index: testsuite/23_containers/map/debug/move_assign_neg.cc
===================================================================
--- testsuite/23_containers/map/debug/move_assign_neg.cc (revision 212959)
+++ testsuite/23_containers/map/debug/move_assign_neg.cc (working copy)
@@ -25,7 +25,8 @@
{
bool test __attribute__((unused)) = true;
- typedef __gnu_test::uneq_allocator<std::pair<const int, int> > alloc_type;
+ typedef __gnu_test::propagating_allocator<std::pair<const int, int>,
+ false> alloc_type;
typedef __gnu_debug::map<int, int, std::less<int>, alloc_type> test_type;
test_type v1(alloc_type(1));
Index: testsuite/23_containers/multimap/debug/move_assign_neg.cc
===================================================================
--- testsuite/23_containers/multimap/debug/move_assign_neg.cc (revision 212959)
+++ testsuite/23_containers/multimap/debug/move_assign_neg.cc (working copy)
@@ -25,7 +25,8 @@
{
bool test __attribute__((unused)) = true;
- typedef __gnu_test::uneq_allocator<std::pair<const int, int> > alloc_type;
+ typedef __gnu_test::propagating_allocator<std::pair<const int, int>,
+ false> alloc_type;
typedef __gnu_debug::multimap<int, int, std::less<int>, alloc_type> test_type;
test_type v1(alloc_type(1));
Index: testsuite/23_containers/multiset/debug/move_assign_neg.cc
===================================================================
--- testsuite/23_containers/multiset/debug/move_assign_neg.cc (revision 212959)
+++ testsuite/23_containers/multiset/debug/move_assign_neg.cc (working copy)
@@ -25,7 +25,7 @@
{
bool test __attribute__((unused)) = true;
- typedef __gnu_test::uneq_allocator<int> alloc_type;
+ typedef __gnu_test::propagating_allocator<int, false> alloc_type;
typedef __gnu_debug::multiset<int, std::less<int>, alloc_type> test_type;
test_type v1(alloc_type(1));
Index: testsuite/23_containers/set/debug/move_assign_neg.cc
===================================================================
--- testsuite/23_containers/set/debug/move_assign_neg.cc (revision 212959)
+++ testsuite/23_containers/set/debug/move_assign_neg.cc (working copy)
@@ -25,7 +25,7 @@
{
bool test __attribute__((unused)) = true;
- typedef __gnu_test::uneq_allocator<int> alloc_type;
+ typedef __gnu_test::propagating_allocator<int, false> alloc_type;
typedef __gnu_debug::set<int, std::less<int>, alloc_type> test_type;
test_type v1(alloc_type(1));
Index: testsuite/23_containers/unordered_map/debug/move_assign_neg.cc
===================================================================
--- testsuite/23_containers/unordered_map/debug/move_assign_neg.cc (revision 212959)
+++ testsuite/23_containers/unordered_map/debug/move_assign_neg.cc (working copy)
@@ -25,7 +25,8 @@
{
bool test __attribute__((unused)) = true;
- typedef __gnu_test::uneq_allocator<std::pair<const int, int> > alloc_type;
+ typedef __gnu_test::propagating_allocator<std::pair<const int, int>,
+ false> alloc_type;
typedef __gnu_debug::unordered_map<int, int,
std::hash<int>, std::equal_to<int>,
alloc_type> test_type;
Index: testsuite/23_containers/unordered_multimap/debug/move_assign_neg.cc
===================================================================
--- testsuite/23_containers/unordered_multimap/debug/move_assign_neg.cc (revision 212959)
+++ testsuite/23_containers/unordered_multimap/debug/move_assign_neg.cc (working copy)
@@ -25,7 +25,8 @@
{
bool test __attribute__((unused)) = true;
- typedef __gnu_test::uneq_allocator<std::pair<const int, int>> alloc_type;
+ typedef __gnu_test::propagating_allocator<std::pair<const int, int>,
+ false> alloc_type;
typedef __gnu_debug::unordered_multimap<int, int, std::hash<int>,
std::equal_to<int>,
alloc_type> test_type;
Index: testsuite/23_containers/unordered_multiset/debug/move_assign_neg.cc
===================================================================
--- testsuite/23_containers/unordered_multiset/debug/move_assign_neg.cc (revision 212959)
+++ testsuite/23_containers/unordered_multiset/debug/move_assign_neg.cc (working copy)
@@ -25,7 +25,7 @@
{
bool test __attribute__((unused)) = true;
- typedef __gnu_test::uneq_allocator<int> alloc_type;
+ typedef __gnu_test::propagating_allocator<int, false> alloc_type;
typedef __gnu_debug::unordered_multiset<int, std::hash<int>,
std::equal_to<int>,
alloc_type> test_type;
Index: testsuite/23_containers/unordered_set/debug/move_assign_neg.cc
===================================================================
--- testsuite/23_containers/unordered_set/debug/move_assign_neg.cc (revision 212959)
+++ testsuite/23_containers/unordered_set/debug/move_assign_neg.cc (working copy)
@@ -25,7 +25,7 @@
{
bool test __attribute__((unused)) = true;
- typedef __gnu_test::uneq_allocator<int> alloc_type;
+ typedef __gnu_test::propagating_allocator<int, false> alloc_type;
typedef __gnu_debug::unordered_set<int, std::hash<int>,
std::equal_to<int>,
alloc_type> test_type;
Index: testsuite/23_containers/vector/debug/move_assign_neg.cc
===================================================================
--- testsuite/23_containers/vector/debug/move_assign_neg.cc (revision 212959)
+++ testsuite/23_containers/vector/debug/move_assign_neg.cc (working copy)
@@ -27,7 +27,7 @@
{
bool test __attribute__((unused)) = true;
- typedef __gnu_test::uneq_allocator<int> alloc_type;
+ typedef __gnu_test::propagating_allocator<int, false> alloc_type;
typedef __gnu_debug::vector<int, alloc_type> test_type;
test_type v1(alloc_type(1));
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: testsuite allocators patch
2014-07-23 20:46 ` François Dumont
@ 2014-07-24 8:58 ` Jonathan Wakely
2014-07-24 20:30 ` François Dumont
2014-07-29 19:42 ` Jonathan Wakely
1 sibling, 1 reply; 17+ messages in thread
From: Jonathan Wakely @ 2014-07-24 8:58 UTC (permalink / raw)
To: François Dumont
Cc: Paolo Carlini, Jonathan Wakely, libstdc++, gcc-patches
On 23/07/14 22:33 +0200, François Dumont wrote:
> I have a small question regarding some code next to the one I am
>modifying in this patch. I can see lines like:
>
> propagating_allocator() noexcept = default;
>
> When using a default implementation shouldn't we let the compiler
>decide if it should be noexcept or not depending on the member fields
>or base class default constructors ?
Stating it explicitly means you get an error if the default
implementation is not noexcept. That can be useful, to ensure you
don't silently start getting a throwing constructor by mistake because
of a change to a base class.
I'm not sure if I added the noexcept above, but if I did that might
have been what I was intending it to do. I don't remember.
I'll review the rest of the patch ASAP. Did you test it with no other
changes in your tree, and run the entire testsuite?
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: testsuite allocators patch
2014-07-24 8:58 ` Jonathan Wakely
@ 2014-07-24 20:30 ` François Dumont
2014-07-24 23:36 ` Jonathan Wakely
0 siblings, 1 reply; 17+ messages in thread
From: François Dumont @ 2014-07-24 20:30 UTC (permalink / raw)
To: Jonathan Wakely; +Cc: Paolo Carlini, Jonathan Wakely, libstdc++, gcc-patches
On 24/07/2014 10:55, Jonathan Wakely wrote:
> On 23/07/14 22:33 +0200, François Dumont wrote:
>> I have a small question regarding some code next to the one I am
>> modifying in this patch. I can see lines like:
>>
>> propagating_allocator() noexcept = default;
>>
>> When using a default implementation shouldn't we let the compiler
>> decide if it should be noexcept or not depending on the member fields
>> or base class default constructors ?
>
> Stating it explicitly means you get an error if the default
> implementation is not noexcept. That can be useful, to ensure you
> don't silently start getting a throwing constructor by mistake because
> of a change to a base class.
>
> I'm not sure if I added the noexcept above, but if I did that might
> have been what I was intending it to do. I don't remember.
>
> I'll review the rest of the patch ASAP. Did you test it with no other
> changes in your tree, and run the entire testsuite?
>
Ok, thanks for the explanation, it is clear now.
Yes I have tested with no other changes in my tree and got only those
pretty printers errors which are unrelated I think:
Python Exception <class 'TypeError'> iter() returned non-iterator of
type '_contained':
$2 = std::experimental::optional<int> [no contained value]
skipping: Python Exception <class 'TypeError'> iter() returned
non-iterator of type '_contained':
got: $2 = std::experimental::optional<int> [no contained value]
PASS: libstdc++-prettyprinters/libfundts.cc print o
Python Exception <class 'TypeError'> iter() returned non-iterator of
type '_contained':
$3 = std::experimental::optional<bool>
skipping: Python Exception <class 'TypeError'> iter() returned
non-iterator of type '_contained':
got: $3 = std::experimental::optional<bool>
FAIL: libstdc++-prettyprinters/libfundts.cc print ob
Python Exception <class 'TypeError'> iter() returned non-iterator of
type '_contained':
$4 = std::experimental::optional<int>
skipping: Python Exception <class 'TypeError'> iter() returned
non-iterator of type '_contained':
got: $4 = std::experimental::optional<int>
FAIL: libstdc++-prettyprinters/libfundts.cc print oi
François
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: testsuite allocators patch
2014-07-24 20:30 ` François Dumont
@ 2014-07-24 23:36 ` Jonathan Wakely
2014-07-29 21:34 ` Jonathan Wakely
0 siblings, 1 reply; 17+ messages in thread
From: Jonathan Wakely @ 2014-07-24 23:36 UTC (permalink / raw)
To: François Dumont
Cc: Jonathan Wakely, Paolo Carlini, libstdc++, gcc-patches
On 24 July 2014 21:11, François Dumont wrote:
>
> Yes I have tested with no other changes in my tree and got only those pretty
> printers errors which are unrelated I think:
>
> Python Exception <class 'TypeError'> iter() returned non-iterator of type
> '_contained':
> $2 = std::experimental::optional<int> [no contained value]
I haven't seen these, I'll fix them on Monday, thanks.
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: testsuite allocators patch
2014-07-23 20:46 ` François Dumont
2014-07-24 8:58 ` Jonathan Wakely
@ 2014-07-29 19:42 ` Jonathan Wakely
1 sibling, 0 replies; 17+ messages in thread
From: Jonathan Wakely @ 2014-07-29 19:42 UTC (permalink / raw)
To: François Dumont
Cc: Paolo Carlini, Jonathan Wakely, libstdc++, gcc-patches
On 23/07/14 22:33 +0200, François Dumont wrote:
>On 27/06/2014 21:48, Paolo Carlini wrote:
>>Hi,
>>
>>On 06/27/2014 07:33 PM, Jonathan Wakely wrote:
>>>I didn't see an obvious fix (I'm not sure if the templated constructor
>>>can deduce its argument since the change) but have been out all day
>>>and not had a chance to look into it.
>>Ok, thanks. I'm reverting the last two libstdc++-v3 commits.
>>
>>Paolo.
>>
>
>Hi
>
> Back from vacation, ready to have this patch committed eventually.
>
> Here is the new version with the missing default and copy constructor.
>
> I have a small question regarding some code next to the one I am
>modifying in this patch. I can see lines like:
>
> propagating_allocator() noexcept = default;
>
> When using a default implementation shouldn't we let the compiler
>decide if it should be noexcept or not depending on the member fields
>or base class default constructors ?
>
> Tested under Linux x86_64.
>
> Ok to commit ?
OK, thanks.
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: testsuite allocators patch
2014-07-24 23:36 ` Jonathan Wakely
@ 2014-07-29 21:34 ` Jonathan Wakely
2014-07-29 21:44 ` Jonathan Wakely
0 siblings, 1 reply; 17+ messages in thread
From: Jonathan Wakely @ 2014-07-29 21:34 UTC (permalink / raw)
To: libstdc++, gcc-patches; +Cc: François Dumont, Paolo Carlini
[-- Attachment #1: Type: text/plain, Size: 572 bytes --]
On 25/07/14 00:19 +0100, Jonathan Wakely wrote:
>On 24 July 2014 21:11, François Dumont wrote:
>>
>> Yes I have tested with no other changes in my tree and got only those pretty
>> printers errors which are unrelated I think:
>>
>> Python Exception <class 'TypeError'> iter() returned non-iterator of type
>> '_contained':
>> $2 = std::experimental::optional<int> [no contained value]
>
>I haven't seen these, I'll fix them on Monday, thanks.
Fixed by the attached patch.
Tested x86_64-linux (thanks to Samual Bronson for testing with
Python3) and committed to trunk.
[-- Attachment #2: patch.txt --]
[-- Type: text/x-patch, Size: 1031 bytes --]
commit 7de83299c42041611360a1426f5164270ac6c6b6
Author: Jonathan Wakely <jwakely@redhat.com>
Date: Tue Jul 29 20:08:31 2014 +0100
* python/libstdcxx/v6/printers.py
(SingleObjContainerPrinter._contained): Use compatibility mixin.
diff --git a/libstdc++-v3/python/libstdcxx/v6/printers.py b/libstdc++-v3/python/libstdcxx/v6/printers.py
index 15d7a88..2e5cd6c 100644
--- a/libstdc++-v3/python/libstdcxx/v6/printers.py
+++ b/libstdc++-v3/python/libstdcxx/v6/printers.py
@@ -851,14 +851,14 @@ class SingleObjContainerPrinter(object):
return gdb.types.apply_type_recognizers(gdb.types.get_type_recognizers(),
type) or str(type)
- class _contained:
+ class _contained(Iterator):
def __init__ (self, val):
self.val = val
def __iter__ (self):
return self
- def next (self):
+ def __next__(self):
if self.val is None:
raise StopIteration
retval = self.val
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: testsuite allocators patch
2014-07-29 21:34 ` Jonathan Wakely
@ 2014-07-29 21:44 ` Jonathan Wakely
0 siblings, 0 replies; 17+ messages in thread
From: Jonathan Wakely @ 2014-07-29 21:44 UTC (permalink / raw)
To: libstdc++, gcc-patches; +Cc: François Dumont, Paolo Carlini
On 29/07/14 22:33 +0100, Jonathan Wakely wrote:
>Tested x86_64-linux (thanks to Samual Bronson for testing with
>Python3) and committed to trunk.
Oops, Samuel not Samual ... no idea why my fingers typed that wrong!
^ permalink raw reply [flat|nested] 17+ messages in thread
end of thread, other threads:[~2014-07-29 21:39 UTC | newest]
Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-06-20 20:37 testsuite allocators patch François Dumont
2014-06-25 19:48 ` François Dumont
2014-06-26 10:33 ` Jonathan Wakely
2014-06-26 20:45 ` François Dumont
2014-06-26 21:24 ` Paolo Carlini
2014-06-26 22:39 ` Jonathan Wakely
2014-06-27 7:30 ` Paolo Carlini
2014-06-27 17:33 ` Jonathan Wakely
2014-06-27 19:51 ` Paolo Carlini
2014-06-27 21:29 ` François Dumont
2014-07-23 20:46 ` François Dumont
2014-07-24 8:58 ` Jonathan Wakely
2014-07-24 20:30 ` François Dumont
2014-07-24 23:36 ` Jonathan Wakely
2014-07-29 21:34 ` Jonathan Wakely
2014-07-29 21:44 ` Jonathan Wakely
2014-07-29 19:42 ` Jonathan Wakely
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).