1 // Profiling unordered_map/unordered_multimap implementation -*- C++ -*-
3 // Copyright (C) 2009, 2010, 2011 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 2, 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 // You should have received a copy of the GNU General Public License along
17 // with this library; see the file COPYING. If not, write to the Free
18 // Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
21 // As a special exception, you may use this file as part of a free software
22 // library without restriction. Specifically, if other files instantiate
23 // templates or use macros or inline functions from this file, or you compile
24 // this file and link it with other files to produce an executable, this
25 // file does not by itself cause the resulting executable to be covered by
26 // the GNU General Public License. This exception does not however
27 // invalidate any other reasons why the executable file might be covered by
28 // the GNU General Public License.
30 /** @file profile/unordered_map
31 * This file is a GNU profile extension to the Standard C++ Library.
34 #ifndef _GLIBCXX_PROFILE_UNORDERED_MAP
35 #define _GLIBCXX_PROFILE_UNORDERED_MAP 1
37 #ifndef __GXX_EXPERIMENTAL_CXX0X__
38 # include <bits/c++0x_warning.h>
40 # include <unordered_map>
42 #include <profile/base.h>
44 #define _GLIBCXX_BASE unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>
45 #define _GLIBCXX_STD_BASE _GLIBCXX_STD_C::_GLIBCXX_BASE
47 namespace std _GLIBCXX_VISIBILITY(default)
51 /// Class std::unordered_map wrapper with performance instrumentation.
52 template<typename _Key, typename _Tp,
53 typename _Hash = std::hash<_Key>,
54 typename _Pred = std::equal_to<_Key>,
55 typename _Alloc = std::allocator<_Key> >
57 : public _GLIBCXX_STD_BASE
59 typedef typename _GLIBCXX_STD_BASE _Base;
62 typedef typename _Base::size_type size_type;
63 typedef typename _Base::hasher hasher;
64 typedef typename _Base::key_equal key_equal;
65 typedef typename _Base::allocator_type allocator_type;
66 typedef typename _Base::key_type key_type;
67 typedef typename _Base::value_type value_type;
68 typedef typename _Base::difference_type difference_type;
69 typedef typename _Base::reference reference;
70 typedef typename _Base::const_reference const_reference;
71 typedef typename _Base::mapped_type mapped_type;
73 typedef typename _Base::iterator iterator;
74 typedef typename _Base::const_iterator const_iterator;
77 unordered_map(size_type __n = 10,
78 const hasher& __hf = hasher(),
79 const key_equal& __eql = key_equal(),
80 const allocator_type& __a = allocator_type())
81 : _Base(__n, __hf, __eql, __a)
83 __profcxx_hashtable_construct(this, _Base::bucket_count());
84 __profcxx_hashtable_construct2(this);
87 template<typename _InputIterator>
88 unordered_map(_InputIterator __f, _InputIterator __l,
90 const hasher& __hf = hasher(),
91 const key_equal& __eql = key_equal(),
92 const allocator_type& __a = allocator_type())
93 : _Base(__f, __l, __n, __hf, __eql, __a)
95 __profcxx_hashtable_construct(this, _Base::bucket_count());
96 __profcxx_hashtable_construct2(this);
99 unordered_map(const unordered_map& __x)
102 __profcxx_hashtable_construct(this, _Base::bucket_count());
103 __profcxx_hashtable_construct2(this);
106 unordered_map(const _Base& __x)
109 __profcxx_hashtable_construct(this, _Base::bucket_count());
110 __profcxx_hashtable_construct2(this);
113 unordered_map(unordered_map&& __x)
114 : _Base(std::move(__x))
116 __profcxx_hashtable_construct(this, _Base::bucket_count());
117 __profcxx_hashtable_construct2(this);
120 unordered_map(initializer_list<value_type> __l,
122 const hasher& __hf = hasher(),
123 const key_equal& __eql = key_equal(),
124 const allocator_type& __a = allocator_type())
125 : _Base(__l, __n, __hf, __eql, __a) { }
128 operator=(const unordered_map& __x)
130 *static_cast<_Base*>(this) = __x;
135 operator=(unordered_map&& __x)
145 operator=(initializer_list<value_type> __l)
152 ~unordered_map() noexcept
154 __profcxx_hashtable_destruct(this, _Base::bucket_count(),
156 _M_profile_destruct();
160 _M_base() noexcept { return *this; }
163 _M_base() const noexcept { return *this; }
168 __profcxx_hashtable_destruct(this, _Base::bucket_count(),
170 _M_profile_destruct();
175 insert(std::initializer_list<value_type> __l)
177 size_type __old_size = _Base::bucket_count();
179 _M_profile_resize(__old_size);
182 std::pair<iterator, bool>
183 insert(const value_type& __obj)
185 size_type __old_size = _Base::bucket_count();
186 std::pair<iterator, bool> __res = _Base::insert(__obj);
187 _M_profile_resize(__old_size);
192 insert(const_iterator __iter, const value_type& __v)
194 size_type __old_size = _Base::bucket_count();
195 iterator __res = _Base::insert(__iter, __v);
196 _M_profile_resize(__old_size);
200 template<typename _Pair, typename = typename
201 std::enable_if<std::is_convertible<_Pair,
202 value_type>::value>::type>
203 std::pair<iterator, bool>
204 insert(_Pair&& __obj)
206 size_type __old_size = _Base::bucket_count();
207 std::pair<iterator, bool> __res
208 = _Base::insert(std::forward<_Pair>(__obj));
209 _M_profile_resize(__old_size);
213 template<typename _Pair, typename = typename
214 std::enable_if<std::is_convertible<_Pair,
215 value_type>::value>::type>
217 insert(const_iterator __iter, _Pair&& __v)
219 size_type __old_size = _Base::bucket_count();
220 iterator __res = _Base::insert(__iter, std::forward<_Pair>(__v));
221 _M_profile_resize(__old_size);
225 template<typename _InputIter>
227 insert(_InputIter __first, _InputIter __last)
229 size_type __old_size = _Base::bucket_count();
230 _Base::insert(__first, __last);
231 _M_profile_resize(__old_size);
235 insert(const value_type* __first, const value_type* __last)
237 size_type __old_size = _Base::bucket_count();
238 _Base::insert(__first, __last);
239 _M_profile_resize(__old_size);
244 operator[](const _Key& __k)
246 size_type __old_size = _Base::bucket_count();
247 mapped_type& __res = _M_base()[__k];
248 _M_profile_resize(__old_size);
253 operator[](_Key&& __k)
255 size_type __old_size = _Base::bucket_count();
256 mapped_type& __res = _M_base()[std::move(__k)];
257 _M_profile_resize(__old_size);
262 swap(unordered_map& __x)
263 { _Base::swap(__x); }
265 void rehash(size_type __n)
267 size_type __old_size = _Base::bucket_count();
269 _M_profile_resize(__old_size);
274 _M_profile_resize(size_type __old_size)
276 size_type __new_size = _Base::bucket_count();
277 if (__old_size != __new_size)
278 __profcxx_hashtable_resize(this, __old_size, __new_size);
282 _M_profile_destruct()
284 size_type __hops = 0, __lc = 0, __chain = 0;
285 for (iterator __it = _M_base().begin(); __it != _M_base().end();
288 while (__it._M_cur_node->_M_next)
296 __lc = __lc > __chain ? __lc : __chain;
297 __hops += __chain * (__chain - 1) / 2;
301 __profcxx_hashtable_destruct2(this, __lc, _Base::size(), __hops);
305 template<typename _Key, typename _Tp, typename _Hash,
306 typename _Pred, typename _Alloc>
308 swap(unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
309 unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
312 template<typename _Key, typename _Tp, typename _Hash,
313 typename _Pred, typename _Alloc>
315 operator==(const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
316 const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
317 { return __x._M_equal(__y); }
319 template<typename _Key, typename _Tp, typename _Hash,
320 typename _Pred, typename _Alloc>
322 operator!=(const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
323 const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
324 { return !(__x == __y); }
327 #undef _GLIBCXX_STD_BASE
328 #define _GLIBCXX_BASE unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>
329 #define _GLIBCXX_STD_BASE _GLIBCXX_STD_C::_GLIBCXX_BASE
331 /// Class std::unordered_multimap wrapper with performance instrumentation.
332 template<typename _Key, typename _Tp,
333 typename _Hash = std::hash<_Key>,
334 typename _Pred = std::equal_to<_Key>,
335 typename _Alloc = std::allocator<_Key> >
336 class unordered_multimap
337 : public _GLIBCXX_STD_BASE
339 typedef typename _GLIBCXX_STD_BASE _Base;
342 typedef typename _Base::size_type size_type;
343 typedef typename _Base::hasher hasher;
344 typedef typename _Base::key_equal key_equal;
345 typedef typename _Base::allocator_type allocator_type;
346 typedef typename _Base::key_type key_type;
347 typedef typename _Base::value_type value_type;
348 typedef typename _Base::difference_type difference_type;
349 typedef typename _Base::reference reference;
350 typedef typename _Base::const_reference const_reference;
352 typedef typename _Base::iterator iterator;
353 typedef typename _Base::const_iterator const_iterator;
356 unordered_multimap(size_type __n = 10,
357 const hasher& __hf = hasher(),
358 const key_equal& __eql = key_equal(),
359 const allocator_type& __a = allocator_type())
360 : _Base(__n, __hf, __eql, __a)
362 __profcxx_hashtable_construct(this, _Base::bucket_count());
364 template<typename _InputIterator>
365 unordered_multimap(_InputIterator __f, _InputIterator __l,
367 const hasher& __hf = hasher(),
368 const key_equal& __eql = key_equal(),
369 const allocator_type& __a = allocator_type())
370 : _Base(__f, __l, __n, __hf, __eql, __a)
372 __profcxx_hashtable_construct(this, _Base::bucket_count());
375 unordered_multimap(const unordered_multimap& __x)
378 __profcxx_hashtable_construct(this, _Base::bucket_count());
381 unordered_multimap(const _Base& __x)
384 __profcxx_hashtable_construct(this, _Base::bucket_count());
387 unordered_multimap(unordered_multimap&& __x)
388 : _Base(std::move(__x))
390 __profcxx_hashtable_construct(this, _Base::bucket_count());
393 unordered_multimap(initializer_list<value_type> __l,
395 const hasher& __hf = hasher(),
396 const key_equal& __eql = key_equal(),
397 const allocator_type& __a = allocator_type())
398 : _Base(__l, __n, __hf, __eql, __a) { }
401 operator=(const unordered_multimap& __x)
403 *static_cast<_Base*>(this) = __x;
408 operator=(unordered_multimap&& __x)
418 operator=(initializer_list<value_type> __l)
425 ~unordered_multimap() noexcept
427 __profcxx_hashtable_destruct(this, _Base::bucket_count(),
429 _M_profile_destruct();
433 _M_base() noexcept { return *this; }
436 _M_base() const noexcept { return *this; }
441 __profcxx_hashtable_destruct(this, _Base::bucket_count(),
443 _M_profile_destruct();
448 insert(std::initializer_list<value_type> __l)
450 size_type __old_size = _Base::bucket_count();
452 _M_profile_resize(__old_size, _Base::bucket_count());
456 insert(const value_type& __obj)
458 size_type __old_size = _Base::bucket_count();
459 iterator __res = _Base::insert(__obj);
460 _M_profile_resize(__old_size, _Base::bucket_count());
465 insert(const_iterator __iter, const value_type& __v)
467 size_type __old_size = _Base::bucket_count();
468 iterator __res = _Base::insert(__iter, __v);
469 _M_profile_resize(__old_size, _Base::bucket_count());
473 template<typename _Pair, typename = typename
474 std::enable_if<std::is_convertible<_Pair,
475 value_type>::value>::type>
477 insert(_Pair&& __obj)
479 size_type __old_size = _Base::bucket_count();
480 iterator __res = _Base::insert(std::forward<_Pair>(__obj));
481 _M_profile_resize(__old_size, _Base::bucket_count());
485 template<typename _Pair, typename = typename
486 std::enable_if<std::is_convertible<_Pair,
487 value_type>::value>::type>
489 insert(const_iterator __iter, _Pair&& __v)
491 size_type __old_size = _Base::bucket_count();
492 iterator __res = _Base::insert(__iter, std::forward<_Pair>(__v));
493 _M_profile_resize(__old_size, _Base::bucket_count());
497 template<typename _InputIter>
499 insert(_InputIter __first, _InputIter __last)
501 size_type __old_size = _Base::bucket_count();
502 _Base::insert(__first, __last);
503 _M_profile_resize(__old_size, _Base::bucket_count());
507 insert(const value_type* __first, const value_type* __last)
509 size_type __old_size = _Base::bucket_count();
510 _Base::insert(__first, __last);
511 _M_profile_resize(__old_size, _Base::bucket_count());
515 swap(unordered_multimap& __x)
516 { _Base::swap(__x); }
518 void rehash(size_type __n)
520 size_type __old_size = _Base::bucket_count();
522 _M_profile_resize(__old_size, _Base::bucket_count());
527 _M_profile_resize(size_type __old_size, size_type __new_size)
529 if (__old_size != __new_size)
530 __profcxx_hashtable_resize(this, __old_size, __new_size);
534 _M_profile_destruct()
536 size_type __hops = 0, __lc = 0, __chain = 0;
537 for (iterator __it = _M_base().begin(); __it != _M_base().end();
540 while (__it._M_cur_node->_M_next)
548 __lc = __lc > __chain ? __lc : __chain;
549 __hops += __chain * (__chain - 1) / 2;
553 __profcxx_hashtable_destruct2(this, __lc, _Base::size(), __hops);
558 template<typename _Key, typename _Tp, typename _Hash,
559 typename _Pred, typename _Alloc>
561 swap(unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
562 unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
565 template<typename _Key, typename _Tp, typename _Hash,
566 typename _Pred, typename _Alloc>
568 operator==(const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
569 const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
570 { return __x._M_equal(__y); }
572 template<typename _Key, typename _Tp, typename _Hash,
573 typename _Pred, typename _Alloc>
575 operator!=(const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
576 const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
577 { return !(__x == __y); }
579 } // namespace __profile
583 #undef _GLIBCXX_STD_BASE
585 #endif // __GXX_EXPERIMENTAL_CXX0X__