# profile/unordered_map

Go to the documentation of this file.

    00001 // Profiling unordered_map/unordered_multimap implementation -*- C++ -*-
    00002
    00003 // Copyright (C) 2009, 2010 Free Software Foundation, Inc.
    00004 //
    00005 // This file is part of the GNU ISO C++ Library.  This library is free
    00006 // software; you can redistribute it and/or modify it under the
    00007 // terms of the GNU General Public License as published by the
    00008 // Free Software Foundation; either version 2, or (at your option)
    00009 // any later version.
    00010
    00011 // This library is distributed in the hope that it will be useful,
    00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
    00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    00014 // GNU General Public License for more details.
    00015
    00016 // You should have received a copy of the GNU General Public License along
    00017 // with this library; see the file COPYING.  If not, write to the Free
    00018 // Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
    00019 // USA.
    00020
    00021 // As a special exception, you may use this file as part of a free software
    00022 // library without restriction.  Specifically, if other files instantiate
    00023 // templates or use macros or inline functions from this file, or you compile
    00024 // this file and link it with other files to produce an executable, this
    00025 // file does not by itself cause the resulting executable to be covered by
    00026 // the GNU General Public License.  This exception does not however
    00027 // invalidate any other reasons why the executable file might be covered by
    00028 // the GNU General Public License.
    00029
    00030 /** @file profile/unordered_map
    00031  *  This file is a GNU profile extension to the Standard C++ Library.
    00032  */
    00033
    00034 #ifndef _GLIBCXX_PROFILE_UNORDERED_MAP
    00035 #define _GLIBCXX_PROFILE_UNORDERED_MAP 1
    00036
    00037 #ifndef __GXX_EXPERIMENTAL_CXX0X__
    00038 # include <bits/c++0x_warning.h>
    00039 #else
    00040 # include <unordered_map>
    00041
    00042 #include <profile/base.h>
    00043
    00044 #define _GLIBCXX_BASE unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>
    00045 #define _GLIBCXX_STD_BASE _GLIBCXX_STD_PR::_GLIBCXX_BASE
    00046
    00047 namespace std
    00048 {
    00049 namespace __profile
    00050 {
    00051   /// Class std::unordered_map wrapper with performance instrumentation.
    00052   template<typename _Key, typename _Tp,
    00053        typename _Hash  = std::hash<_Key>,
    00054        typename _Pred = std::equal_to<_Key>,
    00055        typename _Alloc =  std::allocator<_Key> >
    00056     class unordered_map
    00057     : public _GLIBCXX_STD_BASE
    00058     {
    00059       typedef typename _GLIBCXX_STD_BASE _Base;
    00060
    00061     public:
    00062       typedef typename _Base::size_type       size_type;
    00063       typedef typename _Base::hasher          hasher;
    00064       typedef typename _Base::key_equal       key_equal;
    00065       typedef typename _Base::allocator_type  allocator_type;
    00066       typedef typename _Base::key_type        key_type;
    00067       typedef typename _Base::value_type      value_type;
    00068       typedef typename _Base::difference_type difference_type;
    00069       typedef typename _Base::reference       reference;
    00070       typedef typename _Base::const_reference const_reference;
    00071       typedef typename _Base::mapped_type      mapped_type;
    00072
    00073       typedef typename _Base::iterator iterator;
    00074       typedef typename _Base::const_iterator const_iterator;
    00075
    00076       explicit
    00077       unordered_map(size_type __n = 10,
    00078             const hasher& __hf = hasher(),
    00079             const key_equal& __eql = key_equal(),
    00080             const allocator_type& __a = allocator_type())
    00081       : _Base(__n, __hf, __eql, __a)
    00082       {
    00083         __profcxx_hashtable_construct(this, _Base::bucket_count());
    00084         __profcxx_hashtable_construct2(this);
    00085       }
    00086
    00087       template<typename _InputIterator>
    00088         unordered_map(_InputIterator __f, _InputIterator __l,
    00089               size_type __n = 10,
    00090               const hasher& __hf = hasher(),
    00091               const key_equal& __eql = key_equal(),
    00092               const allocator_type& __a = allocator_type())
    00093       : _Base(__f, __l, __n, __hf, __eql, __a)
    00094       {
    00095         __profcxx_hashtable_construct(this, _Base::bucket_count());
    00096         __profcxx_hashtable_construct2(this);
    00097       }
    00098
    00099       unordered_map(const _Base& __x)
    00100       : _Base(__x)
    00101       {
    00102         __profcxx_hashtable_construct(this, _Base::bucket_count());
    00103         __profcxx_hashtable_construct2(this);
    00104       }
    00105
    00106       unordered_map(unordered_map&& __x)
    00107       : _Base(std::forward<_Base>(__x))
    00108       {
    00109         __profcxx_hashtable_construct(this, _Base::bucket_count());
    00110         __profcxx_hashtable_construct2(this);
    00111       }
    00112
    00113       unordered_map(initializer_list<value_type> __l,
    00114             size_type __n = 10,
    00115             const hasher& __hf = hasher(),
    00116             const key_equal& __eql = key_equal(),
    00117             const allocator_type& __a = allocator_type())
    00118       : _Base(__l, __n, __hf, __eql, __a) { }
    00119
    00120       unordered_map&
    00121       operator=(const unordered_map& __x)
    00122       {
    00123     *static_cast<_Base*>(this) = __x;
    00124     return *this;
    00125       }
    00126
    00127       unordered_map&
    00128       operator=(unordered_map&& __x)
    00129       {
    00130     // NB: DR 1204.
    00131     // NB: DR 675.
    00132     this->clear();
    00133     this->swap(__x);
    00134     return *this;
    00135       }
    00136
    00137       unordered_map&
    00138       operator=(initializer_list<value_type> __l)
    00139       {
    00140     this->clear();
    00141     this->insert(__l);
    00142     return *this;
    00143       }
    00144
    00145       ~unordered_map()
    00146       {
    00147         __profcxx_hashtable_destruct(this, _Base::bucket_count(),
    00148                      _Base::size());
    00149         _M_profile_destruct();
    00150       }
    00151
    00152       _Base&
    00153       _M_base()       { return *this; }
    00154
    00155       const _Base&
    00156       _M_base() const { return *this; }
    00157
    00158
    00159       void
    00160       clear()
    00161       {
    00162         __profcxx_hashtable_destruct(this, _Base::bucket_count(),
    00163                      _Base::size());
    00164         _M_profile_destruct();
    00165         _Base::clear();
    00166       }
    00167
    00168       void
    00169       insert(std::initializer_list<value_type> __l)
    00170       {
    00171         size_type __old_size = _Base::bucket_count();
    00172         _Base::insert(__l);
    00173         _M_profile_resize(__old_size, _Base::bucket_count());
    00174       }
    00175
    00176       std::pair<iterator, bool>
    00177       insert(const value_type& __obj)
    00178       {
    00179         size_type __old_size =  _Base::bucket_count();
    00180         std::pair<iterator, bool> __res = _Base::insert(__obj);
    00181         _M_profile_resize(__old_size, _Base::bucket_count());
    00182         return __res;
    00183       }
    00184
    00185       iterator
    00186       insert(const_iterator __iter, const value_type& __v)
    00187       {
    00188         size_type __old_size = _Base::bucket_count();
    00189         iterator __res = _Base::insert(__iter, __v);
    00190         _M_profile_resize(__old_size, _Base::bucket_count());
    00191         return __res;
    00192       }
    00193
    00194       template<typename _InputIter>
    00195         void
    00196         insert(_InputIter __first, _InputIter __last)
    00197         {
    00198       size_type __old_size = _Base::bucket_count();
    00199       _Base::insert(__first, __last);
    00200       _M_profile_resize(__old_size, _Base::bucket_count());
    00201     }
    00202
    00203       void
    00204       insert(const value_type* __first, const value_type* __last)
    00205       {
    00206         size_type __old_size = _Base::bucket_count();
    00207         _Base::insert(__first, __last);
    00208         _M_profile_resize(__old_size, _Base::bucket_count());
    00209       }
    00210
    00211       // operator []
    00212       mapped_type&
    00213       operator[](const _Key& _k)
    00214       {
    00215         size_type __old_size =  _Base::bucket_count();
    00216         mapped_type& __res = _M_base()[_k];
    00217         size_type __new_size =  _Base::bucket_count();
    00218         _M_profile_resize(__old_size, _Base::bucket_count());
    00219         return __res;
    00220       }
    00221
    00222       void
    00223       swap(unordered_map& __x)
    00224       { _Base::swap(__x); }
    00225
    00226       void rehash(size_type __n)
    00227       {
    00228         size_type __old_size =  _Base::bucket_count();
    00229         _Base::rehash(__n);
    00230         _M_profile_resize(__old_size, _Base::bucket_count());
    00231       }
    00232
    00233     private:
    00234       void
    00235       _M_profile_resize(size_type __old_size, size_type __new_size)
    00236       {
    00237         if (__old_size != __new_size)
    00238       __profcxx_hashtable_resize(this, __old_size, __new_size);
    00239       }
    00240
    00241       void
    00242       _M_profile_destruct()
    00243       {
    00244         size_type __hops = 0, __lc = 0, __chain = 0;
    00245         for (iterator __it = _M_base().begin(); __it != _M_base().end();
    00246          ++__it)
    00247       {
    00248         while (__it._M_cur_node->_M_next)
    00249           {
    00250         ++__chain;
    00251         ++__it;
    00252           }
    00253         if (__chain)
    00254           {
    00255         ++__chain;
    00256         __lc = __lc > __chain ? __lc : __chain;
    00257         __hops += __chain * (__chain - 1) / 2;
    00258         __chain = 0;
    00259           }
    00260       }
    00261         __profcxx_hashtable_destruct2(this, __lc,  _Base::size(), __hops);
    00262       }
    00263    };
    00264
    00265   template<typename _Key, typename _Tp, typename _Hash,
    00266        typename _Pred, typename _Alloc>
    00267     inline void
    00268     swap(unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
    00269      unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
    00270     { __x.swap(__y); }
    00271
    00272   template<typename _Key, typename _Tp, typename _Hash,
    00273        typename _Pred, typename _Alloc>
    00274     inline bool
    00275     operator==(const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
    00276            const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
    00277     { return __x._M_equal(__y); }
    00278
    00279   template<typename _Key, typename _Tp, typename _Hash,
    00280        typename _Pred, typename _Alloc>
    00281     inline bool
    00282     operator!=(const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
    00283            const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
    00284     { return !(__x == __y); }
    00285
    00286 #undef _GLIBCXX_BASE
    00287 #undef _GLIBCXX_STD_BASE
    00288 #define _GLIBCXX_BASE unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>
    00289 #define _GLIBCXX_STD_BASE _GLIBCXX_STD_PR::_GLIBCXX_BASE
    00290
    00291   /// Class std::unordered_multimap wrapper with performance instrumentation.
    00292   template<typename _Key, typename _Tp,
    00293        typename _Hash  = std::hash<_Key>,
    00294        typename _Pred = std::equal_to<_Key>,
    00295        typename _Alloc =  std::allocator<_Key> >
    00296     class unordered_multimap
    00297     : public _GLIBCXX_STD_BASE
    00298     {
    00299       typedef typename _GLIBCXX_STD_BASE _Base;
    00300
    00301     public:
    00302       typedef typename _Base::size_type       size_type;
    00303       typedef typename _Base::hasher          hasher;
    00304       typedef typename _Base::key_equal       key_equal;
    00305       typedef typename _Base::allocator_type  allocator_type;
    00306       typedef typename _Base::key_type        key_type;
    00307       typedef typename _Base::value_type      value_type;
    00308       typedef typename _Base::difference_type difference_type;
    00309       typedef typename _Base::reference       reference;
    00310       typedef typename _Base::const_reference const_reference;
    00311
    00312       typedef typename _Base::iterator iterator;
    00313       typedef typename _Base::const_iterator const_iterator;
    00314
    00315       explicit
    00316       unordered_multimap(size_type __n = 10,
    00317             const hasher& __hf = hasher(),
    00318             const key_equal& __eql = key_equal(),
    00319             const allocator_type& __a = allocator_type())
    00320       : _Base(__n, __hf, __eql, __a)
    00321       {
    00322         __profcxx_hashtable_construct(this, _Base::bucket_count());
    00323       }
    00324       template<typename _InputIterator>
    00325         unordered_multimap(_InputIterator __f, _InputIterator __l,
    00326               size_type __n = 10,
    00327               const hasher& __hf = hasher(),
    00328               const key_equal& __eql = key_equal(),
    00329               const allocator_type& __a = allocator_type())
    00330       : _Base(__f, __l, __n, __hf, __eql, __a)
    00331       {
    00332         __profcxx_hashtable_construct(this, _Base::bucket_count());
    00333       }
    00334
    00335       unordered_multimap(const _Base& __x)
    00336       : _Base(__x)
    00337       {
    00338         __profcxx_hashtable_construct(this, _Base::bucket_count());
    00339       }
    00340
    00341       unordered_multimap(unordered_multimap&& __x)
    00342       : _Base(std::forward<_Base>(__x))
    00343       {
    00344         __profcxx_hashtable_construct(this, _Base::bucket_count());
    00345       }
    00346
    00347       unordered_multimap(initializer_list<value_type> __l,
    00348              size_type __n = 10,
    00349              const hasher& __hf = hasher(),
    00350              const key_equal& __eql = key_equal(),
    00351              const allocator_type& __a = allocator_type())
    00352       : _Base(__l, __n, __hf, __eql, __a) { }
    00353
    00354       unordered_multimap&
    00355       operator=(const unordered_multimap& __x)
    00356       {
    00357     *static_cast<_Base*>(this) = __x;
    00358     return *this;
    00359       }
    00360
    00361       unordered_multimap&
    00362       operator=(unordered_multimap&& __x)
    00363       {
    00364     // NB: DR 1204.
    00365     // NB: DR 675.
    00366     this->clear();
    00367     this->swap(__x);
    00368     return *this;
    00369       }
    00370
    00371       unordered_multimap&
    00372       operator=(initializer_list<value_type> __l)
    00373       {
    00374     this->clear();
    00375     this->insert(__l);
    00376     return *this;
    00377       }
    00378
    00379       ~unordered_multimap()
    00380       {
    00381         __profcxx_hashtable_destruct(this, _Base::bucket_count(),
    00382                      _Base::size());
    00383         _M_profile_destruct();
    00384       }
    00385
    00386       _Base&
    00387       _M_base()       { return *this; }
    00388
    00389       const _Base&
    00390       _M_base() const { return *this; }
    00391
    00392
    00393       void
    00394       clear()
    00395       {
    00396         __profcxx_hashtable_destruct(this, _Base::bucket_count(),
    00397                      _Base::size());
    00398         _M_profile_destruct();
    00399         _Base::clear();
    00400       }
    00401
    00402       void
    00403       insert(std::initializer_list<value_type> __l)
    00404       {
    00405         size_type __old_size =  _Base::bucket_count();
    00406         _Base::insert(__l);
    00407         _M_profile_resize(__old_size, _Base::bucket_count());
    00408       }
    00409
    00410       iterator
    00411       insert(const value_type& __obj)
    00412       {
    00413         size_type __old_size =  _Base::bucket_count();
    00414         iterator __res = _Base::insert(__obj);
    00415         _M_profile_resize(__old_size, _Base::bucket_count());
    00416         return __res;
    00417       }
    00418
    00419       iterator
    00420       insert(const_iterator __iter, const value_type& __v)
    00421       {
    00422         size_type __old_size = _Base::bucket_count();
    00423         iterator __res =_Base::insert(__iter, __v);
    00424         _M_profile_resize(__old_size, _Base::bucket_count());
    00425         return __res;
    00426       }
    00427
    00428       template<typename _InputIter>
    00429         void
    00430         insert(_InputIter __first, _InputIter __last)
    00431         {
    00432       size_type __old_size = _Base::bucket_count();
    00433       _Base::insert(__first, __last);
    00434       _M_profile_resize(__old_size, _Base::bucket_count());
    00435     }
    00436
    00437       void
    00438       insert(const value_type* __first, const value_type* __last)
    00439       {
    00440         size_type __old_size = _Base::bucket_count();
    00441         _Base::insert(__first, __last);
    00442         _M_profile_resize(__old_size, _Base::bucket_count());
    00443       }
    00444
    00445       void
    00446       swap(unordered_multimap& __x)
    00447       { _Base::swap(__x); }
    00448
    00449       void rehash(size_type __n)
    00450       {
    00451         size_type __old_size =  _Base::bucket_count();
    00452         _Base::rehash(__n);
    00453         _M_profile_resize(__old_size, _Base::bucket_count());
    00454       }
    00455
    00456     private:
    00457       void
    00458       _M_profile_resize(size_type __old_size, size_type __new_size)
    00459       {
    00460         if (__old_size != __new_size)
    00461           __profcxx_hashtable_resize(this, __old_size, __new_size);
    00462       }
    00463
    00464       void
    00465       _M_profile_destruct()
    00466       {
    00467         size_type __hops = 0, __lc = 0, __chain = 0;
    00468         for (iterator __it = _M_base().begin(); __it != _M_base().end();
    00469          ++__it)
    00470       {
    00471         while (__it._M_cur_node->_M_next)
    00472           {
    00473         ++__chain;
    00474         ++__it;
    00475           }
    00476         if (__chain)
    00477           {
    00478         ++__chain;
    00479         __lc = __lc > __chain ? __lc : __chain;
    00480         __hops += __chain * (__chain - 1) / 2;
    00481         __chain = 0;
    00482           }
    00483       }
    00484         __profcxx_hashtable_destruct2(this, __lc,  _Base::size(), __hops);
    00485       }
    00486
    00487     };
    00488
    00489   template<typename _Key, typename _Tp, typename _Hash,
    00490        typename _Pred, typename _Alloc>
    00491     inline void
    00492     swap(unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
    00493      unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
    00494     { __x.swap(__y); }
    00495
    00496   template<typename _Key, typename _Tp, typename _Hash,
    00497        typename _Pred, typename _Alloc>
    00498     inline bool
    00499     operator==(const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
    00500            const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
    00501     { return __x._M_equal(__y); }
    00502
    00503   template<typename _Key, typename _Tp, typename _Hash,
    00504        typename _Pred, typename _Alloc>
    00505     inline bool
    00506     operator!=(const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
    00507            const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
    00508     { return !(__x == __y); }
    00509
    00510 } // namespace __profile
    00511 } // namespace std
    00512
    00513 #undef _GLIBCXX_BASE
    00514 #undef _GLIBCXX_STD_BASE
    00515
    00516 #endif // __GXX_EXPERIMENTAL_CXX0X__
    00517
    00518 #endif