1 // Profiling unordered_map/unordered_multimap implementation -*- C++ -*-
3 // Copyright (C) 2009-2014 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 #if __cplusplus < 201103L
32 # include <bits/c++0x_warning.h>
34 # include <unordered_map>
36 #include <profile/base.h>
37 #include <profile/unordered_base.h>
39 #define _GLIBCXX_BASE unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>
40 #define _GLIBCXX_STD_BASE _GLIBCXX_STD_C::_GLIBCXX_BASE
42 namespace std _GLIBCXX_VISIBILITY(default)
46 /// Class std::unordered_map wrapper with performance instrumentation.
47 template<typename _Key, typename _Tp,
48 typename _Hash = std::hash<_Key>,
49 typename _Pred = std::equal_to<_Key>,
50 typename _Alloc = std::allocator<std::pair<const _Key, _Tp> > >
52 : public _GLIBCXX_STD_BASE,
53 public _Unordered_profile<unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>,
56 typedef typename _GLIBCXX_STD_BASE _Base;
59 _M_base() noexcept { return *this; }
62 _M_base() const noexcept { return *this; }
65 typedef typename _Base::size_type size_type;
66 typedef typename _Base::hasher hasher;
67 typedef typename _Base::key_equal key_equal;
68 typedef typename _Base::allocator_type allocator_type;
69 typedef typename _Base::key_type key_type;
70 typedef typename _Base::value_type value_type;
71 typedef typename _Base::difference_type difference_type;
72 typedef typename _Base::reference reference;
73 typedef typename _Base::const_reference const_reference;
74 typedef typename _Base::mapped_type mapped_type;
76 typedef typename _Base::iterator iterator;
77 typedef typename _Base::const_iterator const_iterator;
80 unordered_map(size_type __n = 10,
81 const hasher& __hf = hasher(),
82 const key_equal& __eql = key_equal(),
83 const allocator_type& __a = allocator_type())
84 : _Base(__n, __hf, __eql, __a)
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)
96 unordered_map(const unordered_map&) = default;
98 unordered_map(const _Base& __x)
102 unordered_map(unordered_map&&) = default;
105 unordered_map(const allocator_type& __a)
109 unordered_map(const unordered_map& __umap,
110 const allocator_type& __a)
114 unordered_map(unordered_map&& __umap,
115 const allocator_type& __a)
116 : _Base(std::move(__umap._M_base()), __a)
119 unordered_map(initializer_list<value_type> __l,
121 const hasher& __hf = hasher(),
122 const key_equal& __eql = key_equal(),
123 const allocator_type& __a = allocator_type())
124 : _Base(__l, __n, __hf, __eql, __a)
128 operator=(const unordered_map&) = default;
131 operator=(unordered_map&&) = default;
134 operator=(initializer_list<value_type> __l)
143 __profcxx_hashtable_destruct(this, _Base::bucket_count(),
145 this->_M_profile_destruct();
149 template<typename... _Args>
150 std::pair<iterator, bool>
151 emplace(_Args&&... __args)
153 size_type __old_size = _Base::bucket_count();
154 std::pair<iterator, bool> __res
155 = _Base::emplace(std::forward<_Args>(__args)...);
156 _M_profile_resize(__old_size);
160 template<typename... _Args>
162 emplace_hint(const_iterator __it, _Args&&... __args)
164 size_type __old_size = _Base::bucket_count();
166 = _Base::emplace_hint(__it, std::forward<_Args>(__args)...);
167 _M_profile_resize(__old_size);
172 insert(std::initializer_list<value_type> __l)
174 size_type __old_size = _Base::bucket_count();
176 _M_profile_resize(__old_size);
179 std::pair<iterator, bool>
180 insert(const value_type& __obj)
182 size_type __old_size = _Base::bucket_count();
183 std::pair<iterator, bool> __res = _Base::insert(__obj);
184 _M_profile_resize(__old_size);
189 insert(const_iterator __iter, const value_type& __v)
191 size_type __old_size = _Base::bucket_count();
192 iterator __res = _Base::insert(__iter, __v);
193 _M_profile_resize(__old_size);
197 template<typename _Pair, typename = typename
198 std::enable_if<std::is_constructible<value_type,
199 _Pair&&>::value>::type>
200 std::pair<iterator, bool>
201 insert(_Pair&& __obj)
203 size_type __old_size = _Base::bucket_count();
204 std::pair<iterator, bool> __res
205 = _Base::insert(std::forward<_Pair>(__obj));
206 _M_profile_resize(__old_size);
210 template<typename _Pair, typename = typename
211 std::enable_if<std::is_constructible<value_type,
212 _Pair&&>::value>::type>
214 insert(const_iterator __iter, _Pair&& __v)
216 size_type __old_size = _Base::bucket_count();
217 iterator __res = _Base::insert(__iter, std::forward<_Pair>(__v));
218 _M_profile_resize(__old_size);
222 template<typename _InputIter>
224 insert(_InputIter __first, _InputIter __last)
226 size_type __old_size = _Base::bucket_count();
227 _Base::insert(__first, __last);
228 _M_profile_resize(__old_size);
233 operator[](const _Key& __k)
235 size_type __old_size = _Base::bucket_count();
236 mapped_type& __res = _M_base()[__k];
237 _M_profile_resize(__old_size);
242 operator[](_Key&& __k)
244 size_type __old_size = _Base::bucket_count();
245 mapped_type& __res = _M_base()[std::move(__k)];
246 _M_profile_resize(__old_size);
251 swap(unordered_map& __x)
252 noexcept( noexcept(__x._M_base().swap(__x)) )
253 { _Base::swap(__x._M_base()); }
255 void rehash(size_type __n)
257 size_type __old_size = _Base::bucket_count();
259 _M_profile_resize(__old_size);
264 _M_profile_resize(size_type __old_size)
266 size_type __new_size = _Base::bucket_count();
267 if (__old_size != __new_size)
268 __profcxx_hashtable_resize(this, __old_size, __new_size);
272 template<typename _Key, typename _Tp, typename _Hash,
273 typename _Pred, typename _Alloc>
275 swap(unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
276 unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
279 template<typename _Key, typename _Tp, typename _Hash,
280 typename _Pred, typename _Alloc>
282 operator==(const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
283 const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
284 { return static_cast<const _GLIBCXX_STD_BASE&>(__x) == __y; }
286 template<typename _Key, typename _Tp, typename _Hash,
287 typename _Pred, typename _Alloc>
289 operator!=(const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
290 const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
291 { return !(__x == __y); }
294 #undef _GLIBCXX_STD_BASE
295 #define _GLIBCXX_BASE unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>
296 #define _GLIBCXX_STD_BASE _GLIBCXX_STD_C::_GLIBCXX_BASE
298 /// Class std::unordered_multimap wrapper with performance instrumentation.
299 template<typename _Key, typename _Tp,
300 typename _Hash = std::hash<_Key>,
301 typename _Pred = std::equal_to<_Key>,
302 typename _Alloc = std::allocator<std::pair<const _Key, _Tp> > >
303 class unordered_multimap
304 : public _GLIBCXX_STD_BASE,
305 public _Unordered_profile<unordered_multimap<_Key, _Tp,
306 _Hash, _Pred, _Alloc>,
309 typedef typename _GLIBCXX_STD_BASE _Base;
312 _M_base() noexcept { return *this; }
315 _M_base() const noexcept { return *this; }
318 typedef typename _Base::size_type size_type;
319 typedef typename _Base::hasher hasher;
320 typedef typename _Base::key_equal key_equal;
321 typedef typename _Base::allocator_type allocator_type;
322 typedef typename _Base::key_type key_type;
323 typedef typename _Base::value_type value_type;
324 typedef typename _Base::difference_type difference_type;
325 typedef typename _Base::reference reference;
326 typedef typename _Base::const_reference const_reference;
328 typedef typename _Base::iterator iterator;
329 typedef typename _Base::const_iterator const_iterator;
332 unordered_multimap(size_type __n = 10,
333 const hasher& __hf = hasher(),
334 const key_equal& __eql = key_equal(),
335 const allocator_type& __a = allocator_type())
336 : _Base(__n, __hf, __eql, __a)
339 template<typename _InputIterator>
340 unordered_multimap(_InputIterator __f, _InputIterator __l,
342 const hasher& __hf = hasher(),
343 const key_equal& __eql = key_equal(),
344 const allocator_type& __a = allocator_type())
345 : _Base(__f, __l, __n, __hf, __eql, __a)
348 unordered_multimap(const unordered_multimap&) = default;
350 unordered_multimap(const _Base& __x)
354 unordered_multimap(unordered_multimap&&) = default;
357 unordered_multimap(const allocator_type& __a)
361 unordered_multimap(const unordered_multimap& __ummap,
362 const allocator_type& __a)
363 : _Base(__ummap._M_base(), __a)
366 unordered_multimap(unordered_multimap&& __ummap,
367 const allocator_type& __a)
368 : _Base(std::move(__ummap._M_base()), __a)
371 unordered_multimap(initializer_list<value_type> __l,
373 const hasher& __hf = hasher(),
374 const key_equal& __eql = key_equal(),
375 const allocator_type& __a = allocator_type())
376 : _Base(__l, __n, __hf, __eql, __a)
380 operator=(const unordered_multimap&) = default;
383 operator=(unordered_multimap&&) = default;
386 operator=(initializer_list<value_type> __l)
395 __profcxx_hashtable_destruct(this, _Base::bucket_count(),
397 this->_M_profile_destruct();
401 template<typename... _Args>
403 emplace(_Args&&... __args)
405 size_type __old_size = _Base::bucket_count();
407 = _Base::emplace(std::forward<_Args>(__args)...);
408 _M_profile_resize(__old_size);
412 template<typename... _Args>
414 emplace_hint(const_iterator __it, _Args&&... __args)
416 size_type __old_size = _Base::bucket_count();
418 = _Base::emplace_hint(__it, std::forward<_Args>(__args)...);
419 _M_profile_resize(__old_size);
424 insert(std::initializer_list<value_type> __l)
426 size_type __old_size = _Base::bucket_count();
428 _M_profile_resize(__old_size);
432 insert(const value_type& __obj)
434 size_type __old_size = _Base::bucket_count();
435 iterator __res = _Base::insert(__obj);
436 _M_profile_resize(__old_size);
441 insert(const_iterator __iter, const value_type& __v)
443 size_type __old_size = _Base::bucket_count();
444 iterator __res = _Base::insert(__iter, __v);
445 _M_profile_resize(__old_size);
449 template<typename _Pair, typename = typename
450 std::enable_if<std::is_constructible<value_type,
451 _Pair&&>::value>::type>
453 insert(_Pair&& __obj)
455 size_type __old_size = _Base::bucket_count();
456 iterator __res = _Base::insert(std::forward<_Pair>(__obj));
457 _M_profile_resize(__old_size);
461 template<typename _Pair, typename = typename
462 std::enable_if<std::is_constructible<value_type,
463 _Pair&&>::value>::type>
465 insert(const_iterator __iter, _Pair&& __v)
467 size_type __old_size = _Base::bucket_count();
468 iterator __res = _Base::insert(__iter, std::forward<_Pair>(__v));
469 _M_profile_resize(__old_size);
473 template<typename _InputIter>
475 insert(_InputIter __first, _InputIter __last)
477 size_type __old_size = _Base::bucket_count();
478 _Base::insert(__first, __last);
479 _M_profile_resize(__old_size);
483 swap(unordered_multimap& __x)
484 noexcept( noexcept(__x._M_base().swap(__x)) )
485 { _Base::swap(__x._M_base()); }
488 rehash(size_type __n)
490 size_type __old_size = _Base::bucket_count();
492 _M_profile_resize(__old_size);
497 _M_profile_resize(size_type __old_size)
499 size_type __new_size = _Base::bucket_count();
500 if (__old_size != __new_size)
501 __profcxx_hashtable_resize(this, __old_size, __new_size);
505 template<typename _Key, typename _Tp, typename _Hash,
506 typename _Pred, typename _Alloc>
508 swap(unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
509 unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
512 template<typename _Key, typename _Tp, typename _Hash,
513 typename _Pred, typename _Alloc>
515 operator==(const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
516 const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
517 { return static_cast<const _GLIBCXX_STD_BASE&>(__x) == __y; }
519 template<typename _Key, typename _Tp, typename _Hash,
520 typename _Pred, typename _Alloc>
522 operator!=(const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
523 const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
524 { return !(__x == __y); }
526 } // namespace __profile
530 #undef _GLIBCXX_STD_BASE