From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 31463 invoked by alias); 25 Jun 2014 19:48:21 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 31422 invoked by uid 89); 25 Jun 2014 19:48:12 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.6 required=5.0 tests=AWL,BAYES_00,FREEMAIL_FROM,RCVD_IN_DNSWL_LOW,SPF_PASS autolearn=ham version=3.3.2 X-Spam-User: qpsmtpd, 2 recipients X-HELO: mail-wg0-f43.google.com Received: from mail-wg0-f43.google.com (HELO mail-wg0-f43.google.com) (74.125.82.43) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-SHA encrypted) ESMTPS; Wed, 25 Jun 2014 19:48:06 +0000 Received: by mail-wg0-f43.google.com with SMTP id b13so2514157wgh.26 for ; Wed, 25 Jun 2014 12:48:02 -0700 (PDT) X-Received: by 10.194.246.234 with SMTP id xz10mr11600845wjc.77.1403725682805; Wed, 25 Jun 2014 12:48:02 -0700 (PDT) Received: from [192.168.0.22] (arf62-1-82-237-250-248.fbx.proxad.net. [82.237.250.248]) by mx.google.com with ESMTPSA id o3sm15694690wix.15.2014.06.25.12.48.00 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Wed, 25 Jun 2014 12:48:01 -0700 (PDT) Message-ID: <53AB276F.10806@gmail.com> Date: Wed, 25 Jun 2014 19:48:00 -0000 From: =?ISO-8859-1?Q?Fran=E7ois_Dumont?= User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Thunderbird/24.5.0 MIME-Version: 1.0 To: "libstdc++@gcc.gnu.org" , gcc-patches Subject: Re: testsuite allocators patch References: <53A49B7C.5080506@gmail.com> In-Reply-To: <53A49B7C.5080506@gmail.com> Content-Type: multipart/mixed; boundary="------------040000030407060709090608" X-SW-Source: 2014-06/txt/msg02050.txt.bz2 This is a multi-part message in MIME format. --------------040000030407060709090608 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 8bit Content-length: 1976 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 > > * 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 > --------------040000030407060709090608 Content-Type: text/x-patch; name="testsuite_alloc.patch" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="testsuite_alloc.patch" Content-length: 21162 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 #include #include +#include #include 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 + struct check_consistent_alloc_value_type; + + template + struct check_consistent_alloc_value_type + { 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 tracker_allocator - { - private: - typedef tracker_allocator_counter counter_type; + template > + 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 AllocTraits; + + public: + typedef typename + check_consistent_alloc_value_type::value_type value_type; + typedef typename AllocTraits::pointer pointer; + typedef typename AllocTraits::size_type size_type; - template struct rebind { typedef tracker_allocator other; }; + template + struct rebind + { + typedef tracker_allocator::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 + 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 - tracker_allocator(const tracker_allocator&) _GLIBCXX_USE_NOEXCEPT + ~tracker_allocator() _GLIBCXX_USE_NOEXCEPT { } +#endif - ~tracker_allocator() _GLIBCXX_USE_NOEXCEPT - { } + template + tracker_allocator(const tracker_allocator::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(counter_type::allocate(n * sizeof(T))); } +#if __cplusplus >= 201103L + template + void + construct(U* p, Args&&... args) + { + AllocTraits::construct(*this, p, std::forward(args)...); + counter_type::construct(); + } -#if __cplusplus >= 201103L - template + template + 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)...); + AllocTraits::construct(*this, p, value); counter_type::construct(); } - template 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 + // 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 bool - operator==(const tracker_allocator&, - const tracker_allocator&) throw() - { return true; } + operator==(const tracker_allocator& lhs, + const tracker_allocator& rhs) throw() + { + const Alloc1& alloc1 = lhs; + const Alloc2& alloc2 = rhs; + return lhs == rhs; + } - template + template bool - operator!=(const tracker_allocator&, - const tracker_allocator&) throw() - { return false; } + operator!=(const tracker_allocator& lhs, + const tracker_allocator& 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 + template > class uneq_allocator - : private uneq_allocator_base + : private uneq_allocator_base, + public Alloc { + typedef __gnu_cxx::__alloc_traits 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::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 - struct rebind - { typedef uneq_allocator other; }; + struct rebind + { + typedef uneq_allocator::other> other; + }; uneq_allocator() _GLIBCXX_USE_NOEXCEPT : personality(0) { } @@ -272,7 +311,9 @@ : personality(person) { } template - uneq_allocator(const uneq_allocator& b) _GLIBCXX_USE_NOEXCEPT + uneq_allocator(const uneq_allocator::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(::operator new(n * sizeof(Tp))); + pointer p = AllocTraits::allocate(*this, n); try { get_map().insert(map_type::value_type(reinterpret_cast(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 - void - construct(U* p, Args&&... args) - { ::new((void *)p) U(std::forward(args)...); } - - template - 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 - friend inline bool - operator==(const uneq_allocator& a, const uneq_allocator& b) - { return a.personality == b.personality; } + friend inline bool + operator==(const uneq_allocator& a, + const uneq_allocator::other>& b) + { return a.personality == b.personality; } template - friend inline bool - operator!=(const uneq_allocator& a, const uneq_allocator& b) - { return !(a == b); } + friend inline bool + operator!=(const uneq_allocator& a, + const uneq_allocator::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 - class propagating_allocator : public uneq_allocator + template> + class propagating_allocator : public uneq_allocator { - typedef uneq_allocator base_alloc; + typedef __gnu_cxx::__alloc_traits AllocTraits; + + typedef uneq_allocator 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 - struct rebind { typedef propagating_allocator other; }; + struct rebind + { + typedef propagating_allocator::other> other; + }; propagating_allocator(int i) noexcept : base_alloc(i) @@ -400,8 +426,9 @@ { } template - propagating_allocator(const propagating_allocator& a) - noexcept + propagating_allocator(const propagating_allocator::other>& a) + noexcept : base_alloc(a) { } @@ -418,8 +445,8 @@ } template - propagating_allocator& - operator=(const propagating_allocator& a) noexcept + propagating_allocator& + operator=(const propagating_allocator& a) noexcept { static_assert(P2, "assigning propagating_allocator"); 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 alloc_type; + typedef __gnu_test::propagating_allocator alloc_type; typedef __gnu_debug::forward_list 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 > alloc_type; + typedef __gnu_test::propagating_allocator, + false> alloc_type; typedef __gnu_debug::map, 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 > alloc_type; + typedef __gnu_test::propagating_allocator, + false> alloc_type; typedef __gnu_debug::multimap, 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 alloc_type; + typedef __gnu_test::propagating_allocator alloc_type; typedef __gnu_debug::multiset, 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 alloc_type; + typedef __gnu_test::propagating_allocator alloc_type; typedef __gnu_debug::set, 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 > alloc_type; + typedef __gnu_test::propagating_allocator, + false> alloc_type; typedef __gnu_debug::unordered_map, std::equal_to, 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> alloc_type; + typedef __gnu_test::propagating_allocator, + false> alloc_type; typedef __gnu_debug::unordered_multimap, std::equal_to, 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 alloc_type; + typedef __gnu_test::propagating_allocator alloc_type; typedef __gnu_debug::unordered_multiset, std::equal_to, 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 alloc_type; + typedef __gnu_test::propagating_allocator alloc_type; typedef __gnu_debug::unordered_set, std::equal_to, 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 alloc_type; + typedef __gnu_test::propagating_allocator alloc_type; typedef __gnu_debug::vector test_type; test_type v1(alloc_type(1)); --------------040000030407060709090608--