1 // Profiling unordered_map/unordered_multimap implementation -*- C++ -*-
3 // Copyright (C) 2009, 2010, 2011, 2012 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 unordered_map& __x)
96 __profcxx_hashtable_construct(this, _Base::bucket_count());
97 __profcxx_hashtable_construct2(this);
100 unordered_map(const _Base& __x)
103 __profcxx_hashtable_construct(this, _Base::bucket_count());
104 __profcxx_hashtable_construct2(this);
107 unordered_map(unordered_map&& __x)
108 : _Base(std::move(__x))
110 __profcxx_hashtable_construct(this, _Base::bucket_count());
111 __profcxx_hashtable_construct2(this);
114 unordered_map(initializer_list<value_type> __l,
116 const hasher& __hf = hasher(),
117 const key_equal& __eql = key_equal(),
118 const allocator_type& __a = allocator_type())
119 : _Base(__l, __n, __hf, __eql, __a) { }
122 operator=(const unordered_map& __x)
124 *static_cast<_Base*>(this) = __x;
129 operator=(unordered_map&& __x)
139 operator=(initializer_list<value_type> __l)
146 ~unordered_map() noexcept
148 __profcxx_hashtable_destruct(this, _Base::bucket_count(),
150 _M_profile_destruct();
154 _M_base() noexcept { return *this; }
157 _M_base() const noexcept { return *this; }
162 __profcxx_hashtable_destruct(this, _Base::bucket_count(),
164 _M_profile_destruct();
168 template<typename... _Args>
169 std::pair<iterator, bool>
170 emplace(_Args&&... __args)
172 size_type __old_size = _Base::bucket_count();
173 std::pair<iterator, bool> __res
174 = _Base::emplace(std::forward<_Args>(__args)...);
175 _M_profile_resize(__old_size);
179 template<typename... _Args>
181 emplace_hint(const_iterator __it, _Args&&... __args)
183 size_type __old_size = _Base::bucket_count();
185 = _Base::emplace_hint(__it, std::forward<_Args>(__args)...);
186 _M_profile_resize(__old_size);
191 insert(std::initializer_list<value_type> __l)
193 size_type __old_size = _Base::bucket_count();
195 _M_profile_resize(__old_size);
198 std::pair<iterator, bool>
199 insert(const value_type& __obj)
201 size_type __old_size = _Base::bucket_count();
202 std::pair<iterator, bool> __res = _Base::insert(__obj);
203 _M_profile_resize(__old_size);
208 insert(const_iterator __iter, const value_type& __v)
210 size_type __old_size = _Base::bucket_count();
211 iterator __res = _Base::insert(__iter, __v);
212 _M_profile_resize(__old_size);
216 template<typename _Pair, typename = typename
217 std::enable_if<std::is_constructible<value_type,
218 _Pair&&>::value>::type>
219 std::pair<iterator, bool>
220 insert(_Pair&& __obj)
222 size_type __old_size = _Base::bucket_count();
223 std::pair<iterator, bool> __res
224 = _Base::insert(std::forward<_Pair>(__obj));
225 _M_profile_resize(__old_size);
229 template<typename _Pair, typename = typename
230 std::enable_if<std::is_constructible<value_type,
231 _Pair&&>::value>::type>
233 insert(const_iterator __iter, _Pair&& __v)
235 size_type __old_size = _Base::bucket_count();
236 iterator __res = _Base::insert(__iter, std::forward<_Pair>(__v));
237 _M_profile_resize(__old_size);
241 template<typename _InputIter>
243 insert(_InputIter __first, _InputIter __last)
245 size_type __old_size = _Base::bucket_count();
246 _Base::insert(__first, __last);
247 _M_profile_resize(__old_size);
251 insert(const value_type* __first, const value_type* __last)
253 size_type __old_size = _Base::bucket_count();
254 _Base::insert(__first, __last);
255 _M_profile_resize(__old_size);
260 operator[](const _Key& __k)
262 size_type __old_size = _Base::bucket_count();
263 mapped_type& __res = _M_base()[__k];
264 _M_profile_resize(__old_size);
269 operator[](_Key&& __k)
271 size_type __old_size = _Base::bucket_count();
272 mapped_type& __res = _M_base()[std::move(__k)];
273 _M_profile_resize(__old_size);
278 swap(unordered_map& __x)
279 { _Base::swap(__x); }
281 void rehash(size_type __n)
283 size_type __old_size = _Base::bucket_count();
285 _M_profile_resize(__old_size);
290 _M_profile_resize(size_type __old_size)
292 size_type __new_size = _Base::bucket_count();
293 if (__old_size != __new_size)
294 __profcxx_hashtable_resize(this, __old_size, __new_size);
298 _M_profile_destruct()
300 size_type __hops = 0, __lc = 0, __chain = 0;
301 iterator __it = this->begin();
302 while (__it != this->end())
304 size_type __bkt = this->bucket(__it->first);
305 auto __lit = this->begin(__bkt);
306 auto __lend = this->end(__bkt);
307 for (++__it, ++__lit; __lit != __lend; ++__it, ++__lit)
312 __lc = __lc > __chain ? __lc : __chain;
313 __hops += __chain * (__chain - 1) / 2;
317 __profcxx_hashtable_destruct2(this, __lc, _Base::size(), __hops);
321 template<typename _Key, typename _Tp, typename _Hash,
322 typename _Pred, typename _Alloc>
324 swap(unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
325 unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
328 template<typename _Key, typename _Tp, typename _Hash,
329 typename _Pred, typename _Alloc>
331 operator==(const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
332 const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
333 { return __x._M_equal(__y); }
335 template<typename _Key, typename _Tp, typename _Hash,
336 typename _Pred, typename _Alloc>
338 operator!=(const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
339 const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
340 { return !(__x == __y); }
343 #undef _GLIBCXX_STD_BASE
344 #define _GLIBCXX_BASE unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>
345 #define _GLIBCXX_STD_BASE _GLIBCXX_STD_C::_GLIBCXX_BASE
347 /// Class std::unordered_multimap wrapper with performance instrumentation.
348 template<typename _Key, typename _Tp,
349 typename _Hash = std::hash<_Key>,
350 typename _Pred = std::equal_to<_Key>,
351 typename _Alloc = std::allocator<_Key> >
352 class unordered_multimap
353 : public _GLIBCXX_STD_BASE
355 typedef typename _GLIBCXX_STD_BASE _Base;
358 typedef typename _Base::size_type size_type;
359 typedef typename _Base::hasher hasher;
360 typedef typename _Base::key_equal key_equal;
361 typedef typename _Base::allocator_type allocator_type;
362 typedef typename _Base::key_type key_type;
363 typedef typename _Base::value_type value_type;
364 typedef typename _Base::difference_type difference_type;
365 typedef typename _Base::reference reference;
366 typedef typename _Base::const_reference const_reference;
368 typedef typename _Base::iterator iterator;
369 typedef typename _Base::const_iterator const_iterator;
372 unordered_multimap(size_type __n = 10,
373 const hasher& __hf = hasher(),
374 const key_equal& __eql = key_equal(),
375 const allocator_type& __a = allocator_type())
376 : _Base(__n, __hf, __eql, __a)
378 __profcxx_hashtable_construct(this, _Base::bucket_count());
380 template<typename _InputIterator>
381 unordered_multimap(_InputIterator __f, _InputIterator __l,
383 const hasher& __hf = hasher(),
384 const key_equal& __eql = key_equal(),
385 const allocator_type& __a = allocator_type())
386 : _Base(__f, __l, __n, __hf, __eql, __a)
388 __profcxx_hashtable_construct(this, _Base::bucket_count());
391 unordered_multimap(const unordered_multimap& __x)
394 __profcxx_hashtable_construct(this, _Base::bucket_count());
397 unordered_multimap(const _Base& __x)
400 __profcxx_hashtable_construct(this, _Base::bucket_count());
403 unordered_multimap(unordered_multimap&& __x)
404 : _Base(std::move(__x))
406 __profcxx_hashtable_construct(this, _Base::bucket_count());
409 unordered_multimap(initializer_list<value_type> __l,
411 const hasher& __hf = hasher(),
412 const key_equal& __eql = key_equal(),
413 const allocator_type& __a = allocator_type())
414 : _Base(__l, __n, __hf, __eql, __a) { }
417 operator=(const unordered_multimap& __x)
419 *static_cast<_Base*>(this) = __x;
424 operator=(unordered_multimap&& __x)
434 operator=(initializer_list<value_type> __l)
441 ~unordered_multimap() noexcept
443 __profcxx_hashtable_destruct(this, _Base::bucket_count(),
445 _M_profile_destruct();
451 __profcxx_hashtable_destruct(this, _Base::bucket_count(),
453 _M_profile_destruct();
457 template<typename... _Args>
459 emplace(_Args&&... __args)
461 size_type __old_size = _Base::bucket_count();
463 = _Base::emplace(std::forward<_Args>(__args)...);
464 _M_profile_resize(__old_size);
468 template<typename... _Args>
470 emplace_hint(const_iterator __it, _Args&&... __args)
472 size_type __old_size = _Base::bucket_count();
474 = _Base::emplace_hint(__it, std::forward<_Args>(__args)...);
475 _M_profile_resize(__old_size);
480 insert(std::initializer_list<value_type> __l)
482 size_type __old_size = _Base::bucket_count();
484 _M_profile_resize(__old_size);
488 insert(const value_type& __obj)
490 size_type __old_size = _Base::bucket_count();
491 iterator __res = _Base::insert(__obj);
492 _M_profile_resize(__old_size);
497 insert(const_iterator __iter, const value_type& __v)
499 size_type __old_size = _Base::bucket_count();
500 iterator __res = _Base::insert(__iter, __v);
501 _M_profile_resize(__old_size);
505 template<typename _Pair, typename = typename
506 std::enable_if<std::is_constructible<value_type,
507 _Pair&&>::value>::type>
509 insert(_Pair&& __obj)
511 size_type __old_size = _Base::bucket_count();
512 iterator __res = _Base::insert(std::forward<_Pair>(__obj));
513 _M_profile_resize(__old_size);
517 template<typename _Pair, typename = typename
518 std::enable_if<std::is_constructible<value_type,
519 _Pair&&>::value>::type>
521 insert(const_iterator __iter, _Pair&& __v)
523 size_type __old_size = _Base::bucket_count();
524 iterator __res = _Base::insert(__iter, std::forward<_Pair>(__v));
525 _M_profile_resize(__old_size);
529 template<typename _InputIter>
531 insert(_InputIter __first, _InputIter __last)
533 size_type __old_size = _Base::bucket_count();
534 _Base::insert(__first, __last);
535 _M_profile_resize(__old_size);
539 insert(const value_type* __first, const value_type* __last)
541 size_type __old_size = _Base::bucket_count();
542 _Base::insert(__first, __last);
543 _M_profile_resize(__old_size);
547 swap(unordered_multimap& __x)
548 { _Base::swap(__x); }
550 void rehash(size_type __n)
552 size_type __old_size = _Base::bucket_count();
554 _M_profile_resize(__old_size);
559 _M_profile_resize(size_type __old_size)
561 size_type __new_size = _Base::bucket_count();
562 if (__old_size != __new_size)
563 __profcxx_hashtable_resize(this, __old_size, __new_size);
567 _M_profile_destruct()
569 size_type __hops = 0, __lc = 0, __chain = 0;
570 iterator __it = this->begin();
571 while (__it != this->end())
573 size_type __bkt = this->bucket(__it->first);
574 auto __lit = this->begin(__bkt);
575 auto __lend = this->end(__bkt);
576 for (++__it, ++__lit; __lit != __lend; ++__it, ++__lit)
581 __lc = __lc > __chain ? __lc : __chain;
582 __hops += __chain * (__chain - 1) / 2;
586 __profcxx_hashtable_destruct2(this, __lc, _Base::size(), __hops);
590 template<typename _Key, typename _Tp, typename _Hash,
591 typename _Pred, typename _Alloc>
593 swap(unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
594 unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
597 template<typename _Key, typename _Tp, typename _Hash,
598 typename _Pred, typename _Alloc>
600 operator==(const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
601 const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
602 { return __x._M_equal(__y); }
604 template<typename _Key, typename _Tp, typename _Hash,
605 typename _Pred, typename _Alloc>
607 operator!=(const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
608 const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
609 { return !(__x == __y); }
611 } // namespace __profile
615 #undef _GLIBCXX_STD_BASE
617 #endif // __GXX_EXPERIMENTAL_CXX0X__