1 // Profiling list implementation -*- C++ -*- 2 3 // Copyright (C) 2009, 2010 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 and 21 // a copy of the GCC Runtime Library Exception along with this program; 22 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23 // <http://www.gnu.org/licenses/>. 24 25 /** @file profile/list 26 * This file is a GNU profile extension to the Standard C++ Library. 27 */ 28 29 #ifndef _GLIBCXX_PROFILE_LIST 30 #define _GLIBCXX_PROFILE_LIST 1 31 32 #include <list> 33 #include <profile/base.h> 34 #include <profile/iterator_tracker.h> 35 36 namespace std _GLIBCXX_VISIBILITY(default) 37 { 38 namespace __profile 39 { 40 /** @brief List wrapper with performance instrumentation. */ 41 template<typename _Tp, typename _Allocator = std::allocator<_Tp> > 42 class list 43 : public _GLIBCXX_STD_C::list<_Tp, _Allocator> 44 { 45 typedef _GLIBCXX_STD_C::list<_Tp, _Allocator> _Base; 46 47 public: 48 typedef typename _Base::reference reference; 49 typedef typename _Base::const_reference const_reference; 50 51 typedef __iterator_tracker<typename _Base::iterator, list> 52 iterator; 53 typedef __iterator_tracker<typename _Base::const_iterator, list> 54 const_iterator; 55 56 typedef typename _Base::size_type size_type; 57 typedef typename _Base::difference_type difference_type; 58 59 typedef _Tp value_type; 60 typedef _Allocator allocator_type; 61 typedef typename _Base::pointer pointer; 62 typedef typename _Base::const_pointer const_pointer; 63 typedef std::reverse_iterator<iterator> reverse_iterator; 64 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; 65 66 // 23.2.2.1 construct/copy/destroy: 67 explicit 68 list(const _Allocator& __a = _Allocator()) 69 : _Base(__a) 70 { 71 __profcxx_list_construct(this); // list2slist 72 __profcxx_list_construct2(this); // list2vector 73 } 74 75 #ifdef __GXX_EXPERIMENTAL_CXX0X__ 76 explicit 77 list(size_type __n) 78 : _Base(__n) 79 { 80 __profcxx_list_construct(this); 81 __profcxx_list_construct2(this); 82 } 83 84 list(size_type __n, const _Tp& __value, 85 const _Allocator& __a = _Allocator()) 86 : _Base(__n, __value, __a) 87 { 88 __profcxx_list_construct(this); 89 __profcxx_list_construct2(this); 90 } 91 #else 92 explicit 93 list(size_type __n, const _Tp& __value = _Tp(), 94 const _Allocator& __a = _Allocator()) 95 : _Base(__n, __value, __a) 96 { 97 __profcxx_list_construct(this); 98 __profcxx_list_construct2(this); 99 } 100 #endif 101 102 template<class _InputIterator> 103 list(_InputIterator __first, _InputIterator __last, 104 const _Allocator& __a = _Allocator()) 105 : _Base(__first, __last, __a) 106 { 107 __profcxx_list_construct(this); 108 __profcxx_list_construct2(this); 109 } 110 111 list(const list& __x) 112 : _Base(__x) 113 { 114 __profcxx_list_construct(this); 115 __profcxx_list_construct2(this); 116 } 117 118 list(const _Base& __x) 119 : _Base(__x) 120 { 121 __profcxx_list_construct(this); 122 __profcxx_list_construct2(this); 123 } 124 125 #ifdef __GXX_EXPERIMENTAL_CXX0X__ 126 list(list&& __x) 127 : _Base(std::move(__x)) 128 { 129 __profcxx_list_construct(this); 130 __profcxx_list_construct2(this); 131 } 132 133 list(initializer_list<value_type> __l, 134 const allocator_type& __a = allocator_type()) 135 : _Base(__l, __a) { } 136 #endif 137 138 ~list() { 139 __profcxx_list_destruct(this); 140 __profcxx_list_destruct2(this); 141 } 142 143 list& 144 operator=(const list& __x) 145 { 146 static_cast<_Base&>(*this) = __x; 147 return *this; 148 } 149 150 #ifdef __GXX_EXPERIMENTAL_CXX0X__ 151 list& 152 operator=(list&& __x) 153 { 154 // NB: DR 1204. 155 // NB: DR 675. 156 this->clear(); 157 this->swap(__x); 158 return *this; 159 } 160 161 list& 162 operator=(initializer_list<value_type> __l) 163 { 164 static_cast<_Base&>(*this) = __l; 165 return *this; 166 } 167 168 void 169 assign(initializer_list<value_type> __l) 170 { _Base::assign(__l); } 171 #endif 172 173 template<class _InputIterator> 174 void 175 assign(_InputIterator __first, _InputIterator __last) 176 { _Base::assign(__first, __last); } 177 178 void 179 assign(size_type __n, const _Tp& __t) 180 { _Base::assign(__n, __t); } 181 182 using _Base::get_allocator; 183 184 // iterators: 185 iterator 186 begin() 187 { return iterator(_Base::begin(), this); } 188 189 const_iterator 190 begin() const 191 { return const_iterator(_Base::begin(), this); } 192 193 iterator 194 end() 195 { 196 __profcxx_list_rewind(this); 197 return iterator(_Base::end(), this); 198 } 199 200 const_iterator 201 end() const 202 { 203 __profcxx_list_rewind(this); 204 return const_iterator(_Base::end(), this); 205 } 206 207 reverse_iterator 208 rbegin() 209 { 210 __profcxx_list_rewind(this); 211 return reverse_iterator(end()); 212 } 213 214 const_reverse_iterator 215 rbegin() const 216 { 217 __profcxx_list_rewind(this); 218 return const_reverse_iterator(end()); 219 } 220 221 reverse_iterator 222 rend() 223 { return reverse_iterator(begin()); } 224 225 const_reverse_iterator 226 rend() const 227 { return const_reverse_iterator(begin()); } 228 229 #ifdef __GXX_EXPERIMENTAL_CXX0X__ 230 const_iterator 231 cbegin() const 232 { return const_iterator(_Base::begin(), this); } 233 234 const_iterator 235 cend() const 236 { return const_iterator(_Base::end(), this); } 237 238 const_reverse_iterator 239 crbegin() const 240 { return const_reverse_iterator(end()); } 241 242 const_reverse_iterator 243 crend() const 244 { return const_reverse_iterator(begin()); } 245 #endif 246 247 // 23.2.2.2 capacity: 248 using _Base::empty; 249 using _Base::size; 250 using _Base::max_size; 251 252 #ifdef __GXX_EXPERIMENTAL_CXX0X__ 253 void 254 resize(size_type __sz) 255 { _Base::resize(__sz); } 256 257 void 258 resize(size_type __sz, const _Tp& __c) 259 { _Base::resize(__sz, __c); } 260 #else 261 void 262 resize(size_type __sz, _Tp __c = _Tp()) 263 { _Base::resize(__sz, __c); } 264 #endif 265 266 // element access: 267 reference 268 front() 269 { return _Base::front(); } 270 271 const_reference 272 front() const 273 { return _Base::front(); } 274 275 reference 276 back() 277 { 278 __profcxx_list_rewind(this); 279 return _Base::back(); 280 } 281 282 const_reference 283 back() const 284 { 285 __profcxx_list_rewind(this); 286 return _Base::back(); 287 } 288 289 // 23.2.2.3 modifiers: 290 void 291 push_front(const value_type& __x) 292 { 293 __profcxx_list_invalid_operator(this); 294 __profcxx_list_operation(this); 295 _Base::push_front(__x); 296 } 297 298 #ifdef __GXX_EXPERIMENTAL_CXX0X__ 299 using _Base::emplace_front; 300 #endif 301 302 void 303 pop_front() 304 { 305 __profcxx_list_operation(this); 306 _Base::pop_front(); 307 } 308 309 using _Base::push_back; 310 311 #ifdef __GXX_EXPERIMENTAL_CXX0X__ 312 using _Base::emplace_back; 313 #endif 314 315 void 316 pop_back() 317 { 318 iterator __victim = end(); 319 --__victim; 320 _Base::pop_back(); 321 __profcxx_list_rewind(this); 322 } 323 324 #ifdef __GXX_EXPERIMENTAL_CXX0X__ 325 template<typename... _Args> 326 iterator 327 emplace(iterator __position, _Args&&... __args) 328 { 329 return iterator(_Base::emplace(__position.base(), 330 std::forward<_Args>(__args)...)); 331 } 332 #endif 333 334 iterator 335 insert(iterator __position, const _Tp& __x) 336 { 337 _M_profile_insert(this, __position, size()); 338 return iterator(_Base::insert(__position.base(), __x), this); 339 } 340 341 #ifdef __GXX_EXPERIMENTAL_CXX0X__ 342 iterator 343 insert(iterator __position, _Tp&& __x) 344 { 345 _M_profile_insert(this, __position, size()); 346 return iterator(_Base::emplace(__position.base(), std::move(__x)), 347 this); 348 } 349 350 void 351 insert(iterator __position, initializer_list<value_type> __l) 352 { 353 _M_profile_insert(this, __position, size()); 354 _Base::insert(__position.base(), __l); 355 } 356 #endif 357 358 void 359 insert(iterator __position, size_type __n, const _Tp& __x) 360 { 361 _M_profile_insert(this, __position, size()); 362 _Base::insert(__position.base(), __n, __x); 363 } 364 365 template<class _InputIterator> 366 void 367 insert(iterator __position, _InputIterator __first, 368 _InputIterator __last) 369 { 370 _M_profile_insert(this, __position, size()); 371 _Base::insert(__position.base(), __first, __last); 372 } 373 374 iterator 375 erase(iterator __position) 376 { return iterator(_Base::erase(__position.base()), this); } 377 378 iterator 379 erase(iterator __position, iterator __last) 380 { 381 // _GLIBCXX_RESOLVE_LIB_DEFECTS 382 // 151. can't currently clear() empty container 383 return iterator(_Base::erase(__position.base(), __last.base()), this); 384 } 385 386 void 387 swap(list& __x) 388 { _Base::swap(__x); } 389 390 void 391 clear() 392 { _Base::clear(); } 393 394 // 23.2.2.4 list operations: 395 void 396 #ifdef __GXX_EXPERIMENTAL_CXX0X__ 397 splice(iterator __position, list&& __x) 398 #else 399 splice(iterator __position, list& __x) 400 #endif 401 { this->splice(__position, _GLIBCXX_MOVE(__x), __x.begin(), __x.end()); } 402 403 #ifdef __GXX_EXPERIMENTAL_CXX0X__ 404 void 405 splice(iterator __position, list& __x) 406 { this->splice(__position, std::move(__x)); } 407 #endif 408 409 #ifdef __GXX_EXPERIMENTAL_CXX0X__ 410 void 411 splice(iterator __position, list& __x, iterator __i) 412 { this->splice(__position, std::move(__x), __i); } 413 #endif 414 415 void 416 #ifdef __GXX_EXPERIMENTAL_CXX0X__ 417 splice(iterator __position, list&& __x, iterator __i) 418 #else 419 splice(iterator __position, list& __x, iterator __i) 420 #endif 421 { 422 // We used to perform the splice_alloc check: not anymore, redundant 423 // after implementing the relevant bits of N1599. 424 425 // _GLIBCXX_RESOLVE_LIB_DEFECTS 426 _Base::splice(__position.base(), _GLIBCXX_MOVE(__x._M_base()), 427 __i.base()); 428 } 429 430 void 431 #ifdef __GXX_EXPERIMENTAL_CXX0X__ 432 splice(iterator __position, list&& __x, iterator __first, 433 iterator __last) 434 #else 435 splice(iterator __position, list& __x, iterator __first, 436 iterator __last) 437 #endif 438 { 439 // We used to perform the splice_alloc check: not anymore, redundant 440 // after implementing the relevant bits of N1599. 441 442 _Base::splice(__position.base(), _GLIBCXX_MOVE(__x._M_base()), 443 __first.base(), __last.base()); 444 } 445 446 #ifdef __GXX_EXPERIMENTAL_CXX0X__ 447 void 448 splice(iterator __position, list& __x, iterator __first, iterator __last) 449 { this->splice(__position, std::move(__x), __first, __last); } 450 #endif 451 452 void 453 remove(const _Tp& __value) 454 { 455 for (iterator __x = begin(); __x != end(); ) 456 { 457 if (*__x == __value) 458 __x = erase(__x); 459 else 460 ++__x; 461 } 462 } 463 464 template<class _Predicate> 465 void 466 remove_if(_Predicate __pred) 467 { 468 for (iterator __x = begin(); __x != end(); ) 469 { 470 __profcxx_list_operation(this); 471 if (__pred(*__x)) 472 __x = erase(__x); 473 else 474 ++__x; 475 } 476 } 477 478 void 479 unique() 480 { 481 iterator __first = begin(); 482 iterator __last = end(); 483 if (__first == __last) 484 return; 485 iterator __next = __first; 486 while (++__next != __last) 487 { 488 __profcxx_list_operation(this); 489 if (*__first == *__next) 490 erase(__next); 491 else 492 __first = __next; 493 __next = __first; 494 } 495 } 496 497 template<class _BinaryPredicate> 498 void 499 unique(_BinaryPredicate __binary_pred) 500 { 501 iterator __first = begin(); 502 iterator __last = end(); 503 if (__first == __last) 504 return; 505 iterator __next = __first; 506 while (++__next != __last) 507 { 508 __profcxx_list_operation(this); 509 if (__binary_pred(*__first, *__next)) 510 erase(__next); 511 else 512 __first = __next; 513 __next = __first; 514 } 515 } 516 517 void 518 #ifdef __GXX_EXPERIMENTAL_CXX0X__ 519 merge(list&& __x) 520 #else 521 merge(list& __x) 522 #endif 523 { 524 // _GLIBCXX_RESOLVE_LIB_DEFECTS 525 // 300. list::merge() specification incomplete 526 if (this != &__x) 527 { _Base::merge(_GLIBCXX_MOVE(__x._M_base())); } 528 } 529 530 #ifdef __GXX_EXPERIMENTAL_CXX0X__ 531 void 532 merge(list& __x) 533 { this->merge(std::move(__x)); } 534 #endif 535 536 template<class _Compare> 537 void 538 #ifdef __GXX_EXPERIMENTAL_CXX0X__ 539 merge(list&& __x, _Compare __comp) 540 #else 541 merge(list& __x, _Compare __comp) 542 #endif 543 { 544 // _GLIBCXX_RESOLVE_LIB_DEFECTS 545 // 300. list::merge() specification incomplete 546 if (this != &__x) 547 { _Base::merge(_GLIBCXX_MOVE(__x._M_base()), __comp); } 548 } 549 550 #ifdef __GXX_EXPERIMENTAL_CXX0X__ 551 template<typename _Compare> 552 void 553 merge(list& __x, _Compare __comp) 554 { this->merge(std::move(__x), __comp); } 555 #endif 556 557 void 558 sort() { _Base::sort(); } 559 560 template<typename _StrictWeakOrdering> 561 void 562 sort(_StrictWeakOrdering __pred) { _Base::sort(__pred); } 563 564 using _Base::reverse; 565 566 _Base& 567 _M_base() { return *this; } 568 569 const _Base& 570 _M_base() const { return *this; } 571 572 inline void _M_profile_find() const 573 { } 574 575 inline void _M_profile_iterate(int __rewind = 0) const 576 { 577 __profcxx_list_operation(this); 578 __profcxx_list_iterate(this); 579 if (__rewind) 580 __profcxx_list_rewind(this); 581 } 582 583 private: 584 size_type _M_profile_insert(void* obj, iterator __pos, size_type __size) 585 { 586 size_type __shift = 0; 587 typename _Base::iterator __it = __pos.base(); 588 for ( ; __it!=_Base::end(); __it++) 589 __shift++; 590 __profcxx_list_rewind(this); 591 __profcxx_list_operation(this); 592 __profcxx_list_insert(this, __shift, __size); 593 } 594 }; 595 596 template<typename _Tp, typename _Alloc> 597 inline bool 598 operator==(const list<_Tp, _Alloc>& __lhs, 599 const list<_Tp, _Alloc>& __rhs) 600 { return __lhs._M_base() == __rhs._M_base(); } 601 602 template<typename _Tp, typename _Alloc> 603 inline bool 604 operator!=(const list<_Tp, _Alloc>& __lhs, 605 const list<_Tp, _Alloc>& __rhs) 606 { return __lhs._M_base() != __rhs._M_base(); } 607 608 template<typename _Tp, typename _Alloc> 609 inline bool 610 operator<(const list<_Tp, _Alloc>& __lhs, 611 const list<_Tp, _Alloc>& __rhs) 612 { return __lhs._M_base() < __rhs._M_base(); } 613 614 template<typename _Tp, typename _Alloc> 615 inline bool 616 operator<=(const list<_Tp, _Alloc>& __lhs, 617 const list<_Tp, _Alloc>& __rhs) 618 { return __lhs._M_base() <= __rhs._M_base(); } 619 620 template<typename _Tp, typename _Alloc> 621 inline bool 622 operator>=(const list<_Tp, _Alloc>& __lhs, 623 const list<_Tp, _Alloc>& __rhs) 624 { return __lhs._M_base() >= __rhs._M_base(); } 625 626 template<typename _Tp, typename _Alloc> 627 inline bool 628 operator>(const list<_Tp, _Alloc>& __lhs, 629 const list<_Tp, _Alloc>& __rhs) 630 { return __lhs._M_base() > __rhs._M_base(); } 631 632 template<typename _Tp, typename _Alloc> 633 inline void 634 swap(list<_Tp, _Alloc>& __lhs, list<_Tp, _Alloc>& __rhs) 635 { __lhs.swap(__rhs); } 636 637 } // namespace __profile 638 } // namespace std 639 640 #endif 641