1 // Profiling unordered_map/unordered_multimap implementation -*- C++ -*- 2 3 // Copyright (C) 2009-2013 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 unordered_map(initializer_list<value_type> __l, 105 size_type __n = 0, 106 const hasher& __hf = hasher(), 107 const key_equal& __eql = key_equal(), 108 const allocator_type& __a = allocator_type()) 109 : _Base(__l, __n, __hf, __eql, __a) 110 { } 111 112 unordered_map& 113 operator=(const unordered_map&) = default; 114 115 unordered_map& 116 operator=(unordered_map&&) = default; 117 118 unordered_map& 119 operator=(initializer_list<value_type> __l) 120 { 121 _M_base() = __l; 122 return *this; 123 } 124 125 void 126 clear() noexcept 127 { 128 __profcxx_hashtable_destruct(this, _Base::bucket_count(), 129 _Base::size()); 130 this->_M_profile_destruct(); 131 _Base::clear(); 132 } 133 134 template<typename... _Args> 135 std::pair<iterator, bool> 136 emplace(_Args&&... __args) 137 { 138 size_type __old_size = _Base::bucket_count(); 139 std::pair<iterator, bool> __res 140 = _Base::emplace(std::forward<_Args>(__args)...); 141 _M_profile_resize(__old_size); 142 return __res; 143 } 144 145 template<typename... _Args> 146 iterator 147 emplace_hint(const_iterator __it, _Args&&... __args) 148 { 149 size_type __old_size = _Base::bucket_count(); 150 iterator __res 151 = _Base::emplace_hint(__it, std::forward<_Args>(__args)...); 152 _M_profile_resize(__old_size); 153 return __res; 154 } 155 156 void 157 insert(std::initializer_list<value_type> __l) 158 { 159 size_type __old_size = _Base::bucket_count(); 160 _Base::insert(__l); 161 _M_profile_resize(__old_size); 162 } 163 164 std::pair<iterator, bool> 165 insert(const value_type& __obj) 166 { 167 size_type __old_size = _Base::bucket_count(); 168 std::pair<iterator, bool> __res = _Base::insert(__obj); 169 _M_profile_resize(__old_size); 170 return __res; 171 } 172 173 iterator 174 insert(const_iterator __iter, const value_type& __v) 175 { 176 size_type __old_size = _Base::bucket_count(); 177 iterator __res = _Base::insert(__iter, __v); 178 _M_profile_resize(__old_size); 179 return __res; 180 } 181 182 template<typename _Pair, typename = typename 183 std::enable_if<std::is_constructible<value_type, 184 _Pair&&>::value>::type> 185 std::pair<iterator, bool> 186 insert(_Pair&& __obj) 187 { 188 size_type __old_size = _Base::bucket_count(); 189 std::pair<iterator, bool> __res 190 = _Base::insert(std::forward<_Pair>(__obj)); 191 _M_profile_resize(__old_size); 192 return __res; 193 } 194 195 template<typename _Pair, typename = typename 196 std::enable_if<std::is_constructible<value_type, 197 _Pair&&>::value>::type> 198 iterator 199 insert(const_iterator __iter, _Pair&& __v) 200 { 201 size_type __old_size = _Base::bucket_count(); 202 iterator __res = _Base::insert(__iter, std::forward<_Pair>(__v)); 203 _M_profile_resize(__old_size); 204 return __res; 205 } 206 207 template<typename _InputIter> 208 void 209 insert(_InputIter __first, _InputIter __last) 210 { 211 size_type __old_size = _Base::bucket_count(); 212 _Base::insert(__first, __last); 213 _M_profile_resize(__old_size); 214 } 215 216 // operator[] 217 mapped_type& 218 operator[](const _Key& __k) 219 { 220 size_type __old_size = _Base::bucket_count(); 221 mapped_type& __res = _M_base()[__k]; 222 _M_profile_resize(__old_size); 223 return __res; 224 } 225 226 mapped_type& 227 operator[](_Key&& __k) 228 { 229 size_type __old_size = _Base::bucket_count(); 230 mapped_type& __res = _M_base()[std::move(__k)]; 231 _M_profile_resize(__old_size); 232 return __res; 233 } 234 235 void 236 swap(unordered_map& __x) 237 { _Base::swap(__x._M_base()); } 238 239 void rehash(size_type __n) 240 { 241 size_type __old_size = _Base::bucket_count(); 242 _Base::rehash(__n); 243 _M_profile_resize(__old_size); 244 } 245 246 private: 247 void 248 _M_profile_resize(size_type __old_size) 249 { 250 size_type __new_size = _Base::bucket_count(); 251 if (__old_size != __new_size) 252 __profcxx_hashtable_resize(this, __old_size, __new_size); 253 } 254 }; 255 256 template<typename _Key, typename _Tp, typename _Hash, 257 typename _Pred, typename _Alloc> 258 inline void 259 swap(unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, 260 unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) 261 { __x.swap(__y); } 262 263 template<typename _Key, typename _Tp, typename _Hash, 264 typename _Pred, typename _Alloc> 265 inline bool 266 operator==(const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, 267 const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) 268 { return static_cast<const _GLIBCXX_STD_BASE&>(__x) == __y; } 269 270 template<typename _Key, typename _Tp, typename _Hash, 271 typename _Pred, typename _Alloc> 272 inline bool 273 operator!=(const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, 274 const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) 275 { return !(__x == __y); } 276 277 #undef _GLIBCXX_BASE 278 #undef _GLIBCXX_STD_BASE 279 #define _GLIBCXX_BASE unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc> 280 #define _GLIBCXX_STD_BASE _GLIBCXX_STD_C::_GLIBCXX_BASE 281 282 /// Class std::unordered_multimap wrapper with performance instrumentation. 283 template<typename _Key, typename _Tp, 284 typename _Hash = std::hash<_Key>, 285 typename _Pred = std::equal_to<_Key>, 286 typename _Alloc = std::allocator<std::pair<const _Key, _Tp> > > 287 class unordered_multimap 288 : public _GLIBCXX_STD_BASE, 289 public _Unordered_profile<unordered_multimap<_Key, _Tp, 290 _Hash, _Pred, _Alloc>, 291 false> 292 { 293 typedef typename _GLIBCXX_STD_BASE _Base; 294 295 _Base& 296 _M_base() noexcept { return *this; } 297 298 const _Base& 299 _M_base() const noexcept { return *this; } 300 301 public: 302 typedef typename _Base::size_type size_type; 303 typedef typename _Base::hasher hasher; 304 typedef typename _Base::key_equal key_equal; 305 typedef typename _Base::allocator_type allocator_type; 306 typedef typename _Base::key_type key_type; 307 typedef typename _Base::value_type value_type; 308 typedef typename _Base::difference_type difference_type; 309 typedef typename _Base::reference reference; 310 typedef typename _Base::const_reference const_reference; 311 312 typedef typename _Base::iterator iterator; 313 typedef typename _Base::const_iterator const_iterator; 314 315 explicit 316 unordered_multimap(size_type __n = 10, 317 const hasher& __hf = hasher(), 318 const key_equal& __eql = key_equal(), 319 const allocator_type& __a = allocator_type()) 320 : _Base(__n, __hf, __eql, __a) 321 { } 322 323 template<typename _InputIterator> 324 unordered_multimap(_InputIterator __f, _InputIterator __l, 325 size_type __n = 0, 326 const hasher& __hf = hasher(), 327 const key_equal& __eql = key_equal(), 328 const allocator_type& __a = allocator_type()) 329 : _Base(__f, __l, __n, __hf, __eql, __a) 330 { } 331 332 unordered_multimap(const unordered_multimap&) = default; 333 334 unordered_multimap(const _Base& __x) 335 : _Base(__x) 336 { } 337 338 unordered_multimap(unordered_multimap&&) = default; 339 340 unordered_multimap(initializer_list<value_type> __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(__l, __n, __hf, __eql, __a) 346 { } 347 348 unordered_multimap& 349 operator=(const unordered_multimap&) = default; 350 351 unordered_multimap& 352 operator=(unordered_multimap&&) = default; 353 354 unordered_multimap& 355 operator=(initializer_list<value_type> __l) 356 { 357 _M_base() = __l; 358 return *this; 359 } 360 361 void 362 clear() noexcept 363 { 364 __profcxx_hashtable_destruct(this, _Base::bucket_count(), 365 _Base::size()); 366 this->_M_profile_destruct(); 367 _Base::clear(); 368 } 369 370 template<typename... _Args> 371 iterator 372 emplace(_Args&&... __args) 373 { 374 size_type __old_size = _Base::bucket_count(); 375 iterator __res 376 = _Base::emplace(std::forward<_Args>(__args)...); 377 _M_profile_resize(__old_size); 378 return __res; 379 } 380 381 template<typename... _Args> 382 iterator 383 emplace_hint(const_iterator __it, _Args&&... __args) 384 { 385 size_type __old_size = _Base::bucket_count(); 386 iterator __res 387 = _Base::emplace_hint(__it, std::forward<_Args>(__args)...); 388 _M_profile_resize(__old_size); 389 return __res; 390 } 391 392 void 393 insert(std::initializer_list<value_type> __l) 394 { 395 size_type __old_size = _Base::bucket_count(); 396 _Base::insert(__l); 397 _M_profile_resize(__old_size); 398 } 399 400 iterator 401 insert(const value_type& __obj) 402 { 403 size_type __old_size = _Base::bucket_count(); 404 iterator __res = _Base::insert(__obj); 405 _M_profile_resize(__old_size); 406 return __res; 407 } 408 409 iterator 410 insert(const_iterator __iter, const value_type& __v) 411 { 412 size_type __old_size = _Base::bucket_count(); 413 iterator __res = _Base::insert(__iter, __v); 414 _M_profile_resize(__old_size); 415 return __res; 416 } 417 418 template<typename _Pair, typename = typename 419 std::enable_if<std::is_constructible<value_type, 420 _Pair&&>::value>::type> 421 iterator 422 insert(_Pair&& __obj) 423 { 424 size_type __old_size = _Base::bucket_count(); 425 iterator __res = _Base::insert(std::forward<_Pair>(__obj)); 426 _M_profile_resize(__old_size); 427 return __res; 428 } 429 430 template<typename _Pair, typename = typename 431 std::enable_if<std::is_constructible<value_type, 432 _Pair&&>::value>::type> 433 iterator 434 insert(const_iterator __iter, _Pair&& __v) 435 { 436 size_type __old_size = _Base::bucket_count(); 437 iterator __res = _Base::insert(__iter, std::forward<_Pair>(__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 swap(unordered_multimap& __x) 453 { _Base::swap(__x._M_base()); } 454 455 void 456 rehash(size_type __n) 457 { 458 size_type __old_size = _Base::bucket_count(); 459 _Base::rehash(__n); 460 _M_profile_resize(__old_size); 461 } 462 463 private: 464 void 465 _M_profile_resize(size_type __old_size) 466 { 467 size_type __new_size = _Base::bucket_count(); 468 if (__old_size != __new_size) 469 __profcxx_hashtable_resize(this, __old_size, __new_size); 470 } 471 }; 472 473 template<typename _Key, typename _Tp, typename _Hash, 474 typename _Pred, typename _Alloc> 475 inline void 476 swap(unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, 477 unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) 478 { __x.swap(__y); } 479 480 template<typename _Key, typename _Tp, typename _Hash, 481 typename _Pred, typename _Alloc> 482 inline bool 483 operator==(const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, 484 const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) 485 { return static_cast<const _GLIBCXX_STD_BASE&>(__x) == __y; } 486 487 template<typename _Key, typename _Tp, typename _Hash, 488 typename _Pred, typename _Alloc> 489 inline bool 490 operator!=(const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, 491 const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) 492 { return !(__x == __y); } 493 494 } // namespace __profile 495 } // namespace std 496 497 #undef _GLIBCXX_BASE 498 #undef _GLIBCXX_STD_BASE 499 500 #endif // C++11 501 502 #endif 503