1 // Profiling list implementation -*- C++ -*-
     3 // Copyright (C) 2009-2018 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 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/>.
    25 /** @file profile/list
    26  *  This file is a GNU profile extension to the Standard C++ Library.
    29 #ifndef _GLIBCXX_PROFILE_LIST
    30 #define _GLIBCXX_PROFILE_LIST 1
    33 #include <profile/base.h>
    34 #include <profile/iterator_tracker.h>
    36 namespace std _GLIBCXX_VISIBILITY(default)
    40   template<typename _List>
    45       { return *static_cast<_List*>(this); }
    48       __gnu_profile::__list2slist_info* _M_list2slist_info;
    49       __gnu_profile::__list2vector_info* _M_list2vector_info;
    51       _List_profile() _GLIBCXX_NOEXCEPT
    52       { _M_profile_construct(); }
    55       _M_profile_construct() _GLIBCXX_NOEXCEPT
    57    _M_list2slist_info = __profcxx_list2slist_construct();
    58    _M_list2vector_info = __profcxx_list2vector_construct();
    62       _M_profile_destruct() _GLIBCXX_NOEXCEPT
    64    __profcxx_list2vector_destruct(_M_list2vector_info);
    65    _M_list2vector_info = 0;
    66    __profcxx_list2slist_destruct(_M_list2slist_info);
    67    _M_list2slist_info = 0;
    71       _M_swap(_List_profile& __other)
    73    std::swap(_M_list2slist_info, __other._M_list2slist_info);
    74    std::swap(_M_list2vector_info, __other._M_list2vector_info);
    77 #if __cplusplus >= 201103L
    78       _List_profile(const _List_profile&) noexcept
    80       _List_profile(_List_profile&& __other) noexcept
    85       operator=(const _List_profile&) noexcept
    87    _M_profile_destruct();
    88    _M_profile_construct();
    92       operator=(_List_profile&& __other) noexcept
    95    __other._M_profile_destruct();
    96    __other._M_profile_construct();
   101       { _M_profile_destruct(); }
   104   /** @brief List wrapper with performance instrumentation.  */
   105   template<typename _Tp, typename _Allocator = std::allocator<_Tp> >
   107     : public _GLIBCXX_STD_C::list<_Tp, _Allocator>,
   108       public _List_profile<list<_Tp, _Allocator> >
   110       typedef _GLIBCXX_STD_C::list<_Tp, _Allocator>        _Base;
   113       typedef typename _Base::reference                    reference;
   114       typedef typename _Base::const_reference              const_reference;
   116       typedef __iterator_tracker<typename _Base::iterator, list>
   118       typedef __iterator_tracker<typename _Base::const_iterator, list>
   121       typedef typename _Base::size_type                    size_type;
   122       typedef typename _Base::difference_type              difference_type;
   124       typedef _Tp                                  value_type;
   125       typedef _Allocator                           allocator_type;
   126       typedef typename _Base::pointer                      pointer;
   127       typedef typename _Base::const_pointer                const_pointer;
   128       typedef std::reverse_iterator<iterator>              reverse_iterator;
   129       typedef std::reverse_iterator<const_iterator>        const_reverse_iterator;
   131       // 23.2.2.1 construct/copy/destroy:
   133 #if __cplusplus < 201103L
   135       list(const list& __x)
   141       list(const list&) = default;
   142       list(list&&) = default;
   145       list(initializer_list<value_type> __l,
   146       const allocator_type& __a = allocator_type())
   147       : _Base(__l, __a) { }
   149       list(const list& __x, const allocator_type& __a)
   150       : _Base(__x, __a) { }
   152       list(list&& __x, const allocator_type& __a)
   153       : _Base(std::move(__x), __a) { }
   157       list(const _Allocator& __a) _GLIBCXX_NOEXCEPT
   160 #if __cplusplus >= 201103L
   162       list(size_type __n, const allocator_type& __a = allocator_type())
   163       : _Base(__n, __a) { }
   165       list(size_type __n, const _Tp& __value,
   166       const _Allocator& __a = _Allocator())
   167       : _Base(__n, __value, __a) { }
   170       list(size_type __n, const _Tp& __value = _Tp(),
   171       const _Allocator& __a = _Allocator())
   172       : _Base(__n, __value, __a) { }
   175 #if __cplusplus >= 201103L
   176       template<typename _InputIterator,
   177           typename = std::_RequireInputIter<_InputIterator>>
   179       template<class _InputIterator>
   181       list(_InputIterator __first, _InputIterator __last,
   182       const _Allocator& __a = _Allocator())
   183       : _Base(__first, __last, __a) { }
   185       list(const _Base& __x)
   188 #if __cplusplus < 201103L
   190       operator=(const list& __x)
   192    this->_M_profile_destruct();
   194    this->_M_profile_construct();
   199       operator=(const list&) = default;
   202       operator=(list&&) = default;
   205       operator=(initializer_list<value_type> __l)
   207    this->_M_profile_destruct();
   209    this->_M_profile_construct();
   216       begin() _GLIBCXX_NOEXCEPT
   217       { return iterator(_Base::begin(), this); }
   220       begin() const _GLIBCXX_NOEXCEPT
   221       { return const_iterator(_Base::begin(), this); }
   224       end() _GLIBCXX_NOEXCEPT
   226    __profcxx_list2slist_rewind(this->_M_list2slist_info);
   227    return iterator(_Base::end(), this);
   231       end() const _GLIBCXX_NOEXCEPT
   233    __profcxx_list2slist_rewind(this->_M_list2slist_info);
   234    return const_iterator(_Base::end(), this);
   238       rbegin() _GLIBCXX_NOEXCEPT
   240    __profcxx_list2slist_rewind(this->_M_list2slist_info);
   241    return reverse_iterator(end());
   244       const_reverse_iterator
   245       rbegin() const _GLIBCXX_NOEXCEPT
   247    __profcxx_list2slist_rewind(this->_M_list2slist_info);
   248    return const_reverse_iterator(end());
   252       rend() _GLIBCXX_NOEXCEPT
   253       { return reverse_iterator(begin()); }
   255       const_reverse_iterator
   256       rend() const _GLIBCXX_NOEXCEPT
   257       { return const_reverse_iterator(begin()); }
   259 #if __cplusplus >= 201103L
   261       cbegin() const noexcept
   262       { return const_iterator(_Base::cbegin(), this); }
   265       cend() const noexcept
   266       { return const_iterator(_Base::cend(), this); }
   268       const_reverse_iterator
   269       crbegin() const noexcept
   270       { return const_reverse_iterator(end()); }
   272       const_reverse_iterator
   273       crend() const noexcept
   274       { return const_reverse_iterator(begin()); }
   277       // 23.2.2.2 capacity:
   279       back() _GLIBCXX_NOEXCEPT
   281    __profcxx_list2slist_rewind(this->_M_list2slist_info);
   282    return _Base::back();
   286       back() const _GLIBCXX_NOEXCEPT
   288    __profcxx_list2slist_rewind(this->_M_list2slist_info);
   289    return _Base::back();
   292       // 23.2.2.3 modifiers:
   294       push_front(const value_type& __x)
   296    __profcxx_list2vector_invalid_operator(this->_M_list2vector_info);
   297    __profcxx_list2slist_operation(this->_M_list2slist_info);
   298    _Base::push_front(__x);
   302       pop_front() _GLIBCXX_NOEXCEPT
   304    __profcxx_list2slist_operation(this->_M_list2slist_info);
   309       pop_back() _GLIBCXX_NOEXCEPT
   312    __profcxx_list2slist_rewind(this->_M_list2slist_info);
   315 #if __cplusplus >= 201103L
   316       template<typename... _Args>
   318    emplace(const_iterator __position, _Args&&... __args)
   320      return iterator(_Base::emplace(__position.base(),
   321                                     std::forward<_Args>(__args)...),
   327 #if __cplusplus >= 201103L
   328       insert(const_iterator __pos, const _Tp& __x)
   330       insert(iterator __pos, const _Tp& __x)
   333    _M_profile_insert(__pos, this->size());
   334    return iterator(_Base::insert(__pos.base(), __x), this);
   337 #if __cplusplus >= 201103L
   339       insert(const_iterator __pos, _Tp&& __x)
   341    _M_profile_insert(__pos, this->size());
   342    return iterator(_Base::emplace(__pos.base(), std::move(__x)),
   347       insert(const_iterator __pos, initializer_list<value_type> __l)
   349    _M_profile_insert(__pos, this->size());
   350    return iterator(_Base::insert(__pos.base(), __l), this);
   354 #if __cplusplus >= 201103L
   356       insert(const_iterator __pos, size_type __n, const _Tp& __x)
   358    _M_profile_insert(__pos, this->size());
   359    return iterator(_Base::insert(__pos.base(), __n, __x), this);
   363       insert(iterator __pos, size_type __n, const _Tp& __x)
   365    _M_profile_insert(__pos, this->size());
   366    _Base::insert(__pos.base(), __n, __x);
   370 #if __cplusplus >= 201103L
   371       template<typename _InputIterator,
   372           typename = std::_RequireInputIter<_InputIterator>>
   374    insert(const_iterator __pos, _InputIterator __first,
   375           _InputIterator __last)
   377      _M_profile_insert(__pos, this->size());
   378      return iterator(_Base::insert(__pos.base(), __first, __last),
   382       template<class _InputIterator>
   384    insert(iterator __pos, _InputIterator __first,
   385           _InputIterator __last)
   387      _M_profile_insert(__pos, this->size());
   388      _Base::insert(__pos.base(), __first, __last);
   393 #if __cplusplus >= 201103L
   394       erase(const_iterator __pos) noexcept
   396       erase(iterator __pos)
   398       {    return iterator(_Base::erase(__pos.base()), this); }
   401 #if __cplusplus >= 201103L
   402       erase(const_iterator __pos, const_iterator __last) noexcept
   404       erase(iterator __pos, iterator __last)
   407    // _GLIBCXX_RESOLVE_LIB_DEFECTS
   408    // 151. can't currently clear() empty container
   409    return iterator(_Base::erase(__pos.base(), __last.base()), this);
   414       _GLIBCXX_NOEXCEPT_IF( noexcept(declval<_Base&>().swap(__x)) )
   421       clear() _GLIBCXX_NOEXCEPT
   423    this->_M_profile_destruct();
   425    this->_M_profile_construct();
   428       // 23.2.2.4 list operations:
   430 #if __cplusplus >= 201103L
   431       splice(const_iterator __pos, list&& __x) noexcept
   433       splice(iterator __pos, list& __x)
   435       { this->splice(__pos, _GLIBCXX_MOVE(__x), __x.begin(), __x.end()); }
   437 #if __cplusplus >= 201103L
   439       splice(const_iterator __pos, list& __x) noexcept
   440       { this->splice(__pos, std::move(__x)); }
   443       splice(const_iterator __pos, list& __x, const_iterator __i)
   444       { this->splice(__pos, std::move(__x), __i); }
   448 #if __cplusplus >= 201103L
   449       splice(const_iterator __pos, list&& __x, const_iterator __i) noexcept
   451       splice(iterator __pos, list& __x, iterator __i)
   454    // We used to perform the splice_alloc check:  not anymore, redundant
   455    // after implementing the relevant bits of N1599.
   457    // _GLIBCXX_RESOLVE_LIB_DEFECTS
   458    _Base::splice(__pos.base(), _GLIBCXX_MOVE(__x._M_base()),
   463 #if __cplusplus >= 201103L
   464       splice(const_iterator __pos, list&& __x, const_iterator __first,
   465         const_iterator __last) noexcept
   467       splice(iterator __pos, list& __x, iterator __first,
   471    _Base::splice(__pos.base(), _GLIBCXX_MOVE(__x._M_base()),
   472                  __first.base(), __last.base());
   475 #if __cplusplus >= 201103L
   477       splice(const_iterator __pos, list& __x,
   478         const_iterator __first, const_iterator __last) noexcept
   479       { this->splice(__pos, std::move(__x), __first, __last); }
   483       remove(const _Tp& __value)
   485    for (iterator __x = begin(); __x != end(); )
   494       template<class _Predicate>
   496    remove_if(_Predicate __pred)
   498      for (iterator __x = begin(); __x != end(); )
   500          __profcxx_list2slist_operation(this->_M_list2slist_info);
   511    iterator __first = begin();
   512    iterator __last = end();
   513    if (__first == __last)
   515    iterator __next = __first;
   516    while (++__next != __last)
   518        __profcxx_list2slist_operation(this->_M_list2slist_info);
   519        if (*__first == *__next)
   527       template<class _BinaryPredicate>
   529    unique(_BinaryPredicate __binary_pred)
   531      iterator __first = begin();
   532      iterator __last = end();
   533      if (__first == __last)
   535      iterator __next = __first;
   536      while (++__next != __last)
   538          __profcxx_list2slist_operation(this->_M_list2slist_info);
   539          if (__binary_pred(*__first, *__next))
   548 #if __cplusplus >= 201103L
   553       { _Base::merge(_GLIBCXX_MOVE(__x._M_base())); }
   555 #if __cplusplus >= 201103L
   558       { this->merge(std::move(__x)); }
   561       template<class _Compare>
   563 #if __cplusplus >= 201103L
   564    merge(list&& __x, _Compare __comp)
   566    merge(list& __x, _Compare __comp)
   568    { _Base::merge(_GLIBCXX_MOVE(__x._M_base()), __comp); }
   570 #if __cplusplus >= 201103L
   571       template<typename _Compare>
   573    merge(list& __x, _Compare __comp)
   574    { this->merge(std::move(__x), __comp); }
   578       _M_base() _GLIBCXX_NOEXCEPT  { return *this; }
   581       _M_base() const _GLIBCXX_NOEXCEPT    { return *this; }
   583       void _M_profile_iterate(int __rewind = 0) const
   585    __profcxx_list2slist_operation(this->_M_list2slist_info);
   586    __profcxx_list2vector_iterate(this->_M_list2vector_info, __rewind);
   588      __profcxx_list2slist_rewind(this->_M_list2slist_info);
   593       _M_profile_insert(const_iterator __pos, size_type __size)
   595    size_type __shift = 0;
   596    typename _Base::const_iterator __it = __pos.base();
   597    for (; __it != _Base::end(); ++__it)
   599    __profcxx_list2slist_rewind(this->_M_list2slist_info);
   600    __profcxx_list2slist_operation(this->_M_list2slist_info);
   601    __profcxx_list2vector_insert(this->_M_list2vector_info, __shift, __size);
   605   template<typename _Tp, typename _Alloc>
   607     operator==(const list<_Tp, _Alloc>& __lhs,
   608           const list<_Tp, _Alloc>& __rhs)
   609     { return __lhs._M_base() == __rhs._M_base(); }
   611   template<typename _Tp, typename _Alloc>
   613     operator!=(const list<_Tp, _Alloc>& __lhs,
   614           const list<_Tp, _Alloc>& __rhs)
   615     { return __lhs._M_base() != __rhs._M_base(); }
   617   template<typename _Tp, typename _Alloc>
   619     operator<(const list<_Tp, _Alloc>& __lhs,
   620          const list<_Tp, _Alloc>& __rhs)
   621     { return __lhs._M_base() < __rhs._M_base(); }
   623   template<typename _Tp, typename _Alloc>
   625     operator<=(const list<_Tp, _Alloc>& __lhs,
   626           const list<_Tp, _Alloc>& __rhs)
   627     { return __lhs._M_base() <= __rhs._M_base(); }
   629   template<typename _Tp, typename _Alloc>
   631     operator>=(const list<_Tp, _Alloc>& __lhs,
   632           const list<_Tp, _Alloc>& __rhs)
   633     { return __lhs._M_base() >= __rhs._M_base(); }
   635   template<typename _Tp, typename _Alloc>
   637     operator>(const list<_Tp, _Alloc>& __lhs,
   638          const list<_Tp, _Alloc>& __rhs)
   639     { return __lhs._M_base() > __rhs._M_base(); }
   641   template<typename _Tp, typename _Alloc>
   643     swap(list<_Tp, _Alloc>& __lhs, list<_Tp, _Alloc>& __rhs)
   644     _GLIBCXX_NOEXCEPT_IF(noexcept(__lhs.swap(__rhs)))
   645     { __lhs.swap(__rhs); }
   647 } // namespace __profile