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 42namespace std _GLIBCXX_VISIBILITY(default) 43{ 44namespace __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