libstdc++
unordered_base.h
Go to the documentation of this file.
1 // Profiling unordered containers implementation details -*- C++ -*-
2 
3 // Copyright (C) 2013-2014 Free Software Foundation, Inc.
4 //
5 // This file is part of the GNU ISO C++ Library. This library is free
6 // software; you can redistribute it and/or modify it under the
7 // terms of the GNU General Public License as published by the
8 // Free Software Foundation; either version 3, or (at your option)
9 // any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
15 
16 // Under Section 7 of GPL version 3, you are granted additional
17 // permissions described in the GCC Runtime Library Exception, version
18 // 3.1, as published by the Free Software Foundation.
19 
20 // You should have received a copy of the GNU General Public License along
21 // with this library; see the file COPYING3. If not see
22 // <http://www.gnu.org/licenses/>.
23 
24 /** @file profile/unordered_base.h
25  * This file is a GNU profile extension to the Standard C++ Library.
26  */
27 
28 #ifndef _GLIBCXX_PROFILE_UNORDERED
29 #define _GLIBCXX_PROFILE_UNORDERED 1
30 
31 namespace std _GLIBCXX_VISIBILITY(default)
32 {
33 namespace __profile
34 {
35  template<typename _UnorderedCont,
36  typename _Value, bool _Cache_hash_code>
37  struct _Bucket_index_helper;
38 
39  template<typename _UnorderedCont, typename _Value>
40  struct _Bucket_index_helper<_UnorderedCont, _Value, true>
41  {
42  static std::size_t
43  bucket(const _UnorderedCont& __uc,
44  const __detail::_Hash_node<_Value, true>* __node)
45  { return __node->_M_hash_code % __uc.bucket_count(); }
46  };
47 
48  template<typename _UnorderedCont, typename _Value>
49  struct _Bucket_index_helper<_UnorderedCont, _Value, false>
50  {
51  static std::size_t
52  bucket(const _UnorderedCont& __uc,
53  const __detail::_Hash_node<_Value, false>* __node)
54  { return __uc.bucket(__node->_M_v()); }
55  };
56 
57  template<typename _UnorderedCont, typename _Key, typename _Mapped>
58  struct _Bucket_index_helper<_UnorderedCont,
59  std::pair<const _Key, _Mapped>, false>
60  {
61  typedef std::pair<const _Key, _Mapped> _Value;
62 
63  static std::size_t
64  bucket(const _UnorderedCont& __uc,
65  const __detail::_Hash_node<_Value, false>* __node)
66  { return __uc.bucket(__node->_M_v().first); }
67  };
68 
69  template<typename _UnorderedCont, typename _Value, bool _Cache_hash_code>
70  std::size_t
71  __get_bucket_index(const _UnorderedCont& __uc,
72  const __detail::_Hash_node<_Value, _Cache_hash_code>* __node)
73  {
74  using __bucket_index_helper
75  = _Bucket_index_helper<_UnorderedCont, _Value, _Cache_hash_code>;
76  return __bucket_index_helper::bucket(__uc, __node);
77  }
78 
79  template<typename _UnorderedCont,
80  typename _Value, bool _Cache_hash_code>
81  struct _Equal_helper;
82 
83  template<typename _UnorderedCont, typename _Value>
84  struct _Equal_helper<_UnorderedCont, _Value, true>
85  {
86  static std::size_t
87  are_equal(const _UnorderedCont& __uc,
88  const __detail::_Hash_node<_Value, true>* __lhs,
89  const __detail::_Hash_node<_Value, true>* __rhs)
90  {
91  return __lhs->_M_hash_code == __rhs->_M_hash_code
92  && __uc.key_eq()(__lhs->_M_v(), __rhs->_M_v());
93  }
94  };
95 
96  template<typename _UnorderedCont,
97  typename _Value>
98  struct _Equal_helper<_UnorderedCont, _Value, false>
99  {
100  static std::size_t
101  are_equal(const _UnorderedCont& __uc,
102  const __detail::_Hash_node<_Value, false>* __lhs,
103  const __detail::_Hash_node<_Value, false>* __rhs)
104  { return __uc.key_eq()(__lhs->_M_v(), __rhs->_M_v()); }
105  };
106 
107  template<typename _UnorderedCont,
108  typename _Key, typename _Mapped>
109  struct _Equal_helper<_UnorderedCont, std::pair<const _Key, _Mapped>, true>
110  {
111  typedef std::pair<const _Key, _Mapped> _Value;
112 
113  static std::size_t
114  are_equal(const _UnorderedCont& __uc,
115  const __detail::_Hash_node<_Value, true>* __lhs,
116  const __detail::_Hash_node<_Value, true>* __rhs)
117  {
118  return __lhs->_M_hash_code == __rhs->_M_hash_code
119  && __uc.key_eq()(__lhs->_M_v().first, __rhs->_M_v().first);
120  }
121  };
122 
123  template<typename _UnorderedCont,
124  typename _Key, typename _Mapped>
125  struct _Equal_helper<_UnorderedCont, std::pair<const _Key, _Mapped>, false>
126  {
127  typedef std::pair<const _Key, _Mapped> _Value;
128 
129  static std::size_t
130  are_equal(const _UnorderedCont& __uc,
131  const __detail::_Hash_node<_Value, false>* __lhs,
132  const __detail::_Hash_node<_Value, false>* __rhs)
133  { return __uc.key_eq()(__lhs->_M_v().first, __rhs->_M_v().first); }
134  };
135 
136  template<typename _UnorderedCont, typename _Value, bool _Cache_hash_code>
137  bool
138  __are_equal(const _UnorderedCont& __uc,
139  const __detail::_Hash_node<_Value, _Cache_hash_code>* __lhs,
140  const __detail::_Hash_node<_Value, _Cache_hash_code>* __rhs)
141  {
142  using __equal_helper
143  = _Equal_helper<_UnorderedCont, _Value, _Cache_hash_code>;
144  return __equal_helper::are_equal(__uc, __lhs, __rhs);
145  }
146 
147  template<typename _UnorderedCont, bool _Unique_keys>
148  class _Unordered_profile
149  {
150  _UnorderedCont&
151  _M_conjure()
152  { return *(static_cast<_UnorderedCont*>(this)); }
153 
154  using __unique_keys = std::integral_constant<bool, _Unique_keys>;
155 
156  protected:
157  _Unordered_profile()
158  {
159  auto& __uc = _M_conjure();
160  __profcxx_hashtable_construct(&__uc, __uc.bucket_count());
161  __profcxx_hashtable_construct2(&__uc);
162  }
163  _Unordered_profile(const _Unordered_profile&)
164  : _Unordered_profile() { }
165  _Unordered_profile(_Unordered_profile&&)
166  : _Unordered_profile() { }
167 
168  ~_Unordered_profile() noexcept
169  {
170  auto& __uc = _M_conjure();
171  __profcxx_hashtable_destruct(&__uc, __uc.bucket_count(), __uc.size());
172  _M_profile_destruct();
173  }
174 
175  _Unordered_profile&
176  operator=(const _Unordered_profile&) = default;
177 
178  _Unordered_profile&
179  operator=(_Unordered_profile&&) = default;
180 
181  void
182  _M_profile_destruct()
183  {
184  if (!__profcxx_inefficient_hash_is_on())
185  return;
186 
187  _M_profile_destruct(__unique_keys());
188  }
189 
190  private:
191  void
192  _M_profile_destruct(std::true_type);
193 
194  void
195  _M_profile_destruct(std::false_type);
196  };
197 
198  template<typename _UnorderedCont, bool _Unique_keys>
199  void
200  _Unordered_profile<_UnorderedCont, _Unique_keys>::
201  _M_profile_destruct(std::true_type)
202  {
203  auto& __uc = _M_conjure();
204  std::size_t __hops = 0, __lc = 0, __chain = 0;
205  auto __it = __uc.begin();
206  while (__it != __uc.end())
207  {
208  auto __bkt = __get_bucket_index(__uc, __it._M_cur);
209  auto __lit = __uc.begin(__bkt);
210  auto __lend = __uc.end(__bkt);
211  for (++__it, ++__lit; __lit != __lend; ++__it, ++__lit)
212  ++__chain;
213  if (__chain)
214  {
215  ++__chain;
216  __lc = __lc > __chain ? __lc : __chain;
217  __hops += __chain * (__chain - 1) / 2;
218  __chain = 0;
219  }
220  }
221  __profcxx_hashtable_destruct2(&__uc, __lc, __uc.size(), __hops);
222  }
223 
224  template<typename _UnorderedCont, bool _Unique_keys>
225  void
226  _Unordered_profile<_UnorderedCont, _Unique_keys>::
227  _M_profile_destruct(std::false_type)
228  {
229  auto& __uc = _M_conjure();
230  std::size_t __hops = 0, __lc = 0, __chain = 0, __unique_size = 0;
231  auto __it = __uc.begin();
232  while (__it != __uc.end())
233  {
234  auto __bkt = __get_bucket_index(__uc, __it._M_cur);
235  auto __lit = __uc.begin(__bkt);
236  auto __lend = __uc.end(__bkt);
237  auto __pit = __it;
238  ++__unique_size;
239  for (++__it, ++__lit; __lit != __lend; ++__it, ++__lit)
240  {
241  if (!__are_equal(__uc, __pit._M_cur, __it._M_cur))
242  {
243  ++__chain;
244  ++__unique_size;
245  __pit = __it;
246  }
247  }
248  if (__chain)
249  {
250  ++__chain;
251  __lc = __lc > __chain ? __lc : __chain;
252  __hops += __chain * (__chain - 1) / 2;
253  __chain = 0;
254  }
255  }
256  __profcxx_hashtable_destruct2(&__uc, __lc, __unique_size, __hops);
257  }
258 
259 } // namespace __profile
260 } // namespace std
261 
262 #endif
Struct holding two objects of arbitrary type.
Definition: stl_pair.h:96
integral_constant
Definition: type_traits:57