diff options
author | fdumont <fdumont@138bc75d-0d04-0410-961f-82ee72b054a4> | 2013-05-07 20:26:15 +0000 |
---|---|---|
committer | fdumont <fdumont@138bc75d-0d04-0410-961f-82ee72b054a4> | 2013-05-07 20:26:15 +0000 |
commit | c50ff294f77295d98662af55db383e38dfce5a55 (patch) | |
tree | 92c9652b0d5109aa6374cb73a679a0241e262cd0 /libstdc++-v3/include/profile | |
parent | 5c2d214df49bbdccbb8fc6dbf31593c7e3a385b7 (diff) | |
download | ppe42-gcc-c50ff294f77295d98662af55db383e38dfce5a55.tar.gz ppe42-gcc-c50ff294f77295d98662af55db383e38dfce5a55.zip |
2013-05-07 François Dumont <fdumont@gcc.gnu.org>
* include/profile/unordered_base.h: New.
* include/Makefile.am: Add new profile header.
* include/Makefile.in: Regenerate.
* include/profile/impl/profiler.h
(__profcxx_inefficient_hash_is_on): New macro.
* include/profile/unordered_map (std::profile::unordered_map<>):
Use new _Unordered_profile base class. Use default implementations
for special functions.
(std::profile::unordered_multimap<>): Likewise.
* include/profile/unordered_set (std::profile::unordered_set<>):
Likewise.
(std::profile::unordered_multiset<>): Likewise.
* testsuite/23_containers/unordered_multiset/55043.cc: Fix
MoveOnly equality operator signature.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@198698 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libstdc++-v3/include/profile')
-rw-r--r-- | libstdc++-v3/include/profile/impl/profiler.h | 9 | ||||
-rw-r--r-- | libstdc++-v3/include/profile/unordered_base.h | 262 | ||||
-rw-r--r-- | libstdc++-v3/include/profile/unordered_map | 261 | ||||
-rw-r--r-- | libstdc++-v3/include/profile/unordered_set | 259 |
4 files changed, 444 insertions, 347 deletions
diff --git a/libstdc++-v3/include/profile/impl/profiler.h b/libstdc++-v3/include/profile/impl/profiler.h index d8019cb313f..081bb64ba96 100644 --- a/libstdc++-v3/include/profile/impl/profiler.h +++ b/libstdc++-v3/include/profile/impl/profiler.h @@ -188,7 +188,7 @@ namespace __gnu_profile _GLIBCXX_PROFILE_REENTRANCE_GUARD(__gnu_profile::__is_invalid()) #define __profcxx_is_on() \ _GLIBCXX_PROFILE_REENTRANCE_GUARD(__gnu_profile::__is_on()) -#define __profcxx__is_off() \ +#define __profcxx_is_off() \ _GLIBCXX_PROFILE_REENTRANCE_GUARD(__gnu_profile::__is_off()) #else #define __profcxx_report() @@ -237,6 +237,8 @@ namespace __gnu_profile // Turn on/off instrumentation for INEFFICIENT_HASH. #if defined(_GLIBCXX_PROFILE_INEFFICIENT_HASH) +#define __profcxx_inefficient_hash_is_on() \ + __gnu_profile::__is_on() #define __profcxx_hashtable_construct2(__x...) \ _GLIBCXX_PROFILE_REENTRANCE_GUARD( \ __gnu_profile::__trace_hash_func_construct(__x)) @@ -244,8 +246,9 @@ namespace __gnu_profile _GLIBCXX_PROFILE_REENTRANCE_GUARD( \ __gnu_profile::__trace_hash_func_destruct(__x)) #else -#define __profcxx_hashtable_destruct2(__x...) -#define __profcxx_hashtable_construct2(__x...) +#define __profcxx_inefficient_hash_is_on() false +#define __profcxx_hashtable_destruct2(__x...) +#define __profcxx_hashtable_construct2(__x...) #endif // Turn on/off instrumentation for VECTOR_TO_LIST. diff --git a/libstdc++-v3/include/profile/unordered_base.h b/libstdc++-v3/include/profile/unordered_base.h new file mode 100644 index 00000000000..81d7694f515 --- /dev/null +++ b/libstdc++-v3/include/profile/unordered_base.h @@ -0,0 +1,262 @@ +// Profiling unordered containers implementation details -*- C++ -*- + +// Copyright (C) 2013 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. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// 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/>. + +/** @file profile/unordered_base.h + * This file is a GNU profile extension to the Standard C++ Library. + */ + +#ifndef _GLIBCXX_PROFILE_UNORDERED +#define _GLIBCXX_PROFILE_UNORDERED 1 + +namespace std _GLIBCXX_VISIBILITY(default) +{ +namespace __profile +{ + template<typename _UnorderedCont, + typename _Value, bool _Cache_hash_code> + struct _Bucket_index_helper; + + template<typename _UnorderedCont, typename _Value> + struct _Bucket_index_helper<_UnorderedCont, _Value, true> + { + static std::size_t + bucket(const _UnorderedCont& __uc, + const __detail::_Hash_node<_Value, true>* __node) + { return __node->_M_hash_code % __uc.bucket_count(); } + }; + + template<typename _UnorderedCont, typename _Value> + struct _Bucket_index_helper<_UnorderedCont, _Value, false> + { + static std::size_t + bucket(const _UnorderedCont& __uc, + const __detail::_Hash_node<_Value, false>* __node) + { return __uc.bucket(__node->_M_v()); } + }; + + template<typename _UnorderedCont, typename _Key, typename _Mapped> + struct _Bucket_index_helper<_UnorderedCont, + std::pair<const _Key, _Mapped>, false> + { + typedef std::pair<const _Key, _Mapped> _Value; + + static std::size_t + bucket(const _UnorderedCont& __uc, + const __detail::_Hash_node<_Value, false>* __node) + { return __uc.bucket(__node->_M_v().first); } + }; + + template<typename _UnorderedCont, typename _Value, bool _Cache_hash_code> + std::size_t + __get_bucket_index(const _UnorderedCont& __uc, + const __detail::_Hash_node<_Value, _Cache_hash_code>* __node) + { + using __bucket_index_helper + = _Bucket_index_helper<_UnorderedCont, _Value, _Cache_hash_code>; + return __bucket_index_helper::bucket(__uc, __node); + } + + template<typename _UnorderedCont, + typename _Value, bool _Cache_hash_code> + struct _Equal_helper; + + template<typename _UnorderedCont, typename _Value> + struct _Equal_helper<_UnorderedCont, _Value, true> + { + static std::size_t + are_equal(const _UnorderedCont& __uc, + const __detail::_Hash_node<_Value, true>* __lhs, + const __detail::_Hash_node<_Value, true>* __rhs) + { + return __lhs->_M_hash_code == __rhs->_M_hash_code + && __uc.key_eq()(__lhs->_M_v(), __rhs->_M_v()); + } + }; + + template<typename _UnorderedCont, + typename _Value> + struct _Equal_helper<_UnorderedCont, _Value, false> + { + static std::size_t + are_equal(const _UnorderedCont& __uc, + const __detail::_Hash_node<_Value, false>* __lhs, + const __detail::_Hash_node<_Value, false>* __rhs) + { return __uc.key_eq()(__lhs->_M_v(), __rhs->_M_v()); } + }; + + template<typename _UnorderedCont, + typename _Key, typename _Mapped> + struct _Equal_helper<_UnorderedCont, std::pair<const _Key, _Mapped>, true> + { + typedef std::pair<const _Key, _Mapped> _Value; + + static std::size_t + are_equal(const _UnorderedCont& __uc, + const __detail::_Hash_node<_Value, true>* __lhs, + const __detail::_Hash_node<_Value, true>* __rhs) + { + return __lhs->_M_hash_code == __rhs->_M_hash_code + && __uc.key_eq()(__lhs->_M_v().first, __rhs->_M_v().first); + } + }; + + template<typename _UnorderedCont, + typename _Key, typename _Mapped> + struct _Equal_helper<_UnorderedCont, std::pair<const _Key, _Mapped>, false> + { + typedef std::pair<const _Key, _Mapped> _Value; + + static std::size_t + are_equal(const _UnorderedCont& __uc, + const __detail::_Hash_node<_Value, false>* __lhs, + const __detail::_Hash_node<_Value, false>* __rhs) + { return __uc.key_eq()(__lhs->_M_v().first, __rhs->_M_v().first); } + }; + + template<typename _UnorderedCont, typename _Value, bool _Cache_hash_code> + bool + __are_equal(const _UnorderedCont& __uc, + const __detail::_Hash_node<_Value, _Cache_hash_code>* __lhs, + const __detail::_Hash_node<_Value, _Cache_hash_code>* __rhs) + { + using __equal_helper + = _Equal_helper<_UnorderedCont, _Value, _Cache_hash_code>; + return __equal_helper::are_equal(__uc, __lhs, __rhs); + } + + template<typename _UnorderedCont, bool _Unique_keys> + class _Unordered_profile + { + _UnorderedCont& + _M_conjure() + { return *(static_cast<_UnorderedCont*>(this)); } + + using __unique_keys = std::integral_constant<bool, _Unique_keys>; + + protected: + _Unordered_profile() + { + auto& __uc = _M_conjure(); + __profcxx_hashtable_construct(&__uc, __uc.bucket_count()); + __profcxx_hashtable_construct2(&__uc); + } + _Unordered_profile(const _Unordered_profile&) + : _Unordered_profile() { } + _Unordered_profile(_Unordered_profile&&) + : _Unordered_profile() { } + + ~_Unordered_profile() noexcept + { + auto& __uc = _M_conjure(); + __profcxx_hashtable_destruct(&__uc, __uc.bucket_count(), __uc.size()); + _M_profile_destruct(); + } + + _Unordered_profile& + operator=(const _Unordered_profile&) = default; + + _Unordered_profile& + operator=(_Unordered_profile&&) = default; + + void + _M_profile_destruct() + { + if (!__profcxx_inefficient_hash_is_on()) + return; + + _M_profile_destruct(__unique_keys()); + } + + private: + void + _M_profile_destruct(std::true_type); + + void + _M_profile_destruct(std::false_type); + }; + + template<typename _UnorderedCont, bool _Unique_keys> + void + _Unordered_profile<_UnorderedCont, _Unique_keys>:: + _M_profile_destruct(std::true_type) + { + auto& __uc = _M_conjure(); + std::size_t __hops = 0, __lc = 0, __chain = 0; + auto __it = __uc.begin(); + while (__it != __uc.end()) + { + auto __bkt = __get_bucket_index(__uc, __it._M_cur); + auto __lit = __uc.begin(__bkt); + auto __lend = __uc.end(__bkt); + for (++__it, ++__lit; __lit != __lend; ++__it, ++__lit) + ++__chain; + if (__chain) + { + ++__chain; + __lc = __lc > __chain ? __lc : __chain; + __hops += __chain * (__chain - 1) / 2; + __chain = 0; + } + } + __profcxx_hashtable_destruct2(&__uc, __lc, __uc.size(), __hops); + } + + template<typename _UnorderedCont, bool _Unique_keys> + void + _Unordered_profile<_UnorderedCont, _Unique_keys>:: + _M_profile_destruct(std::false_type) + { + auto& __uc = _M_conjure(); + std::size_t __hops = 0, __lc = 0, __chain = 0, __unique_size = 0; + auto __it = __uc.begin(); + while (__it != __uc.end()) + { + auto __bkt = __get_bucket_index(__uc, __it._M_cur); + auto __lit = __uc.begin(__bkt); + auto __lend = __uc.end(__bkt); + auto __pit = __it; + ++__unique_size; + for (++__it, ++__lit; __lit != __lend; ++__it, ++__lit) + { + if (!__are_equal(__uc, __pit._M_cur, __it._M_cur)) + { + ++__chain; + ++__unique_size; + __pit = __it; + } + } + if (__chain) + { + ++__chain; + __lc = __lc > __chain ? __lc : __chain; + __hops += __chain * (__chain - 1) / 2; + __chain = 0; + } + } + __profcxx_hashtable_destruct2(&__uc, __lc, __unique_size, __hops); + } + +} // namespace __profile +} // namespace std + +#endif diff --git a/libstdc++-v3/include/profile/unordered_map b/libstdc++-v3/include/profile/unordered_map index f594ab8752c..ac5fecc60fa 100644 --- a/libstdc++-v3/include/profile/unordered_map +++ b/libstdc++-v3/include/profile/unordered_map @@ -34,6 +34,7 @@ # include <unordered_map> #include <profile/base.h> +#include <profile/unordered_base.h> #define _GLIBCXX_BASE unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc> #define _GLIBCXX_STD_BASE _GLIBCXX_STD_C::_GLIBCXX_BASE @@ -48,10 +49,18 @@ namespace __profile typename _Pred = std::equal_to<_Key>, typename _Alloc = std::allocator<std::pair<const _Key, _Tp> > > class unordered_map - : public _GLIBCXX_STD_BASE + : public _GLIBCXX_STD_BASE, + public _Unordered_profile<unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>, + true> { typedef typename _GLIBCXX_STD_BASE _Base; + _Base& + _M_base() noexcept { return *this; } + + const _Base& + _M_base() const noexcept { return *this; } + public: typedef typename _Base::size_type size_type; typedef typename _Base::hasher hasher; @@ -72,11 +81,8 @@ namespace __profile const hasher& __hf = hasher(), const key_equal& __eql = key_equal(), const allocator_type& __a = allocator_type()) - : _Base(__n, __hf, __eql, __a) - { - __profcxx_hashtable_construct(this, _Base::bucket_count()); - __profcxx_hashtable_construct2(this); - } + : _Base(__n, __hf, __eql, __a) + { } template<typename _InputIterator> unordered_map(_InputIterator __f, _InputIterator __l, @@ -84,85 +90,60 @@ namespace __profile const hasher& __hf = hasher(), const key_equal& __eql = key_equal(), const allocator_type& __a = allocator_type()) - : _Base(__f, __l, __n, __hf, __eql, __a) - { - __profcxx_hashtable_construct(this, _Base::bucket_count()); - __profcxx_hashtable_construct2(this); - } + : _Base(__f, __l, __n, __hf, __eql, __a) + { } - unordered_map(const unordered_map& __x) - : _Base(__x) - { - __profcxx_hashtable_construct(this, _Base::bucket_count()); - __profcxx_hashtable_construct2(this); - } + unordered_map(const unordered_map&) = default; unordered_map(const _Base& __x) - : _Base(__x) - { - __profcxx_hashtable_construct(this, _Base::bucket_count()); - __profcxx_hashtable_construct2(this); - } + : _Base(__x) + { } - unordered_map(unordered_map&& __x) - : _Base(std::move(__x)) - { - __profcxx_hashtable_construct(this, _Base::bucket_count()); - __profcxx_hashtable_construct2(this); - } + unordered_map(unordered_map&&) = default; + + explicit + unordered_map(const allocator_type& __a) + : _Base(__a) + { } + + unordered_map(const unordered_map& __umap, + const allocator_type& __a) + : _Base(__umap, __a) + { } + + unordered_map(unordered_map&& __umap, + const allocator_type& __a) + : _Base(std::move(__umap._M_base()), __a) + { } unordered_map(initializer_list<value_type> __l, size_type __n = 0, const hasher& __hf = hasher(), const key_equal& __eql = key_equal(), const allocator_type& __a = allocator_type()) - : _Base(__l, __n, __hf, __eql, __a) { } + : _Base(__l, __n, __hf, __eql, __a) + { } unordered_map& - operator=(const unordered_map& __x) - { - *static_cast<_Base*>(this) = __x; - return *this; - } + operator=(const unordered_map&) = default; unordered_map& - operator=(unordered_map&& __x) - { - // NB: DR 1204. - // NB: DR 675. - this->clear(); - this->swap(__x); - return *this; - } + operator=(unordered_map&&) = default; unordered_map& operator=(initializer_list<value_type> __l) { - this->clear(); - this->insert(__l); + _M_base() = __l; return *this; } - ~unordered_map() noexcept - { - __profcxx_hashtable_destruct(this, _Base::bucket_count(), - _Base::size()); - _M_profile_destruct(); - } - - _Base& - _M_base() noexcept { return *this; } - - const _Base& - _M_base() const noexcept { return *this; } - void clear() noexcept { __profcxx_hashtable_destruct(this, _Base::bucket_count(), _Base::size()); - _M_profile_destruct(); - _Base::clear(); + this->_M_profile_destruct(); + _Base::clear(); } template<typename... _Args> @@ -247,14 +228,6 @@ namespace __profile _M_profile_resize(__old_size); } - void - insert(const value_type* __first, const value_type* __last) - { - size_type __old_size = _Base::bucket_count(); - _Base::insert(__first, __last); - _M_profile_resize(__old_size); - } - // operator[] mapped_type& operator[](const _Key& __k) @@ -276,7 +249,8 @@ namespace __profile void swap(unordered_map& __x) - { _Base::swap(__x); } + noexcept( noexcept(__x._M_base().swap(__x)) ) + { _Base::swap(__x._M_base()); } void rehash(size_type __n) { @@ -293,29 +267,6 @@ namespace __profile if (__old_size != __new_size) __profcxx_hashtable_resize(this, __old_size, __new_size); } - - void - _M_profile_destruct() - { - size_type __hops = 0, __lc = 0, __chain = 0; - iterator __it = this->begin(); - while (__it != this->end()) - { - size_type __bkt = this->bucket(__it->first); - auto __lit = this->begin(__bkt); - auto __lend = this->end(__bkt); - for (++__it, ++__lit; __lit != __lend; ++__it, ++__lit) - ++__chain; - if (__chain) - { - ++__chain; - __lc = __lc > __chain ? __lc : __chain; - __hops += __chain * (__chain - 1) / 2; - __chain = 0; - } - } - __profcxx_hashtable_destruct2(this, __lc, _Base::size(), __hops); - } }; template<typename _Key, typename _Tp, typename _Hash, @@ -350,10 +301,19 @@ namespace __profile typename _Pred = std::equal_to<_Key>, typename _Alloc = std::allocator<std::pair<const _Key, _Tp> > > class unordered_multimap - : public _GLIBCXX_STD_BASE + : public _GLIBCXX_STD_BASE, + public _Unordered_profile<unordered_multimap<_Key, _Tp, + _Hash, _Pred, _Alloc>, + false> { typedef typename _GLIBCXX_STD_BASE _Base; + _Base& + _M_base() noexcept { return *this; } + + const _Base& + _M_base() const noexcept { return *this; } + public: typedef typename _Base::size_type size_type; typedef typename _Base::hasher hasher; @@ -373,85 +333,69 @@ namespace __profile const hasher& __hf = hasher(), const key_equal& __eql = key_equal(), const allocator_type& __a = allocator_type()) - : _Base(__n, __hf, __eql, __a) - { - __profcxx_hashtable_construct(this, _Base::bucket_count()); - } + : _Base(__n, __hf, __eql, __a) + { } + template<typename _InputIterator> unordered_multimap(_InputIterator __f, _InputIterator __l, size_type __n = 0, const hasher& __hf = hasher(), const key_equal& __eql = key_equal(), const allocator_type& __a = allocator_type()) - : _Base(__f, __l, __n, __hf, __eql, __a) - { - __profcxx_hashtable_construct(this, _Base::bucket_count()); - } + : _Base(__f, __l, __n, __hf, __eql, __a) + { } - unordered_multimap(const unordered_multimap& __x) - : _Base(__x) - { - __profcxx_hashtable_construct(this, _Base::bucket_count()); - } + unordered_multimap(const unordered_multimap&) = default; unordered_multimap(const _Base& __x) - : _Base(__x) - { - __profcxx_hashtable_construct(this, _Base::bucket_count()); - } + : _Base(__x) + { } - unordered_multimap(unordered_multimap&& __x) - : _Base(std::move(__x)) - { - __profcxx_hashtable_construct(this, _Base::bucket_count()); - } + unordered_multimap(unordered_multimap&&) = default; + + explicit + unordered_multimap(const allocator_type& __a) + : _Base(__a) + { } + + unordered_multimap(const unordered_multimap& __ummap, + const allocator_type& __a) + : _Base(__ummap._M_base(), __a) + { } + + unordered_multimap(unordered_multimap&& __ummap, + const allocator_type& __a) + : _Base(std::move(__ummap._M_base()), __a) + { } unordered_multimap(initializer_list<value_type> __l, size_type __n = 0, const hasher& __hf = hasher(), const key_equal& __eql = key_equal(), const allocator_type& __a = allocator_type()) - : _Base(__l, __n, __hf, __eql, __a) { } + : _Base(__l, __n, __hf, __eql, __a) + { } unordered_multimap& - operator=(const unordered_multimap& __x) - { - *static_cast<_Base*>(this) = __x; - return *this; - } + operator=(const unordered_multimap&) = default; unordered_multimap& - operator=(unordered_multimap&& __x) - { - // NB: DR 1204. - // NB: DR 675. - this->clear(); - this->swap(__x); - return *this; - } + operator=(unordered_multimap&&) = default; unordered_multimap& operator=(initializer_list<value_type> __l) { - this->clear(); - this->insert(__l); + _M_base() = __l; return *this; } - ~unordered_multimap() noexcept - { - __profcxx_hashtable_destruct(this, _Base::bucket_count(), - _Base::size()); - _M_profile_destruct(); - } - void clear() noexcept { - __profcxx_hashtable_destruct(this, _Base::bucket_count(), + __profcxx_hashtable_destruct(this, _Base::bucket_count(), _Base::size()); - _M_profile_destruct(); - _Base::clear(); + this->_M_profile_destruct(); + _Base::clear(); } template<typename... _Args> @@ -536,18 +480,12 @@ namespace __profile } void - insert(const value_type* __first, const value_type* __last) - { - size_type __old_size = _Base::bucket_count(); - _Base::insert(__first, __last); - _M_profile_resize(__old_size); - } - - void swap(unordered_multimap& __x) - { _Base::swap(__x); } + noexcept( noexcept(__x._M_base().swap(__x)) ) + { _Base::swap(__x._M_base()); } - void rehash(size_type __n) + void + rehash(size_type __n) { size_type __old_size = _Base::bucket_count(); _Base::rehash(__n); @@ -562,29 +500,6 @@ namespace __profile if (__old_size != __new_size) __profcxx_hashtable_resize(this, __old_size, __new_size); } - - void - _M_profile_destruct() - { - size_type __hops = 0, __lc = 0, __chain = 0; - iterator __it = this->begin(); - while (__it != this->end()) - { - size_type __bkt = this->bucket(__it->first); - auto __lit = this->begin(__bkt); - auto __lend = this->end(__bkt); - for (++__it, ++__lit; __lit != __lend; ++__it, ++__lit) - ++__chain; - if (__chain) - { - ++__chain; - __lc = __lc > __chain ? __lc : __chain; - __hops += __chain * (__chain - 1) / 2; - __chain = 0; - } - } - __profcxx_hashtable_destruct2(this, __lc, _Base::size(), __hops); - } }; template<typename _Key, typename _Tp, typename _Hash, diff --git a/libstdc++-v3/include/profile/unordered_set b/libstdc++-v3/include/profile/unordered_set index 737b6ec6b96..f6bcda7d4d1 100644 --- a/libstdc++-v3/include/profile/unordered_set +++ b/libstdc++-v3/include/profile/unordered_set @@ -34,6 +34,7 @@ # include <unordered_set> #include <profile/base.h> +#include <profile/unordered_base.h> #define _GLIBCXX_BASE unordered_set<_Key, _Hash, _Pred, _Alloc> #define _GLIBCXX_STD_BASE _GLIBCXX_STD_C::_GLIBCXX_BASE @@ -44,14 +45,22 @@ namespace __profile { /** @brief Unordered_set wrapper with performance instrumentation. */ template<typename _Key, - typename _Hash = std::hash<_Key>, + typename _Hash = std::hash<_Key>, typename _Pred = std::equal_to<_Key>, typename _Alloc = std::allocator<_Key> > class unordered_set - : public _GLIBCXX_STD_BASE + : public _GLIBCXX_STD_BASE, + public _Unordered_profile<unordered_set<_Key, _Hash, _Pred, _Alloc>, + true> { typedef _GLIBCXX_STD_BASE _Base; + _Base& + _M_base() noexcept { return *this; } + + const _Base& + _M_base() const noexcept { return *this; } + public: typedef typename _Base::size_type size_type; typedef typename _Base::hasher hasher; @@ -71,11 +80,8 @@ namespace __profile const hasher& __hf = hasher(), const key_equal& __eql = key_equal(), const allocator_type& __a = allocator_type()) - : _Base(__n, __hf, __eql, __a) - { - __profcxx_hashtable_construct(this, _Base::bucket_count()); - __profcxx_hashtable_construct2(this); - } + : _Base(__n, __hf, __eql, __a) + { } template<typename _InputIterator> unordered_set(_InputIterator __f, _InputIterator __l, @@ -83,84 +89,64 @@ namespace __profile const hasher& __hf = hasher(), const key_equal& __eql = key_equal(), const allocator_type& __a = allocator_type()) - : _Base(__f, __l, __n, __hf, __eql, __a) - { - __profcxx_hashtable_construct(this, _Base::bucket_count()); - __profcxx_hashtable_construct2(this); - } + : _Base(__f, __l, __n, __hf, __eql, __a) + { } - unordered_set(const unordered_set& __x) - : _Base(__x) - { - __profcxx_hashtable_construct(this, _Base::bucket_count()); - __profcxx_hashtable_construct2(this); - } + unordered_set(const unordered_set&) = default; unordered_set(const _Base& __x) - : _Base(__x) - { - __profcxx_hashtable_construct(this, _Base::bucket_count()); - __profcxx_hashtable_construct2(this); - } + : _Base(__x) + { } - unordered_set(unordered_set&& __x) - : _Base(std::move(__x)) - { - __profcxx_hashtable_construct(this, _Base::bucket_count()); - __profcxx_hashtable_construct2(this); - } + unordered_set(unordered_set&&) = default; + + explicit + unordered_set(const allocator_type& __a) + : _Base(__a) + { } + + unordered_set(const unordered_set& __uset, + const allocator_type& __a) + : _Base(__uset._M_base(), __a) + { } + + unordered_set(unordered_set&& __uset, + const allocator_type& __a) + : _Base(std::move(__uset._M_base()), __a) + { } unordered_set(initializer_list<value_type> __l, size_type __n = 0, const hasher& __hf = hasher(), const key_equal& __eql = key_equal(), const allocator_type& __a = allocator_type()) - : _Base(__l, __n, __hf, __eql, __a) { } + : _Base(__l, __n, __hf, __eql, __a) + { } unordered_set& - operator=(const unordered_set& __x) - { - *static_cast<_Base*>(this) = __x; - return *this; - } + operator=(const unordered_set&) = default; unordered_set& - operator=(unordered_set&& __x) - { - // NB: DR 1204. - // NB: DR 675. - this->clear(); - this->swap(__x); - return *this; - } + operator=(unordered_set&&) = default; unordered_set& operator=(initializer_list<value_type> __l) { - this->clear(); - this->insert(__l); + _M_base() = __l; return *this; } - ~unordered_set() noexcept - { - __profcxx_hashtable_destruct(this, _Base::bucket_count(), - _Base::size()); - _M_profile_destruct(); - } - void swap(unordered_set& __x) - { - _Base::swap(__x); - } + noexcept( noexcept(__x._M_base().swap(__x)) ) + { _Base::swap(__x); } void clear() noexcept { __profcxx_hashtable_destruct(this, _Base::bucket_count(), _Base::size()); - _M_profile_destruct(); + this->_M_profile_destruct(); _Base::clear(); } @@ -240,14 +226,7 @@ namespace __profile } void - insert(const value_type* __first, const value_type* __last) - { - size_type __old_size = _Base::bucket_count(); - _Base::insert(__first, __last); - _M_profile_resize(__old_size); - } - - void rehash(size_type __n) + rehash(size_type __n) { size_type __old_size = _Base::bucket_count(); _Base::rehash(__n); @@ -262,29 +241,6 @@ namespace __profile if (__old_size != __new_size) __profcxx_hashtable_resize(this, __old_size, __new_size); } - - void - _M_profile_destruct() - { - size_type __hops = 0, __lc = 0, __chain = 0; - iterator __it = this->begin(); - while (__it != this->end()) - { - size_type __bkt = this->bucket(*__it); - auto __lit = this->begin(__bkt); - auto __lend = this->end(__bkt); - for (++__it, ++__lit; __lit != __lend; ++__it, ++__lit) - ++__chain; - if (__chain) - { - ++__chain; - __lc = __lc > __chain ? __lc : __chain; - __hops += __chain * (__chain - 1) / 2; - __chain = 0; - } - } - __profcxx_hashtable_destruct2(this, __lc, _Base::size(), __hops); - } }; template<typename _Key, typename _Hash, typename _Pred, typename _Alloc> @@ -312,14 +268,23 @@ namespace __profile /** @brief Unordered_multiset wrapper with performance instrumentation. */ template<typename _Value, - typename _Hash = std::hash<_Value>, - typename _Pred = std::equal_to<_Value>, - typename _Alloc = std::allocator<_Value> > + typename _Hash = std::hash<_Value>, + typename _Pred = std::equal_to<_Value>, + typename _Alloc = std::allocator<_Value> > class unordered_multiset - : public _GLIBCXX_STD_BASE + : public _GLIBCXX_STD_BASE, + public _Unordered_profile<unordered_multiset<_Value, + _Hash, _Pred, _Alloc>, + false> { typedef _GLIBCXX_STD_BASE _Base; + _Base& + _M_base() noexcept { return *this; } + + const _Base& + _M_base() const noexcept { return *this; } + public: typedef typename _Base::size_type size_type; typedef typename _Base::hasher hasher; @@ -339,10 +304,8 @@ namespace __profile const hasher& __hf = hasher(), const key_equal& __eql = key_equal(), const allocator_type& __a = allocator_type()) - : _Base(__n, __hf, __eql, __a) - { - __profcxx_hashtable_construct(this, _Base::bucket_count()); - } + : _Base(__n, __hf, __eql, __a) + { } template<typename _InputIterator> unordered_multiset(_InputIterator __f, _InputIterator __l, @@ -350,80 +313,64 @@ namespace __profile const hasher& __hf = hasher(), const key_equal& __eql = key_equal(), const allocator_type& __a = allocator_type()) - : _Base(__f, __l, __n, __hf, __eql, __a) - { - __profcxx_hashtable_construct(this, _Base::bucket_count()); - } + : _Base(__f, __l, __n, __hf, __eql, __a) + { } - unordered_multiset(const unordered_multiset& __x) - : _Base(__x) - { - __profcxx_hashtable_construct(this, _Base::bucket_count()); - } + unordered_multiset(const unordered_multiset&) = default; unordered_multiset(const _Base& __x) - : _Base(__x) - { - __profcxx_hashtable_construct(this, _Base::bucket_count()); - } + : _Base(__x) + { } - unordered_multiset(unordered_multiset&& __x) - : _Base(std::move(__x)) - { - __profcxx_hashtable_construct(this, _Base::bucket_count()); - } + unordered_multiset(unordered_multiset&&) = default; + + explicit + unordered_multiset(const allocator_type& __a) + : _Base(__a) + { } + + unordered_multiset(const unordered_multiset& __umset, + const allocator_type& __a) + : _Base(__umset._M_base(), __a) + { } + + unordered_multiset(unordered_multiset&& __umset, + const allocator_type& __a) + : _Base(std::move(__umset._M_base()), __a) + { } unordered_multiset(initializer_list<value_type> __l, size_type __n = 0, const hasher& __hf = hasher(), const key_equal& __eql = key_equal(), const allocator_type& __a = allocator_type()) - : _Base(__l, __n, __hf, __eql, __a) { } + : _Base(__l, __n, __hf, __eql, __a) + { } unordered_multiset& - operator=(const unordered_multiset& __x) - { - *static_cast<_Base*>(this) = __x; - return *this; - } + operator=(const unordered_multiset&) = default; unordered_multiset& - operator=(unordered_multiset&& __x) - { - // NB: DR 1204. - // NB: DR 675. - this->clear(); - this->swap(__x); - return *this; - } + operator=(unordered_multiset&&) = default; unordered_multiset& operator=(initializer_list<value_type> __l) { - this->clear(); - this->insert(__l); + _M_base() = __l; return *this; } - ~unordered_multiset() noexcept - { - __profcxx_hashtable_destruct(this, _Base::bucket_count(), - _Base::size()); - _M_profile_destruct(); - } - void swap(unordered_multiset& __x) - { - _Base::swap(__x); - } + noexcept( noexcept(__x._M_base().swap(__x)) ) + { _Base::swap(__x); } void clear() noexcept { __profcxx_hashtable_destruct(this, _Base::bucket_count(), _Base::size()); - _M_profile_destruct(); + this->_M_profile_destruct(); _Base::clear(); } @@ -502,14 +449,7 @@ namespace __profile } void - insert(const value_type* __first, const value_type* __last) - { - size_type __old_size = _Base::bucket_count(); - _Base::insert(__first, __last); - _M_profile_resize(__old_size); - } - - void rehash(size_type __n) + rehash(size_type __n) { size_type __old_size = _Base::bucket_count(); _Base::rehash(__n); @@ -524,29 +464,6 @@ namespace __profile if (__old_size != __new_size) __profcxx_hashtable_resize(this, __old_size, __new_size); } - - void - _M_profile_destruct() - { - size_type __hops = 0, __lc = 0, __chain = 0; - iterator __it = this->begin(); - while (__it != this->end()) - { - size_type __bkt = this->bucket(*__it); - auto __lit = this->begin(__bkt); - auto __lend = this->end(__bkt); - for (++__it, ++__lit; __lit != __lend; ++__it, ++__lit) - ++__chain; - if (__chain) - { - ++__chain; - __lc = __lc > __chain ? __lc : __chain; - __hops += __chain * (__chain - 1) / 2; - __chain = 0; - } - } - __profcxx_hashtable_destruct2(this, __lc, _Base::size(), __hops); - } }; template<typename _Value, typename _Hash, typename _Pred, typename _Alloc> |