1 // Profiling unordered_map/unordered_multimap implementation -*- C++ -*-
3 // Copyright (C) 2009, 2010 Free Software Foundation, Inc.
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)
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.
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.
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/>.
24 /** @file profile/unordered_map
25 * This file is a GNU profile extension to the Standard C++ Library.
28 #ifndef _GLIBCXX_PROFILE_UNORDERED_MAP
29 #define _GLIBCXX_PROFILE_UNORDERED_MAP 1
31 #ifndef __GXX_EXPERIMENTAL_CXX0X__
32 # include <bits/c++0x_warning.h>
34 # include <unordered_map>
36 #include <profile/base.h>
38 #define _GLIBCXX_BASE unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>
39 #define _GLIBCXX_STD_BASE _GLIBCXX_STD_C::_GLIBCXX_BASE
41 namespace std _GLIBCXX_VISIBILITY(default)
45 /// Class std::unordered_map wrapper with performance instrumentation.
46 template<typename _Key, typename _Tp,
47 typename _Hash = std::hash<_Key>,
48 typename _Pred = std::equal_to<_Key>,
49 typename _Alloc = std::allocator<_Key> >
51 : public _GLIBCXX_STD_BASE
53 typedef typename _GLIBCXX_STD_BASE _Base;
56 typedef typename _Base::size_type size_type;
57 typedef typename _Base::hasher hasher;
58 typedef typename _Base::key_equal key_equal;
59 typedef typename _Base::allocator_type allocator_type;
60 typedef typename _Base::key_type key_type;
61 typedef typename _Base::value_type value_type;
62 typedef typename _Base::difference_type difference_type;
63 typedef typename _Base::reference reference;
64 typedef typename _Base::const_reference const_reference;
65 typedef typename _Base::mapped_type mapped_type;
67 typedef typename _Base::iterator iterator;
68 typedef typename _Base::const_iterator const_iterator;
71 unordered_map(size_type __n = 10,
72 const hasher& __hf = hasher(),
73 const key_equal& __eql = key_equal(),
74 const allocator_type& __a = allocator_type())
75 : _Base(__n, __hf, __eql, __a)
77 __profcxx_hashtable_construct(this, _Base::bucket_count());
78 __profcxx_hashtable_construct2(this);
81 template<typename _InputIterator>
82 unordered_map(_InputIterator __f, _InputIterator __l,
84 const hasher& __hf = hasher(),
85 const key_equal& __eql = key_equal(),
86 const allocator_type& __a = allocator_type())
87 : _Base(__f, __l, __n, __hf, __eql, __a)
89 __profcxx_hashtable_construct(this, _Base::bucket_count());
90 __profcxx_hashtable_construct2(this);
93 unordered_map(const _Base& __x)
96 __profcxx_hashtable_construct(this, _Base::bucket_count());
97 __profcxx_hashtable_construct2(this);
100 unordered_map(unordered_map&& __x)
101 : _Base(std::move(__x))
103 __profcxx_hashtable_construct(this, _Base::bucket_count());
104 __profcxx_hashtable_construct2(this);
107 unordered_map(initializer_list<value_type> __l,
109 const hasher& __hf = hasher(),
110 const key_equal& __eql = key_equal(),
111 const allocator_type& __a = allocator_type())
112 : _Base(__l, __n, __hf, __eql, __a) { }
115 operator=(const unordered_map& __x)
117 *static_cast<_Base*>(this) = __x;
122 operator=(unordered_map&& __x)
132 operator=(initializer_list<value_type> __l)
141 __profcxx_hashtable_destruct(this, _Base::bucket_count(),
143 _M_profile_destruct();
147 _M_base() { return *this; }
150 _M_base() const { return *this; }
156 __profcxx_hashtable_destruct(this, _Base::bucket_count(),
158 _M_profile_destruct();
163 insert(std::initializer_list<value_type> __l)
165 size_type __old_size = _Base::bucket_count();
167 _M_profile_resize(__old_size);
170 std::pair<iterator, bool>
171 insert(const value_type& __obj)
173 size_type __old_size = _Base::bucket_count();
174 std::pair<iterator, bool> __res = _Base::insert(__obj);
175 _M_profile_resize(__old_size);
180 insert(const_iterator __iter, const value_type& __v)
182 size_type __old_size = _Base::bucket_count();
183 iterator __res = _Base::insert(__iter, __v);
184 _M_profile_resize(__old_size);
188 template<typename _Pair, typename = typename
189 std::enable_if<std::is_convertible<_Pair,
190 value_type>::value>::type>
191 std::pair<iterator, bool>
192 insert(_Pair&& __obj)
194 size_type __old_size = _Base::bucket_count();
195 std::pair<iterator, bool> __res
196 = _Base::insert(std::forward<_Pair>(__obj));
197 _M_profile_resize(__old_size);
201 template<typename _Pair, typename = typename
202 std::enable_if<std::is_convertible<_Pair,
203 value_type>::value>::type>
205 insert(const_iterator __iter, _Pair&& __v)
207 size_type __old_size = _Base::bucket_count();
208 iterator __res = _Base::insert(__iter, std::forward<_Pair>(__v));
209 _M_profile_resize(__old_size);
213 template<typename _InputIter>
215 insert(_InputIter __first, _InputIter __last)
217 size_type __old_size = _Base::bucket_count();
218 _Base::insert(__first, __last);
219 _M_profile_resize(__old_size);
223 insert(const value_type* __first, const value_type* __last)
225 size_type __old_size = _Base::bucket_count();
226 _Base::insert(__first, __last);
227 _M_profile_resize(__old_size);
232 operator[](const _Key& __k)
234 size_type __old_size = _Base::bucket_count();
235 mapped_type& __res = _M_base()[__k];
236 _M_profile_resize(__old_size);
241 operator[](_Key&& __k)
243 size_type __old_size = _Base::bucket_count();
244 mapped_type& __res = _M_base()[std::move(__k)];
245 _M_profile_resize(__old_size);
250 swap(unordered_map& __x)
251 { _Base::swap(__x); }
253 void rehash(size_type __n)
255 size_type __old_size = _Base::bucket_count();
257 _M_profile_resize(__old_size);
262 _M_profile_resize(size_type __old_size)
264 size_type __new_size = _Base::bucket_count();
265 if (__old_size != __new_size)
266 __profcxx_hashtable_resize(this, __old_size, __new_size);
270 _M_profile_destruct()
272 size_type __hops = 0, __lc = 0, __chain = 0;
273 for (iterator __it = _M_base().begin(); __it != _M_base().end();
276 while (__it._M_cur_node->_M_next)
284 __lc = __lc > __chain ? __lc : __chain;
285 __hops += __chain * (__chain - 1) / 2;
289 __profcxx_hashtable_destruct2(this, __lc, _Base::size(), __hops);
293 template<typename _Key, typename _Tp, typename _Hash,
294 typename _Pred, typename _Alloc>
296 swap(unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
297 unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
300 template<typename _Key, typename _Tp, typename _Hash,
301 typename _Pred, typename _Alloc>
303 operator==(const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
304 const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
305 { return __x._M_equal(__y); }
307 template<typename _Key, typename _Tp, typename _Hash,
308 typename _Pred, typename _Alloc>
310 operator!=(const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
311 const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
312 { return !(__x == __y); }
315 #undef _GLIBCXX_STD_BASE
316 #define _GLIBCXX_BASE unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>
317 #define _GLIBCXX_STD_BASE _GLIBCXX_STD_C::_GLIBCXX_BASE
319 /// Class std::unordered_multimap wrapper with performance instrumentation.
320 template<typename _Key, typename _Tp,
321 typename _Hash = std::hash<_Key>,
322 typename _Pred = std::equal_to<_Key>,
323 typename _Alloc = std::allocator<_Key> >
324 class unordered_multimap
325 : public _GLIBCXX_STD_BASE
327 typedef typename _GLIBCXX_STD_BASE _Base;
330 typedef typename _Base::size_type size_type;
331 typedef typename _Base::hasher hasher;
332 typedef typename _Base::key_equal key_equal;
333 typedef typename _Base::allocator_type allocator_type;
334 typedef typename _Base::key_type key_type;
335 typedef typename _Base::value_type value_type;
336 typedef typename _Base::difference_type difference_type;
337 typedef typename _Base::reference reference;
338 typedef typename _Base::const_reference const_reference;
340 typedef typename _Base::iterator iterator;
341 typedef typename _Base::const_iterator const_iterator;
344 unordered_multimap(size_type __n = 10,
345 const hasher& __hf = hasher(),
346 const key_equal& __eql = key_equal(),
347 const allocator_type& __a = allocator_type())
348 : _Base(__n, __hf, __eql, __a)
350 __profcxx_hashtable_construct(this, _Base::bucket_count());
352 template<typename _InputIterator>
353 unordered_multimap(_InputIterator __f, _InputIterator __l,
355 const hasher& __hf = hasher(),
356 const key_equal& __eql = key_equal(),
357 const allocator_type& __a = allocator_type())
358 : _Base(__f, __l, __n, __hf, __eql, __a)
360 __profcxx_hashtable_construct(this, _Base::bucket_count());
363 unordered_multimap(const _Base& __x)
366 __profcxx_hashtable_construct(this, _Base::bucket_count());
369 unordered_multimap(unordered_multimap&& __x)
370 : _Base(std::move(__x))
372 __profcxx_hashtable_construct(this, _Base::bucket_count());
375 unordered_multimap(initializer_list<value_type> __l,
377 const hasher& __hf = hasher(),
378 const key_equal& __eql = key_equal(),
379 const allocator_type& __a = allocator_type())
380 : _Base(__l, __n, __hf, __eql, __a) { }
383 operator=(const unordered_multimap& __x)
385 *static_cast<_Base*>(this) = __x;
390 operator=(unordered_multimap&& __x)
400 operator=(initializer_list<value_type> __l)
407 ~unordered_multimap()
409 __profcxx_hashtable_destruct(this, _Base::bucket_count(),
411 _M_profile_destruct();
415 _M_base() { return *this; }
418 _M_base() const { return *this; }
424 __profcxx_hashtable_destruct(this, _Base::bucket_count(),
426 _M_profile_destruct();
431 insert(std::initializer_list<value_type> __l)
433 size_type __old_size = _Base::bucket_count();
435 _M_profile_resize(__old_size, _Base::bucket_count());
439 insert(const value_type& __obj)
441 size_type __old_size = _Base::bucket_count();
442 iterator __res = _Base::insert(__obj);
443 _M_profile_resize(__old_size, _Base::bucket_count());
448 insert(const_iterator __iter, const value_type& __v)
450 size_type __old_size = _Base::bucket_count();
451 iterator __res = _Base::insert(__iter, __v);
452 _M_profile_resize(__old_size, _Base::bucket_count());
456 template<typename _Pair, typename = typename
457 std::enable_if<std::is_convertible<_Pair,
458 value_type>::value>::type>
460 insert(_Pair&& __obj)
462 size_type __old_size = _Base::bucket_count();
463 iterator __res = _Base::insert(std::forward<_Pair>(__obj));
464 _M_profile_resize(__old_size, _Base::bucket_count());
468 template<typename _Pair, typename = typename
469 std::enable_if<std::is_convertible<_Pair,
470 value_type>::value>::type>
472 insert(const_iterator __iter, _Pair&& __v)
474 size_type __old_size = _Base::bucket_count();
475 iterator __res = _Base::insert(__iter, std::forward<_Pair>(__v));
476 _M_profile_resize(__old_size, _Base::bucket_count());
480 template<typename _InputIter>
482 insert(_InputIter __first, _InputIter __last)
484 size_type __old_size = _Base::bucket_count();
485 _Base::insert(__first, __last);
486 _M_profile_resize(__old_size, _Base::bucket_count());
490 insert(const value_type* __first, const value_type* __last)
492 size_type __old_size = _Base::bucket_count();
493 _Base::insert(__first, __last);
494 _M_profile_resize(__old_size, _Base::bucket_count());
498 swap(unordered_multimap& __x)
499 { _Base::swap(__x); }
501 void rehash(size_type __n)
503 size_type __old_size = _Base::bucket_count();
505 _M_profile_resize(__old_size, _Base::bucket_count());
510 _M_profile_resize(size_type __old_size, size_type __new_size)
512 if (__old_size != __new_size)
513 __profcxx_hashtable_resize(this, __old_size, __new_size);
517 _M_profile_destruct()
519 size_type __hops = 0, __lc = 0, __chain = 0;
520 for (iterator __it = _M_base().begin(); __it != _M_base().end();
523 while (__it._M_cur_node->_M_next)
531 __lc = __lc > __chain ? __lc : __chain;
532 __hops += __chain * (__chain - 1) / 2;
536 __profcxx_hashtable_destruct2(this, __lc, _Base::size(), __hops);
541 template<typename _Key, typename _Tp, typename _Hash,
542 typename _Pred, typename _Alloc>
544 swap(unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
545 unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
548 template<typename _Key, typename _Tp, typename _Hash,
549 typename _Pred, typename _Alloc>
551 operator==(const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
552 const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
553 { return __x._M_equal(__y); }
555 template<typename _Key, typename _Tp, typename _Hash,
556 typename _Pred, typename _Alloc>
558 operator!=(const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
559 const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
560 { return !(__x == __y); }
562 } // namespace __profile
566 #undef _GLIBCXX_STD_BASE
568 #endif // __GXX_EXPERIMENTAL_CXX0X__