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