[PATCH 1/3] libstdc++: Refactor std::list::size() for cxx11 ABI
Jonathan Wakely
jwakely@redhat.com
Tue Dec 3 21:36:08 GMT 2024
Pushed
On Fri, 15 Nov 2024 at 15:26, Jonathan Wakely <jwakely@redhat.com> wrote:
>
> Remove some preprocessor conditionals by moving the _M_size member for
> the cxx11 ABI into a new base class, which is empty for the gcc4-compat
> ABI.
>
> Move some unused members that are only retained for ABI compatibility to
> the end of _List_base and add an explanatory comment. Stop using
> list::_M_node_count and list::_D_distance and then move them to the end
> of std::list with a comment too.
>
> libstdc++-v3/ChangeLog:
>
> * include/bits/stl_list.h (_List_size): New struct.
> (_List_node_header): Replace _M_size member with _List_size base
> class.
> (_List_node_header(_List_node_header&&)): Replace explicit uses
> of _M_size with initializing the base.
> (_List_node_header::_M_init): Likewise.
> (_List_base::_S_distance, _List_base::_M_distance)
> (_List_base::_M_node_count): Move to end of class body and add
> comment.
> (list::_S_distance, list::_M_node_count): Likewise.
> (list::size): Inline _M_node_count effects to here.
> (list::splice(iterator, list&, iterator, iterator)): Use #if and
> call std::distance instead of _S_distance.
> ---
>
> Tested x86_64-linux.
>
> Pull request at https://forge.sourceware.org/gcc/gcc-TEST/pulls/25
>
> libstdc++-v3/include/bits/stl_list.h | 179 +++++++++++++++------------
> 1 file changed, 97 insertions(+), 82 deletions(-)
>
> diff --git a/libstdc++-v3/include/bits/stl_list.h b/libstdc++-v3/include/bits/stl_list.h
> index 7deb04b4bfe..d51fde90e2b 100644
> --- a/libstdc++-v3/include/bits/stl_list.h
> +++ b/libstdc++-v3/include/bits/stl_list.h
> @@ -104,22 +104,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> _M_unhook() _GLIBCXX_USE_NOEXCEPT;
> };
>
> - /// The %list node header.
> - struct _List_node_header : public _List_node_base
> + struct _List_size
> {
> #if _GLIBCXX_USE_CXX11_ABI
> - std::size_t _M_size;
> + // Store the size here so that std::list::size() is fast.
> + size_t _M_size;
> #endif
> + };
>
> +
> + /// The %list node header.
> + struct _List_node_header : public _List_node_base, _List_size
> + {
> _List_node_header() _GLIBCXX_NOEXCEPT
> { _M_init(); }
>
> #if __cplusplus >= 201103L
> _List_node_header(_List_node_header&& __x) noexcept
> - : _List_node_base{ __x._M_next, __x._M_prev }
> -# if _GLIBCXX_USE_CXX11_ABI
> - , _M_size(__x._M_size)
> -# endif
> + : _List_node_base(__x), _List_size(__x)
> {
> if (__x._M_base()->_M_next == __x._M_base())
> this->_M_next = this->_M_prev = this;
> @@ -142,9 +144,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> __node->_M_next = __xnode->_M_next;
> __node->_M_prev = __xnode->_M_prev;
> __node->_M_next->_M_prev = __node->_M_prev->_M_next = __node;
> -# if _GLIBCXX_USE_CXX11_ABI
> - _M_size = __x._M_size;
> -# endif
> + _List_size::operator=(__x);
> __x._M_init();
> }
> }
> @@ -154,9 +154,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> _M_init() _GLIBCXX_NOEXCEPT
> {
> this->_M_next = this->_M_prev = this;
> -#if _GLIBCXX_USE_CXX11_ABI
> - this->_M_size = 0;
> -#endif
> + _List_size::operator=(_List_size());
> }
>
> private:
> @@ -436,21 +434,6 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
> rebind<_List_node<_Tp> >::other _Node_alloc_type;
> typedef __gnu_cxx::__alloc_traits<_Node_alloc_type> _Node_alloc_traits;
>
> -#if !_GLIBCXX_INLINE_VERSION
> - static size_t
> - _S_distance(const __detail::_List_node_base* __first,
> - const __detail::_List_node_base* __last)
> - {
> - size_t __n = 0;
> - while (__first != __last)
> - {
> - __first = __first->_M_next;
> - ++__n;
> - }
> - return __n;
> - }
> -#endif
> -
> struct _List_impl
> : public _Node_alloc_type
> {
> @@ -488,33 +471,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
> void _M_inc_size(size_t __n) { _M_impl._M_node._M_size += __n; }
>
> void _M_dec_size(size_t __n) { _M_impl._M_node._M_size -= __n; }
> -
> -# if !_GLIBCXX_INLINE_VERSION
> - size_t
> - _M_distance(const __detail::_List_node_base* __first,
> - const __detail::_List_node_base* __last) const
> - { return _S_distance(__first, __last); }
> -
> - // return the stored size
> - size_t _M_node_count() const { return _M_get_size(); }
> -# endif
> #else
> // dummy implementations used when the size is not stored
> size_t _M_get_size() const { return 0; }
> void _M_set_size(size_t) { }
> void _M_inc_size(size_t) { }
> void _M_dec_size(size_t) { }
> -
> -# if !_GLIBCXX_INLINE_VERSION
> - size_t _M_distance(const void*, const void*) const { return 0; }
> -
> - // count the number of nodes
> - size_t _M_node_count() const
> - {
> - return _S_distance(_M_impl._M_node._M_next,
> - std::__addressof(_M_impl._M_node));
> - }
> -# endif
> #endif
>
> typename _Node_alloc_traits::pointer
> @@ -549,16 +511,6 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
> #if __cplusplus >= 201103L
> _List_base(_List_base&&) = default;
>
> -# if !_GLIBCXX_INLINE_VERSION
> - _List_base(_List_base&& __x, _Node_alloc_type&& __a)
> - : _M_impl(std::move(__a))
> - {
> - if (__x._M_get_Node_allocator() == _M_get_Node_allocator())
> - _M_move_nodes(std::move(__x));
> - // else caller must move individual elements.
> - }
> -# endif
> -
> // Used when allocator is_always_equal.
> _List_base(_Node_alloc_type&& __a, _List_base&& __x)
> : _M_impl(std::move(__a), std::move(__x._M_impl))
> @@ -584,6 +536,57 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
> void
> _M_init() _GLIBCXX_NOEXCEPT
> { this->_M_impl._M_node._M_init(); }
> +
> +#if !_GLIBCXX_INLINE_VERSION
> + // XXX GLIBCXX_ABI Deprecated
> + // These members are unused by std::list now, but we keep them here
> + // so that an explicit instantiation of std::list will define them.
> + // This ensures that explicit instantiations still define these symbols,
> + // so that explicit instantiation declarations of std::list that were
> + // compiled with old versions of GCC can still find these old symbols.
> +
> +# if __cplusplus >= 201103L
> + _List_base(_List_base&& __x, _Node_alloc_type&& __a)
> + : _M_impl(std::move(__a))
> + {
> + if (__x._M_get_Node_allocator() == _M_get_Node_allocator())
> + _M_move_nodes(std::move(__x));
> + // else caller must move individual elements.
> + }
> +# endif
> +
> + static size_t
> + _S_distance(const __detail::_List_node_base* __first,
> + const __detail::_List_node_base* __last)
> + {
> + size_t __n = 0;
> + while (__first != __last)
> + {
> + __first = __first->_M_next;
> + ++__n;
> + }
> + return __n;
> + }
> +
> +#if _GLIBCXX_USE_CXX11_ABI
> + size_t
> + _M_distance(const __detail::_List_node_base* __first,
> + const __detail::_List_node_base* __last) const
> + { return _S_distance(__first, __last); }
> +
> + // return the stored size
> + size_t _M_node_count() const { return _M_get_size(); }
> +#else
> + size_t _M_distance(const void*, const void*) const { return 0; }
> +
> + // count the number of nodes
> + size_t _M_node_count() const
> + {
> + return _S_distance(_M_impl._M_node._M_next,
> + std::__addressof(_M_impl._M_node));
> + }
> +#endif
> +#endif // ! INLINE_VERSION
> };
>
> /**
> @@ -721,27 +724,6 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
> }
> #endif
>
> -#if _GLIBCXX_USE_CXX11_ABI
> - static size_t
> - _S_distance(const_iterator __first, const_iterator __last)
> - { return std::distance(__first, __last); }
> -
> - // return the stored size
> - size_t
> - _M_node_count() const
> - { return this->_M_get_size(); }
> -#else
> - // dummy implementations used when the size is not stored
> - static size_t
> - _S_distance(const_iterator, const_iterator)
> - { return 0; }
> -
> - // count the number of nodes
> - size_t
> - _M_node_count() const
> - { return std::distance(begin(), end()); }
> -#endif
> -
> public:
> // [23.2.2.1] construct/copy/destroy
> // (assign() and get_allocator() are also listed in this section)
> @@ -1193,7 +1175,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
> _GLIBCXX_NODISCARD
> size_type
> size() const _GLIBCXX_NOEXCEPT
> - { return _M_node_count(); }
> + {
> +#if _GLIBCXX_USE_CXX11_ABI
> + return this->_M_get_size(); // return the stored size
> +#else
> + return std::distance(begin(), end()); // count the number of nodes
> +#endif
> + }
>
> /** Returns the size() of the largest possible %list. */
> _GLIBCXX_NODISCARD
> @@ -1851,9 +1839,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
> if (this != std::__addressof(__x))
> _M_check_equal_allocators(__x);
>
> - size_t __n = _S_distance(__first, __last);
> +#if _GLIBCXX_USE_CXX11_ABI
> + size_t __n = std::distance(__first, __last);
> this->_M_inc_size(__n);
> __x._M_dec_size(__n);
> +#endif
>
> this->_M_transfer(__position._M_const_cast(),
> __first._M_const_cast(),
> @@ -2213,6 +2203,31 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
> { explicit _Finalize_merge(list&, list&, const iterator&) { } };
> #endif
>
> +#if !_GLIBCXX_INLINE_VERSION
> + // XXX GLIBCXX_ABI Deprecated
> + // These members are unused by std::list now, but we keep them here
> + // so that an explicit instantiation of std::list will define them.
> + // This ensures that any objects or libraries compiled against old
> + // versions of GCC will still be able to use the symbols.
> +
> +#if _GLIBCXX_USE_CXX11_ABI
> + static size_t
> + _S_distance(const_iterator __first, const_iterator __last)
> + { return std::distance(__first, __last); }
> +
> + size_t
> + _M_node_count() const
> + { return this->_M_get_size(); }
> +#else
> + static size_t
> + _S_distance(const_iterator, const_iterator)
> + { return 0; }
> +
> + size_t
> + _M_node_count() const
> + { return std::distance(begin(), end()); }
> +#endif
> +#endif // ! INLINE_VERSION
> };
>
> #if __cpp_deduction_guides >= 201606
> --
> 2.47.0
>
More information about the Libstdc++
mailing list