Commit 703f140f by François Dumont

unordered_base.h: New.

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.

From-SVN: r198698
parent 4ffecb1f
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.
2013-05-02 Paolo Carlini <paolo.carlini@oracle.com> 2013-05-02 Paolo Carlini <paolo.carlini@oracle.com>
* testsuite/tr1/4_metaprogramming/integral_constant/requirements/ * testsuite/tr1/4_metaprogramming/integral_constant/requirements/
......
...@@ -788,6 +788,7 @@ profile_builddir = ./profile ...@@ -788,6 +788,7 @@ profile_builddir = ./profile
profile_headers = \ profile_headers = \
${profile_srcdir}/array \ ${profile_srcdir}/array \
${profile_srcdir}/base.h \ ${profile_srcdir}/base.h \
${profile_srcdir}/unordered_base.h \
${profile_srcdir}/unordered_map \ ${profile_srcdir}/unordered_map \
${profile_srcdir}/unordered_set \ ${profile_srcdir}/unordered_set \
${profile_srcdir}/vector \ ${profile_srcdir}/vector \
......
...@@ -1045,6 +1045,7 @@ profile_builddir = ./profile ...@@ -1045,6 +1045,7 @@ profile_builddir = ./profile
profile_headers = \ profile_headers = \
${profile_srcdir}/array \ ${profile_srcdir}/array \
${profile_srcdir}/base.h \ ${profile_srcdir}/base.h \
${profile_srcdir}/unordered_base.h \
${profile_srcdir}/unordered_map \ ${profile_srcdir}/unordered_map \
${profile_srcdir}/unordered_set \ ${profile_srcdir}/unordered_set \
${profile_srcdir}/vector \ ${profile_srcdir}/vector \
......
...@@ -188,7 +188,7 @@ namespace __gnu_profile ...@@ -188,7 +188,7 @@ namespace __gnu_profile
_GLIBCXX_PROFILE_REENTRANCE_GUARD(__gnu_profile::__is_invalid()) _GLIBCXX_PROFILE_REENTRANCE_GUARD(__gnu_profile::__is_invalid())
#define __profcxx_is_on() \ #define __profcxx_is_on() \
_GLIBCXX_PROFILE_REENTRANCE_GUARD(__gnu_profile::__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()) _GLIBCXX_PROFILE_REENTRANCE_GUARD(__gnu_profile::__is_off())
#else #else
#define __profcxx_report() #define __profcxx_report()
...@@ -237,6 +237,8 @@ namespace __gnu_profile ...@@ -237,6 +237,8 @@ namespace __gnu_profile
// Turn on/off instrumentation for INEFFICIENT_HASH. // Turn on/off instrumentation for INEFFICIENT_HASH.
#if defined(_GLIBCXX_PROFILE_INEFFICIENT_HASH) #if defined(_GLIBCXX_PROFILE_INEFFICIENT_HASH)
#define __profcxx_inefficient_hash_is_on() \
__gnu_profile::__is_on()
#define __profcxx_hashtable_construct2(__x...) \ #define __profcxx_hashtable_construct2(__x...) \
_GLIBCXX_PROFILE_REENTRANCE_GUARD( \ _GLIBCXX_PROFILE_REENTRANCE_GUARD( \
__gnu_profile::__trace_hash_func_construct(__x)) __gnu_profile::__trace_hash_func_construct(__x))
...@@ -244,6 +246,7 @@ namespace __gnu_profile ...@@ -244,6 +246,7 @@ namespace __gnu_profile
_GLIBCXX_PROFILE_REENTRANCE_GUARD( \ _GLIBCXX_PROFILE_REENTRANCE_GUARD( \
__gnu_profile::__trace_hash_func_destruct(__x)) __gnu_profile::__trace_hash_func_destruct(__x))
#else #else
#define __profcxx_inefficient_hash_is_on() false
#define __profcxx_hashtable_destruct2(__x...) #define __profcxx_hashtable_destruct2(__x...)
#define __profcxx_hashtable_construct2(__x...) #define __profcxx_hashtable_construct2(__x...)
#endif #endif
......
// 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
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
# include <unordered_map> # include <unordered_map>
#include <profile/base.h> #include <profile/base.h>
#include <profile/unordered_base.h>
#define _GLIBCXX_BASE unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc> #define _GLIBCXX_BASE unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>
#define _GLIBCXX_STD_BASE _GLIBCXX_STD_C::_GLIBCXX_BASE #define _GLIBCXX_STD_BASE _GLIBCXX_STD_C::_GLIBCXX_BASE
...@@ -48,10 +49,18 @@ namespace __profile ...@@ -48,10 +49,18 @@ namespace __profile
typename _Pred = std::equal_to<_Key>, typename _Pred = std::equal_to<_Key>,
typename _Alloc = std::allocator<std::pair<const _Key, _Tp> > > typename _Alloc = std::allocator<std::pair<const _Key, _Tp> > >
class unordered_map 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; typedef typename _GLIBCXX_STD_BASE _Base;
_Base&
_M_base() noexcept { return *this; }
const _Base&
_M_base() const noexcept { return *this; }
public: public:
typedef typename _Base::size_type size_type; typedef typename _Base::size_type size_type;
typedef typename _Base::hasher hasher; typedef typename _Base::hasher hasher;
...@@ -73,10 +82,7 @@ namespace __profile ...@@ -73,10 +82,7 @@ namespace __profile
const key_equal& __eql = key_equal(), const key_equal& __eql = key_equal(),
const allocator_type& __a = allocator_type()) const allocator_type& __a = allocator_type())
: _Base(__n, __hf, __eql, __a) : _Base(__n, __hf, __eql, __a)
{ { }
__profcxx_hashtable_construct(this, _Base::bucket_count());
__profcxx_hashtable_construct2(this);
}
template<typename _InputIterator> template<typename _InputIterator>
unordered_map(_InputIterator __f, _InputIterator __l, unordered_map(_InputIterator __f, _InputIterator __l,
...@@ -85,83 +91,58 @@ namespace __profile ...@@ -85,83 +91,58 @@ namespace __profile
const key_equal& __eql = key_equal(), const key_equal& __eql = key_equal(),
const allocator_type& __a = allocator_type()) const allocator_type& __a = allocator_type())
: _Base(__f, __l, __n, __hf, __eql, __a) : _Base(__f, __l, __n, __hf, __eql, __a)
{ { }
__profcxx_hashtable_construct(this, _Base::bucket_count());
__profcxx_hashtable_construct2(this);
}
unordered_map(const unordered_map& __x) unordered_map(const unordered_map&) = default;
: _Base(__x)
{
__profcxx_hashtable_construct(this, _Base::bucket_count());
__profcxx_hashtable_construct2(this);
}
unordered_map(const _Base& __x) unordered_map(const _Base& __x)
: _Base(__x) : _Base(__x)
{ { }
__profcxx_hashtable_construct(this, _Base::bucket_count());
__profcxx_hashtable_construct2(this);
}
unordered_map(unordered_map&& __x) unordered_map(unordered_map&&) = default;
: _Base(std::move(__x))
{ explicit
__profcxx_hashtable_construct(this, _Base::bucket_count()); unordered_map(const allocator_type& __a)
__profcxx_hashtable_construct2(this); : _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, unordered_map(initializer_list<value_type> __l,
size_type __n = 0, size_type __n = 0,
const hasher& __hf = hasher(), const hasher& __hf = hasher(),
const key_equal& __eql = key_equal(), const key_equal& __eql = key_equal(),
const allocator_type& __a = allocator_type()) const allocator_type& __a = allocator_type())
: _Base(__l, __n, __hf, __eql, __a) { } : _Base(__l, __n, __hf, __eql, __a)
{ }
unordered_map& unordered_map&
operator=(const unordered_map& __x) operator=(const unordered_map&) = default;
{
*static_cast<_Base*>(this) = __x;
return *this;
}
unordered_map& unordered_map&
operator=(unordered_map&& __x) operator=(unordered_map&&) = default;
{
// NB: DR 1204.
// NB: DR 675.
this->clear();
this->swap(__x);
return *this;
}
unordered_map& unordered_map&
operator=(initializer_list<value_type> __l) operator=(initializer_list<value_type> __l)
{ {
this->clear(); _M_base() = __l;
this->insert(__l);
return *this; 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 void
clear() noexcept clear() noexcept
{ {
__profcxx_hashtable_destruct(this, _Base::bucket_count(), __profcxx_hashtable_destruct(this, _Base::bucket_count(),
_Base::size()); _Base::size());
_M_profile_destruct(); this->_M_profile_destruct();
_Base::clear(); _Base::clear();
} }
...@@ -247,14 +228,6 @@ namespace __profile ...@@ -247,14 +228,6 @@ namespace __profile
_M_profile_resize(__old_size); _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[] // operator[]
mapped_type& mapped_type&
operator[](const _Key& __k) operator[](const _Key& __k)
...@@ -276,7 +249,8 @@ namespace __profile ...@@ -276,7 +249,8 @@ namespace __profile
void void
swap(unordered_map& __x) swap(unordered_map& __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)
{ {
...@@ -293,29 +267,6 @@ namespace __profile ...@@ -293,29 +267,6 @@ namespace __profile
if (__old_size != __new_size) if (__old_size != __new_size)
__profcxx_hashtable_resize(this, __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, template<typename _Key, typename _Tp, typename _Hash,
...@@ -350,10 +301,19 @@ namespace __profile ...@@ -350,10 +301,19 @@ namespace __profile
typename _Pred = std::equal_to<_Key>, typename _Pred = std::equal_to<_Key>,
typename _Alloc = std::allocator<std::pair<const _Key, _Tp> > > typename _Alloc = std::allocator<std::pair<const _Key, _Tp> > >
class unordered_multimap 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; typedef typename _GLIBCXX_STD_BASE _Base;
_Base&
_M_base() noexcept { return *this; }
const _Base&
_M_base() const noexcept { return *this; }
public: public:
typedef typename _Base::size_type size_type; typedef typename _Base::size_type size_type;
typedef typename _Base::hasher hasher; typedef typename _Base::hasher hasher;
...@@ -374,9 +334,8 @@ namespace __profile ...@@ -374,9 +334,8 @@ namespace __profile
const key_equal& __eql = key_equal(), const key_equal& __eql = key_equal(),
const allocator_type& __a = allocator_type()) const allocator_type& __a = allocator_type())
: _Base(__n, __hf, __eql, __a) : _Base(__n, __hf, __eql, __a)
{ { }
__profcxx_hashtable_construct(this, _Base::bucket_count());
}
template<typename _InputIterator> template<typename _InputIterator>
unordered_multimap(_InputIterator __f, _InputIterator __l, unordered_multimap(_InputIterator __f, _InputIterator __l,
size_type __n = 0, size_type __n = 0,
...@@ -384,73 +343,58 @@ namespace __profile ...@@ -384,73 +343,58 @@ namespace __profile
const key_equal& __eql = key_equal(), const key_equal& __eql = key_equal(),
const allocator_type& __a = allocator_type()) const allocator_type& __a = allocator_type())
: _Base(__f, __l, __n, __hf, __eql, __a) : _Base(__f, __l, __n, __hf, __eql, __a)
{ { }
__profcxx_hashtable_construct(this, _Base::bucket_count());
}
unordered_multimap(const unordered_multimap& __x) unordered_multimap(const unordered_multimap&) = default;
: _Base(__x)
{
__profcxx_hashtable_construct(this, _Base::bucket_count());
}
unordered_multimap(const _Base& __x) unordered_multimap(const _Base& __x)
: _Base(__x) : _Base(__x)
{ { }
__profcxx_hashtable_construct(this, _Base::bucket_count());
}
unordered_multimap(unordered_multimap&& __x) unordered_multimap(unordered_multimap&&) = default;
: _Base(std::move(__x))
{ explicit
__profcxx_hashtable_construct(this, _Base::bucket_count()); 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, unordered_multimap(initializer_list<value_type> __l,
size_type __n = 0, size_type __n = 0,
const hasher& __hf = hasher(), const hasher& __hf = hasher(),
const key_equal& __eql = key_equal(), const key_equal& __eql = key_equal(),
const allocator_type& __a = allocator_type()) const allocator_type& __a = allocator_type())
: _Base(__l, __n, __hf, __eql, __a) { } : _Base(__l, __n, __hf, __eql, __a)
{ }
unordered_multimap& unordered_multimap&
operator=(const unordered_multimap& __x) operator=(const unordered_multimap&) = default;
{
*static_cast<_Base*>(this) = __x;
return *this;
}
unordered_multimap& unordered_multimap&
operator=(unordered_multimap&& __x) operator=(unordered_multimap&&) = default;
{
// NB: DR 1204.
// NB: DR 675.
this->clear();
this->swap(__x);
return *this;
}
unordered_multimap& unordered_multimap&
operator=(initializer_list<value_type> __l) operator=(initializer_list<value_type> __l)
{ {
this->clear(); _M_base() = __l;
this->insert(__l);
return *this; return *this;
} }
~unordered_multimap() noexcept
{
__profcxx_hashtable_destruct(this, _Base::bucket_count(),
_Base::size());
_M_profile_destruct();
}
void void
clear() noexcept clear() noexcept
{ {
__profcxx_hashtable_destruct(this, _Base::bucket_count(), __profcxx_hashtable_destruct(this, _Base::bucket_count(),
_Base::size()); _Base::size());
_M_profile_destruct(); this->_M_profile_destruct();
_Base::clear(); _Base::clear();
} }
...@@ -536,18 +480,12 @@ namespace __profile ...@@ -536,18 +480,12 @@ namespace __profile
} }
void 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) 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(); size_type __old_size = _Base::bucket_count();
_Base::rehash(__n); _Base::rehash(__n);
...@@ -562,29 +500,6 @@ namespace __profile ...@@ -562,29 +500,6 @@ namespace __profile
if (__old_size != __new_size) if (__old_size != __new_size)
__profcxx_hashtable_resize(this, __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, template<typename _Key, typename _Tp, typename _Hash,
......
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
# include <unordered_set> # include <unordered_set>
#include <profile/base.h> #include <profile/base.h>
#include <profile/unordered_base.h>
#define _GLIBCXX_BASE unordered_set<_Key, _Hash, _Pred, _Alloc> #define _GLIBCXX_BASE unordered_set<_Key, _Hash, _Pred, _Alloc>
#define _GLIBCXX_STD_BASE _GLIBCXX_STD_C::_GLIBCXX_BASE #define _GLIBCXX_STD_BASE _GLIBCXX_STD_C::_GLIBCXX_BASE
...@@ -48,10 +49,18 @@ namespace __profile ...@@ -48,10 +49,18 @@ namespace __profile
typename _Pred = std::equal_to<_Key>, typename _Pred = std::equal_to<_Key>,
typename _Alloc = std::allocator<_Key> > typename _Alloc = std::allocator<_Key> >
class unordered_set 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; typedef _GLIBCXX_STD_BASE _Base;
_Base&
_M_base() noexcept { return *this; }
const _Base&
_M_base() const noexcept { return *this; }
public: public:
typedef typename _Base::size_type size_type; typedef typename _Base::size_type size_type;
typedef typename _Base::hasher hasher; typedef typename _Base::hasher hasher;
...@@ -72,10 +81,7 @@ namespace __profile ...@@ -72,10 +81,7 @@ namespace __profile
const key_equal& __eql = key_equal(), const key_equal& __eql = key_equal(),
const allocator_type& __a = allocator_type()) const allocator_type& __a = allocator_type())
: _Base(__n, __hf, __eql, __a) : _Base(__n, __hf, __eql, __a)
{ { }
__profcxx_hashtable_construct(this, _Base::bucket_count());
__profcxx_hashtable_construct2(this);
}
template<typename _InputIterator> template<typename _InputIterator>
unordered_set(_InputIterator __f, _InputIterator __l, unordered_set(_InputIterator __f, _InputIterator __l,
...@@ -84,83 +90,63 @@ namespace __profile ...@@ -84,83 +90,63 @@ namespace __profile
const key_equal& __eql = key_equal(), const key_equal& __eql = key_equal(),
const allocator_type& __a = allocator_type()) const allocator_type& __a = allocator_type())
: _Base(__f, __l, __n, __hf, __eql, __a) : _Base(__f, __l, __n, __hf, __eql, __a)
{ { }
__profcxx_hashtable_construct(this, _Base::bucket_count());
__profcxx_hashtable_construct2(this);
}
unordered_set(const unordered_set& __x) unordered_set(const unordered_set&) = default;
: _Base(__x)
{
__profcxx_hashtable_construct(this, _Base::bucket_count());
__profcxx_hashtable_construct2(this);
}
unordered_set(const _Base& __x) unordered_set(const _Base& __x)
: _Base(__x) : _Base(__x)
{ { }
__profcxx_hashtable_construct(this, _Base::bucket_count());
__profcxx_hashtable_construct2(this);
}
unordered_set(unordered_set&& __x) unordered_set(unordered_set&&) = default;
: _Base(std::move(__x))
{ explicit
__profcxx_hashtable_construct(this, _Base::bucket_count()); unordered_set(const allocator_type& __a)
__profcxx_hashtable_construct2(this); : _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, unordered_set(initializer_list<value_type> __l,
size_type __n = 0, size_type __n = 0,
const hasher& __hf = hasher(), const hasher& __hf = hasher(),
const key_equal& __eql = key_equal(), const key_equal& __eql = key_equal(),
const allocator_type& __a = allocator_type()) const allocator_type& __a = allocator_type())
: _Base(__l, __n, __hf, __eql, __a) { } : _Base(__l, __n, __hf, __eql, __a)
{ }
unordered_set& unordered_set&
operator=(const unordered_set& __x) operator=(const unordered_set&) = default;
{
*static_cast<_Base*>(this) = __x;
return *this;
}
unordered_set& unordered_set&
operator=(unordered_set&& __x) operator=(unordered_set&&) = default;
{
// NB: DR 1204.
// NB: DR 675.
this->clear();
this->swap(__x);
return *this;
}
unordered_set& unordered_set&
operator=(initializer_list<value_type> __l) operator=(initializer_list<value_type> __l)
{ {
this->clear(); _M_base() = __l;
this->insert(__l);
return *this; return *this;
} }
~unordered_set() noexcept
{
__profcxx_hashtable_destruct(this, _Base::bucket_count(),
_Base::size());
_M_profile_destruct();
}
void void
swap(unordered_set& __x) swap(unordered_set& __x)
{ noexcept( noexcept(__x._M_base().swap(__x)) )
_Base::swap(__x); { _Base::swap(__x); }
}
void void
clear() noexcept clear() noexcept
{ {
__profcxx_hashtable_destruct(this, _Base::bucket_count(), __profcxx_hashtable_destruct(this, _Base::bucket_count(),
_Base::size()); _Base::size());
_M_profile_destruct(); this->_M_profile_destruct();
_Base::clear(); _Base::clear();
} }
...@@ -240,14 +226,7 @@ namespace __profile ...@@ -240,14 +226,7 @@ namespace __profile
} }
void void
insert(const value_type* __first, const value_type* __last) rehash(size_type __n)
{
size_type __old_size = _Base::bucket_count();
_Base::insert(__first, __last);
_M_profile_resize(__old_size);
}
void rehash(size_type __n)
{ {
size_type __old_size = _Base::bucket_count(); size_type __old_size = _Base::bucket_count();
_Base::rehash(__n); _Base::rehash(__n);
...@@ -262,29 +241,6 @@ namespace __profile ...@@ -262,29 +241,6 @@ namespace __profile
if (__old_size != __new_size) if (__old_size != __new_size)
__profcxx_hashtable_resize(this, __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> template<typename _Key, typename _Hash, typename _Pred, typename _Alloc>
...@@ -316,10 +272,19 @@ namespace __profile ...@@ -316,10 +272,19 @@ namespace __profile
typename _Pred = std::equal_to<_Value>, typename _Pred = std::equal_to<_Value>,
typename _Alloc = std::allocator<_Value> > typename _Alloc = std::allocator<_Value> >
class unordered_multiset 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; typedef _GLIBCXX_STD_BASE _Base;
_Base&
_M_base() noexcept { return *this; }
const _Base&
_M_base() const noexcept { return *this; }
public: public:
typedef typename _Base::size_type size_type; typedef typename _Base::size_type size_type;
typedef typename _Base::hasher hasher; typedef typename _Base::hasher hasher;
...@@ -340,9 +305,7 @@ namespace __profile ...@@ -340,9 +305,7 @@ namespace __profile
const key_equal& __eql = key_equal(), const key_equal& __eql = key_equal(),
const allocator_type& __a = allocator_type()) const allocator_type& __a = allocator_type())
: _Base(__n, __hf, __eql, __a) : _Base(__n, __hf, __eql, __a)
{ { }
__profcxx_hashtable_construct(this, _Base::bucket_count());
}
template<typename _InputIterator> template<typename _InputIterator>
unordered_multiset(_InputIterator __f, _InputIterator __l, unordered_multiset(_InputIterator __f, _InputIterator __l,
...@@ -351,79 +314,63 @@ namespace __profile ...@@ -351,79 +314,63 @@ namespace __profile
const key_equal& __eql = key_equal(), const key_equal& __eql = key_equal(),
const allocator_type& __a = allocator_type()) const allocator_type& __a = allocator_type())
: _Base(__f, __l, __n, __hf, __eql, __a) : _Base(__f, __l, __n, __hf, __eql, __a)
{ { }
__profcxx_hashtable_construct(this, _Base::bucket_count());
}
unordered_multiset(const unordered_multiset& __x) unordered_multiset(const unordered_multiset&) = default;
: _Base(__x)
{
__profcxx_hashtable_construct(this, _Base::bucket_count());
}
unordered_multiset(const _Base& __x) unordered_multiset(const _Base& __x)
: _Base(__x) : _Base(__x)
{ { }
__profcxx_hashtable_construct(this, _Base::bucket_count());
}
unordered_multiset(unordered_multiset&& __x) unordered_multiset(unordered_multiset&&) = default;
: _Base(std::move(__x))
{ explicit
__profcxx_hashtable_construct(this, _Base::bucket_count()); 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, unordered_multiset(initializer_list<value_type> __l,
size_type __n = 0, size_type __n = 0,
const hasher& __hf = hasher(), const hasher& __hf = hasher(),
const key_equal& __eql = key_equal(), const key_equal& __eql = key_equal(),
const allocator_type& __a = allocator_type()) const allocator_type& __a = allocator_type())
: _Base(__l, __n, __hf, __eql, __a) { } : _Base(__l, __n, __hf, __eql, __a)
{ }
unordered_multiset& unordered_multiset&
operator=(const unordered_multiset& __x) operator=(const unordered_multiset&) = default;
{
*static_cast<_Base*>(this) = __x;
return *this;
}
unordered_multiset& unordered_multiset&
operator=(unordered_multiset&& __x) operator=(unordered_multiset&&) = default;
{
// NB: DR 1204.
// NB: DR 675.
this->clear();
this->swap(__x);
return *this;
}
unordered_multiset& unordered_multiset&
operator=(initializer_list<value_type> __l) operator=(initializer_list<value_type> __l)
{ {
this->clear(); _M_base() = __l;
this->insert(__l);
return *this; return *this;
} }
~unordered_multiset() noexcept
{
__profcxx_hashtable_destruct(this, _Base::bucket_count(),
_Base::size());
_M_profile_destruct();
}
void void
swap(unordered_multiset& __x) swap(unordered_multiset& __x)
{ noexcept( noexcept(__x._M_base().swap(__x)) )
_Base::swap(__x); { _Base::swap(__x); }
}
void void
clear() noexcept clear() noexcept
{ {
__profcxx_hashtable_destruct(this, _Base::bucket_count(), __profcxx_hashtable_destruct(this, _Base::bucket_count(),
_Base::size()); _Base::size());
_M_profile_destruct(); this->_M_profile_destruct();
_Base::clear(); _Base::clear();
} }
...@@ -502,14 +449,7 @@ namespace __profile ...@@ -502,14 +449,7 @@ namespace __profile
} }
void void
insert(const value_type* __first, const value_type* __last) rehash(size_type __n)
{
size_type __old_size = _Base::bucket_count();
_Base::insert(__first, __last);
_M_profile_resize(__old_size);
}
void rehash(size_type __n)
{ {
size_type __old_size = _Base::bucket_count(); size_type __old_size = _Base::bucket_count();
_Base::rehash(__n); _Base::rehash(__n);
...@@ -524,29 +464,6 @@ namespace __profile ...@@ -524,29 +464,6 @@ namespace __profile
if (__old_size != __new_size) if (__old_size != __new_size)
__profcxx_hashtable_resize(this, __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> template<typename _Value, typename _Hash, typename _Pred, typename _Alloc>
......
...@@ -30,7 +30,7 @@ struct MoveOnly ...@@ -30,7 +30,7 @@ struct MoveOnly
}; };
struct equal { struct equal {
bool operator()(const MoveOnly&, const MoveOnly) const { return true; } bool operator()(const MoveOnly&, const MoveOnly&) const { return true; }
}; };
struct hash { struct hash {
std::size_t operator()(const MoveOnly&) const { return 0; } std::size_t operator()(const MoveOnly&) const { return 0; }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment