1// Profiling unordered_set/unordered_multiset 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_set
25 *  This file is a GNU profile extension to the Standard C++ Library.
26 */
27
28#ifndef _GLIBCXX_PROFILE_UNORDERED_SET
29#define _GLIBCXX_PROFILE_UNORDERED_SET 1
30
31#if __cplusplus < 201103L
32# include <bits/c++0x_warning.h>
33#else
34# include <unordered_set>
35
36#include <profile/base.h>
37#include <profile/unordered_base.h>
38
39#define _GLIBCXX_BASE unordered_set<_Key, _Hash, _Pred, _Alloc>
40#define _GLIBCXX_STD_BASE _GLIBCXX_STD_C::_GLIBCXX_BASE
41
42namespace std _GLIBCXX_VISIBILITY(default)
43{
44namespace __profile
45{
46  /** @brief Unordered_set wrapper with performance instrumentation.  */
47  template<typename _Key,
48	   typename _Hash = std::hash<_Key>,
49	   typename _Pred = std::equal_to<_Key>,
50	   typename _Alloc =  std::allocator<_Key> >
51    class unordered_set
52    : public _GLIBCXX_STD_BASE,
53      public _Unordered_profile<unordered_set<_Key, _Hash, _Pred, _Alloc>,
54				true>
55    {
56      typedef _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
75      typedef typename _Base::iterator iterator;
76      typedef typename _Base::const_iterator const_iterator;
77
78      explicit
79      unordered_set(size_type __n = 10,
80		    const hasher& __hf = hasher(),
81		    const key_equal& __eql = key_equal(),
82		    const allocator_type& __a = allocator_type())
83	: _Base(__n, __hf, __eql, __a)
84      { }
85
86      template<typename _InputIterator>
87        unordered_set(_InputIterator __f, _InputIterator __l,
88		      size_type __n = 0,
89		      const hasher& __hf = hasher(),
90		      const key_equal& __eql = key_equal(),
91		      const allocator_type& __a = allocator_type())
92	  : _Base(__f, __l, __n, __hf, __eql, __a)
93      { }
94
95      unordered_set(const unordered_set&) = default;
96
97      unordered_set(const _Base& __x)
98	: _Base(__x)
99      { }
100
101      unordered_set(unordered_set&&) = default;
102
103      explicit
104      unordered_set(const allocator_type& __a)
105	: _Base(__a)
106      { }
107
108      unordered_set(const unordered_set& __uset,
109		    const allocator_type& __a)
110	: _Base(__uset._M_base(), __a)
111      { }
112
113      unordered_set(unordered_set&& __uset,
114		    const allocator_type& __a)
115	: _Base(std::move(__uset._M_base()), __a)
116      { }
117
118      unordered_set(initializer_list<value_type> __l,
119		    size_type __n = 0,
120		    const hasher& __hf = hasher(),
121		    const key_equal& __eql = key_equal(),
122		    const allocator_type& __a = allocator_type())
123      : _Base(__l, __n, __hf, __eql, __a)
124      { }
125
126      unordered_set&
127      operator=(const unordered_set&) = default;
128
129      unordered_set&
130      operator=(unordered_set&&) = default;
131
132      unordered_set&
133      operator=(initializer_list<value_type> __l)
134      {
135	_M_base() = __l;
136	return *this;
137      }
138
139      void
140      swap(unordered_set& __x)
141      noexcept( noexcept(__x._M_base().swap(__x)) )
142      { _Base::swap(__x); }
143
144      void
145      clear() noexcept
146      {
147        __profcxx_hashtable_destruct(this, _Base::bucket_count(),
148                                     _Base::size());
149        this->_M_profile_destruct();
150        _Base::clear();
151      }
152
153      template<typename... _Args>
154	std::pair<iterator, bool>
155	emplace(_Args&&... __args)
156	{
157	  size_type __old_size = _Base::bucket_count();
158	  std::pair<iterator, bool> __res
159	    = _Base::emplace(std::forward<_Args>(__args)...);
160	  _M_profile_resize(__old_size);
161	  return __res;
162	}
163
164      template<typename... _Args>
165	iterator
166	emplace_hint(const_iterator __it, _Args&&... __args)
167	{
168	  size_type __old_size = _Base::bucket_count();
169	  iterator __res
170	    = _Base::emplace_hint(__it, std::forward<_Args>(__args)...);
171	  _M_profile_resize(__old_size);
172	  return __res;
173	}
174
175      void
176      insert(std::initializer_list<value_type> __l)
177      {
178        size_type __old_size = _Base::bucket_count();
179        _Base::insert(__l);
180        _M_profile_resize(__old_size);
181      }
182
183      std::pair<iterator, bool>
184      insert(const value_type& __obj)
185      {
186        size_type __old_size = _Base::bucket_count();
187        std::pair<iterator, bool> __res = _Base::insert(__obj);
188        _M_profile_resize(__old_size);
189        return __res;
190      }
191
192      iterator
193      insert(const_iterator __iter, const value_type& __v)
194      {
195        size_type __old_size = _Base::bucket_count();
196        iterator __res = _Base::insert(__iter, __v);
197        _M_profile_resize(__old_size);
198        return __res;
199      }
200
201      std::pair<iterator, bool>
202      insert(value_type&& __obj)
203      {
204        size_type __old_size = _Base::bucket_count();
205        std::pair<iterator, bool> __res = _Base::insert(std::move(__obj));
206        _M_profile_resize(__old_size);
207        return __res;
208      }
209
210      iterator
211      insert(const_iterator __iter, value_type&& __v)
212      {
213        size_type __old_size = _Base::bucket_count();
214        iterator __res = _Base::insert(__iter, std::move(__v));
215        _M_profile_resize(__old_size);
216        return __res;
217      }
218
219      template<typename _InputIter>
220        void
221        insert(_InputIter __first, _InputIter __last)
222        {
223	  size_type __old_size = _Base::bucket_count();
224	  _Base::insert(__first, __last);
225	  _M_profile_resize(__old_size);
226	}
227
228      void
229      rehash(size_type __n)
230      {
231        size_type __old_size = _Base::bucket_count();
232        _Base::rehash(__n);
233        _M_profile_resize(__old_size);
234      }
235
236    private:
237      void
238      _M_profile_resize(size_type __old_size)
239      {
240	size_type __new_size = _Base::bucket_count();
241	if (__old_size != __new_size)
242	  __profcxx_hashtable_resize(this, __old_size, __new_size);
243      }
244  };
245
246  template<typename _Key, typename _Hash, typename _Pred, typename _Alloc>
247    inline void
248    swap(unordered_set<_Key, _Hash, _Pred, _Alloc>& __x,
249	 unordered_set<_Key, _Hash, _Pred, _Alloc>& __y)
250    { __x.swap(__y); }
251
252  template<typename _Key, typename _Hash, typename _Pred, typename _Alloc>
253    inline bool
254    operator==(const unordered_set<_Key, _Hash, _Pred, _Alloc>& __x,
255	       const unordered_set<_Key, _Hash, _Pred, _Alloc>& __y)
256    { return static_cast<const _GLIBCXX_STD_BASE&>(__x) == __y; }
257
258  template<typename _Key, typename _Hash, typename _Pred, typename _Alloc>
259    inline bool
260    operator!=(const unordered_set<_Key, _Hash, _Pred, _Alloc>& __x,
261	       const unordered_set<_Key, _Hash, _Pred, _Alloc>& __y)
262    { return !(__x == __y); }
263
264#undef _GLIBCXX_BASE
265#undef _GLIBCXX_STD_BASE
266#define _GLIBCXX_STD_BASE _GLIBCXX_STD_C::_GLIBCXX_BASE
267#define _GLIBCXX_BASE unordered_multiset<_Value, _Hash, _Pred, _Alloc>
268
269  /** @brief Unordered_multiset wrapper with performance instrumentation.  */
270  template<typename _Value,
271	   typename _Hash = std::hash<_Value>,
272	   typename _Pred = std::equal_to<_Value>,
273	   typename _Alloc =  std::allocator<_Value> >
274    class unordered_multiset
275    : public _GLIBCXX_STD_BASE,
276      public _Unordered_profile<unordered_multiset<_Value,
277						   _Hash, _Pred, _Alloc>,
278				false>
279    {
280      typedef _GLIBCXX_STD_BASE _Base;
281
282      _Base&
283      _M_base() noexcept       { return *this; }
284
285      const _Base&
286      _M_base() const noexcept { return *this; }
287
288    public:
289      typedef typename _Base::size_type       size_type;
290      typedef typename _Base::hasher          hasher;
291      typedef typename _Base::key_equal       key_equal;
292      typedef typename _Base::allocator_type  allocator_type;
293      typedef typename _Base::key_type        key_type;
294      typedef typename _Base::value_type      value_type;
295      typedef typename _Base::difference_type difference_type;
296      typedef typename _Base::reference       reference;
297      typedef typename _Base::const_reference const_reference;
298
299      typedef typename _Base::iterator iterator;
300      typedef typename _Base::const_iterator const_iterator;
301
302      explicit
303      unordered_multiset(size_type __n = 10,
304			 const hasher& __hf = hasher(),
305			 const key_equal& __eql = key_equal(),
306			 const allocator_type& __a = allocator_type())
307	: _Base(__n, __hf, __eql, __a)
308      { }
309
310      template<typename _InputIterator>
311        unordered_multiset(_InputIterator __f, _InputIterator __l,
312			   size_type __n = 0,
313			   const hasher& __hf = hasher(),
314			   const key_equal& __eql = key_equal(),
315			   const allocator_type& __a = allocator_type())
316	  : _Base(__f, __l, __n, __hf, __eql, __a)
317      { }
318
319      unordered_multiset(const unordered_multiset&) = default;
320
321      unordered_multiset(const _Base& __x)
322	: _Base(__x)
323      { }
324
325      unordered_multiset(unordered_multiset&&) = default;
326
327      explicit
328      unordered_multiset(const allocator_type& __a)
329	: _Base(__a)
330      { }
331
332      unordered_multiset(const unordered_multiset& __umset,
333			 const allocator_type& __a)
334	: _Base(__umset._M_base(), __a)
335      { }
336
337      unordered_multiset(unordered_multiset&& __umset,
338			 const allocator_type& __a)
339	: _Base(std::move(__umset._M_base()), __a)
340      { }
341
342      unordered_multiset(initializer_list<value_type> __l,
343			 size_type __n = 0,
344			 const hasher& __hf = hasher(),
345			 const key_equal& __eql = key_equal(),
346			 const allocator_type& __a = allocator_type())
347	: _Base(__l, __n, __hf, __eql, __a)
348      { }
349
350      unordered_multiset&
351      operator=(const unordered_multiset&) = default;
352
353      unordered_multiset&
354      operator=(unordered_multiset&&) = default;
355
356      unordered_multiset&
357      operator=(initializer_list<value_type> __l)
358      {
359	_M_base() = __l;
360	return *this;
361      }
362
363      void
364      swap(unordered_multiset& __x)
365      noexcept( noexcept(__x._M_base().swap(__x)) )
366      { _Base::swap(__x); }
367
368      void
369      clear() noexcept
370      {
371        __profcxx_hashtable_destruct(this, _Base::bucket_count(),
372                                     _Base::size());
373        this->_M_profile_destruct();
374        _Base::clear();
375      }
376
377      template<typename... _Args>
378	iterator
379	emplace(_Args&&... __args)
380	{
381	  size_type __old_size = _Base::bucket_count();
382	  iterator __res = _Base::emplace(std::forward<_Args>(__args)...);
383	  _M_profile_resize(__old_size);
384	  return __res;
385	}
386
387      template<typename... _Args>
388	iterator
389	emplace_hint(const_iterator __it, _Args&&... __args)
390	{
391	  size_type __old_size = _Base::bucket_count();
392	  iterator __res
393	    = _Base::emplace_hint(__it, std::forward<_Args>(__args)...);
394	  _M_profile_resize(__old_size);
395	  return __res;
396	}
397
398      void
399      insert(std::initializer_list<value_type> __l)
400      {
401        size_type __old_size = _Base::bucket_count();
402        _Base::insert(__l);
403        _M_profile_resize(__old_size);
404      }
405
406      iterator
407      insert(const value_type& __obj)
408      {
409        size_type __old_size = _Base::bucket_count();
410        iterator __res = _Base::insert(__obj);
411        _M_profile_resize(__old_size);
412        return __res;
413      }
414
415      iterator
416      insert(const_iterator __iter, const value_type& __v)
417      {
418        size_type __old_size = _Base::bucket_count();
419        iterator __res = _Base::insert(__iter, __v);
420        _M_profile_resize(__old_size);
421        return __res;
422      }
423
424      iterator
425      insert(value_type&& __obj)
426      {
427	size_type __old_size = _Base::bucket_count();
428        iterator __res = _Base::insert(std::move(__obj));
429        _M_profile_resize(__old_size);
430        return __res;
431      }
432
433      iterator
434      insert(const_iterator __iter, value_type&& __v)
435      {
436        size_type __old_size = _Base::bucket_count();
437        iterator __res = _Base::insert(__iter, std::move(__v));
438        _M_profile_resize(__old_size);
439        return __res;
440      }
441
442      template<typename _InputIter>
443        void
444        insert(_InputIter __first, _InputIter __last)
445        {
446	  size_type __old_size = _Base::bucket_count();
447	  _Base::insert(__first, __last);
448	  _M_profile_resize(__old_size);
449	}
450
451      void
452      rehash(size_type __n)
453      {
454        size_type __old_size = _Base::bucket_count();
455        _Base::rehash(__n);
456        _M_profile_resize(__old_size);
457      }
458
459    private:
460      void
461      _M_profile_resize(size_type __old_size)
462      {
463	size_type __new_size = _Base::bucket_count();
464        if (__old_size != __new_size)
465          __profcxx_hashtable_resize(this, __old_size, __new_size);
466      }
467   };
468
469  template<typename _Value, typename _Hash, typename _Pred, typename _Alloc>
470    inline void
471    swap(unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __x,
472	 unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __y)
473    { __x.swap(__y); }
474
475  template<typename _Value, typename _Hash, typename _Pred, typename _Alloc>
476    inline bool
477    operator==(const unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __x,
478	       const unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __y)
479    { return static_cast<const _GLIBCXX_STD_BASE&>(__x) == __y; }
480
481  template<typename _Value, typename _Hash, typename _Pred, typename _Alloc>
482    inline bool
483    operator!=(const unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __x,
484	       const unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __y)
485    { return !(__x == __y); }
486
487} // namespace __profile
488} // namespace std
489
490#undef _GLIBCXX_BASE
491#undef _GLIBCXX_STD_BASE
492
493#endif // C++11
494
495#endif
496