Home | History | Annotate | Download | only in profile
      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 
     42 namespace std _GLIBCXX_VISIBILITY(default)
     43 {
     44 namespace __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