1// Profiling unordered_map/unordered_multimap implementation -*- C++ -*-
2
3// Copyright (C) 2009-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_map
25 *  This file is a GNU profile extension to the Standard C++ Library.
26 */
27
28#ifndef _GLIBCXX_PROFILE_UNORDERED_MAP
29#define _GLIBCXX_PROFILE_UNORDERED_MAP 1
30
31#if __cplusplus < 201103L
32# include <bits/c++0x_warning.h>
33#else
34# include <unordered_map>
35
36#include <profile/base.h>
37#include <profile/unordered_base.h>
38
39#define _GLIBCXX_BASE unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>
40#define _GLIBCXX_STD_BASE _GLIBCXX_STD_C::_GLIBCXX_BASE
41
42namespace std _GLIBCXX_VISIBILITY(default)
43{
44namespace __profile
45{
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> > >
51    class unordered_map
52    : public _GLIBCXX_STD_BASE,
53      public _Unordered_profile<unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>,
54				true>
55    {
56      typedef typename _GLIBCXX_STD_BASE _Base;
57
58      _Base&
59      _M_base() noexcept       { return *this; }
60
61      const _Base&
62      _M_base() const noexcept { return *this; }
63
64    public:
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;
75
76      typedef typename _Base::iterator iterator;
77      typedef typename _Base::const_iterator const_iterator;
78
79      explicit
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)
85      { }
86
87      template<typename _InputIterator>
88        unordered_map(_InputIterator __f, _InputIterator __l,
89		      size_type __n = 0,
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)
94        { }
95
96      unordered_map(const unordered_map&) = default;
97
98      unordered_map(const _Base& __x)
99	: _Base(__x)
100      { }
101
102      unordered_map(unordered_map&&) = default;
103
104      explicit
105      unordered_map(const allocator_type& __a)
106	: _Base(__a)
107      { }
108
109      unordered_map(const unordered_map& __umap,
110		    const allocator_type& __a)
111	: _Base(__umap, __a)
112      { }
113
114      unordered_map(unordered_map&& __umap,
115		    const allocator_type& __a)
116	: _Base(std::move(__umap._M_base()), __a)
117      { }
118
119      unordered_map(initializer_list<value_type> __l,
120		    size_type __n = 0,
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)
125      { }
126
127      unordered_map&
128      operator=(const unordered_map&) = default;
129
130      unordered_map&
131      operator=(unordered_map&&) = default;
132
133      unordered_map&
134      operator=(initializer_list<value_type> __l)
135      {
136	_M_base() = __l;
137	return *this;
138      }
139
140      void
141      clear() noexcept
142      {
143        __profcxx_hashtable_destruct(this, _Base::bucket_count(),
144				     _Base::size());
145        this->_M_profile_destruct();
146	_Base::clear();
147      }
148
149      template<typename... _Args>
150	std::pair<iterator, bool>
151	emplace(_Args&&... __args)
152	{
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);
157	  return __res;
158	}
159
160      template<typename... _Args>
161	iterator
162	emplace_hint(const_iterator __it, _Args&&... __args)
163	{
164	  size_type __old_size = _Base::bucket_count();
165	  iterator __res
166	    = _Base::emplace_hint(__it, std::forward<_Args>(__args)...);
167	  _M_profile_resize(__old_size);
168	  return __res;
169	}
170
171      void
172      insert(std::initializer_list<value_type> __l)
173      {
174        size_type __old_size = _Base::bucket_count();
175        _Base::insert(__l);
176        _M_profile_resize(__old_size);
177      }
178
179      std::pair<iterator, bool>
180      insert(const value_type& __obj)
181      {
182        size_type __old_size = _Base::bucket_count();
183        std::pair<iterator, bool> __res = _Base::insert(__obj);
184        _M_profile_resize(__old_size);
185        return __res;
186      }
187
188      iterator
189      insert(const_iterator __iter, const value_type& __v)
190      {
191        size_type __old_size = _Base::bucket_count();
192        iterator __res = _Base::insert(__iter, __v);
193        _M_profile_resize(__old_size);
194        return __res;
195      }
196
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)
202        {
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);
207	  return __res;
208	}
209
210      template<typename _Pair, typename = typename
211	       std::enable_if<std::is_constructible<value_type,
212						    _Pair&&>::value>::type>
213        iterator
214        insert(const_iterator __iter, _Pair&& __v)
215        {
216	  size_type __old_size = _Base::bucket_count();
217	  iterator __res = _Base::insert(__iter, std::forward<_Pair>(__v));
218	  _M_profile_resize(__old_size);
219	  return __res;
220	}
221
222      template<typename _InputIter>
223        void
224        insert(_InputIter __first, _InputIter __last)
225        {
226	  size_type __old_size = _Base::bucket_count();
227	  _Base::insert(__first, __last);
228	  _M_profile_resize(__old_size);
229	}
230
231      // operator[]
232      mapped_type&
233      operator[](const _Key& __k)
234      {
235        size_type __old_size = _Base::bucket_count();
236        mapped_type& __res = _M_base()[__k];
237        _M_profile_resize(__old_size);
238        return __res;
239      }
240
241      mapped_type&
242      operator[](_Key&& __k)
243      {
244        size_type __old_size = _Base::bucket_count();
245        mapped_type& __res = _M_base()[std::move(__k)];
246        _M_profile_resize(__old_size);
247        return __res;
248      }
249
250      void
251      swap(unordered_map& __x)
252      noexcept( noexcept(__x._M_base().swap(__x)) )
253      { _Base::swap(__x._M_base()); }
254
255      void rehash(size_type __n)
256      {
257	size_type __old_size = _Base::bucket_count();
258	_Base::rehash(__n);
259	_M_profile_resize(__old_size);
260      }
261
262    private:
263      void
264      _M_profile_resize(size_type __old_size)
265      {
266	size_type __new_size = _Base::bucket_count();
267	if (__old_size != __new_size)
268	  __profcxx_hashtable_resize(this, __old_size, __new_size);
269      }
270  };
271
272  template<typename _Key, typename _Tp, typename _Hash,
273	   typename _Pred, typename _Alloc>
274    inline void
275    swap(unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
276	 unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
277    { __x.swap(__y); }
278
279  template<typename _Key, typename _Tp, typename _Hash,
280	   typename _Pred, typename _Alloc>
281    inline bool
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; }
285
286  template<typename _Key, typename _Tp, typename _Hash,
287	   typename _Pred, typename _Alloc>
288    inline bool
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); }
292
293#undef _GLIBCXX_BASE
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
297
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>,
307				false>
308    {
309      typedef typename _GLIBCXX_STD_BASE _Base;
310
311      _Base&
312      _M_base() noexcept       { return *this; }
313
314      const _Base&
315      _M_base() const noexcept { return *this; }
316
317    public:
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;
327
328      typedef typename _Base::iterator iterator;
329      typedef typename _Base::const_iterator const_iterator;
330
331      explicit
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)
337      { }
338
339      template<typename _InputIterator>
340        unordered_multimap(_InputIterator __f, _InputIterator __l,
341			   size_type __n = 0,
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)
346      { }
347
348      unordered_multimap(const unordered_multimap&) = default;
349
350      unordered_multimap(const _Base& __x)
351	: _Base(__x)
352      { }
353
354      unordered_multimap(unordered_multimap&&) = default;
355
356      explicit
357      unordered_multimap(const allocator_type& __a)
358	: _Base(__a)
359      { }
360
361      unordered_multimap(const unordered_multimap& __ummap,
362			 const allocator_type& __a)
363	: _Base(__ummap._M_base(), __a)
364      { }
365
366      unordered_multimap(unordered_multimap&& __ummap,
367			 const allocator_type& __a)
368	: _Base(std::move(__ummap._M_base()), __a)
369      { }
370
371      unordered_multimap(initializer_list<value_type> __l,
372			 size_type __n = 0,
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)
377      { }
378
379      unordered_multimap&
380      operator=(const unordered_multimap&) = default;
381
382      unordered_multimap&
383      operator=(unordered_multimap&&) = default;
384
385      unordered_multimap&
386      operator=(initializer_list<value_type> __l)
387      {
388	_M_base() = __l;
389	return *this;
390      }
391
392      void
393      clear() noexcept
394      {
395	__profcxx_hashtable_destruct(this, _Base::bucket_count(),
396				     _Base::size());
397	this->_M_profile_destruct();
398	_Base::clear();
399      }
400
401      template<typename... _Args>
402	iterator
403	emplace(_Args&&... __args)
404	{
405	  size_type __old_size = _Base::bucket_count();
406	  iterator __res
407	    = _Base::emplace(std::forward<_Args>(__args)...);
408	  _M_profile_resize(__old_size);
409	  return __res;
410	}
411
412      template<typename... _Args>
413	iterator
414	emplace_hint(const_iterator __it, _Args&&... __args)
415	{
416	  size_type __old_size = _Base::bucket_count();
417	  iterator __res
418	    = _Base::emplace_hint(__it, std::forward<_Args>(__args)...);
419	  _M_profile_resize(__old_size);
420	  return __res;
421	}
422
423      void
424      insert(std::initializer_list<value_type> __l)
425      {
426        size_type __old_size = _Base::bucket_count();
427        _Base::insert(__l);
428        _M_profile_resize(__old_size);
429      }
430
431      iterator
432      insert(const value_type& __obj)
433      {
434        size_type __old_size = _Base::bucket_count();
435        iterator __res = _Base::insert(__obj);
436        _M_profile_resize(__old_size);
437        return __res;
438      }
439
440      iterator
441      insert(const_iterator __iter, const value_type& __v)
442      {
443        size_type __old_size = _Base::bucket_count();
444        iterator __res = _Base::insert(__iter, __v);
445        _M_profile_resize(__old_size);
446        return __res;
447      }
448
449      template<typename _Pair, typename = typename
450	       std::enable_if<std::is_constructible<value_type,
451						    _Pair&&>::value>::type>
452        iterator
453        insert(_Pair&& __obj)
454        {
455	  size_type __old_size = _Base::bucket_count();
456	  iterator __res = _Base::insert(std::forward<_Pair>(__obj));
457	  _M_profile_resize(__old_size);
458	  return __res;
459	}
460
461      template<typename _Pair, typename = typename
462	       std::enable_if<std::is_constructible<value_type,
463						    _Pair&&>::value>::type>
464        iterator
465        insert(const_iterator __iter, _Pair&& __v)
466        {
467	  size_type __old_size = _Base::bucket_count();
468	  iterator __res = _Base::insert(__iter, std::forward<_Pair>(__v));
469	  _M_profile_resize(__old_size);
470	  return __res;
471	}
472
473      template<typename _InputIter>
474        void
475        insert(_InputIter __first, _InputIter __last)
476        {
477	  size_type __old_size = _Base::bucket_count();
478	  _Base::insert(__first, __last);
479	  _M_profile_resize(__old_size);
480	}
481
482      void
483      swap(unordered_multimap& __x)
484      noexcept( noexcept(__x._M_base().swap(__x)) )
485      { _Base::swap(__x._M_base()); }
486
487      void
488      rehash(size_type __n)
489      {
490        size_type __old_size = _Base::bucket_count();
491        _Base::rehash(__n);
492        _M_profile_resize(__old_size);
493      }
494
495    private:
496      void
497      _M_profile_resize(size_type __old_size)
498      {
499	size_type __new_size = _Base::bucket_count();
500        if (__old_size != __new_size)
501          __profcxx_hashtable_resize(this, __old_size, __new_size);
502      }
503  };
504
505  template<typename _Key, typename _Tp, typename _Hash,
506	   typename _Pred, typename _Alloc>
507    inline void
508    swap(unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
509	 unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
510    { __x.swap(__y); }
511
512  template<typename _Key, typename _Tp, typename _Hash,
513	   typename _Pred, typename _Alloc>
514    inline bool
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; }
518
519  template<typename _Key, typename _Tp, typename _Hash,
520	   typename _Pred, typename _Alloc>
521    inline bool
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); }
525
526} // namespace __profile
527} // namespace std
528
529#undef _GLIBCXX_BASE
530#undef _GLIBCXX_STD_BASE
531
532#endif // C++11
533
534#endif
535