From d70f8667e12b77c8d078dc7d4856170ee750a3e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Wed, 4 May 2022 22:52:15 +0200 Subject: [PATCH] Add unlink_after_and_dispose and detach_and_dispose functions --- .../detail/common_slist_algorithms.hpp | 71 ++++++++++++++++++- 1 file changed, 70 insertions(+), 1 deletion(-) diff --git a/include/boost/intrusive/detail/common_slist_algorithms.hpp b/include/boost/intrusive/detail/common_slist_algorithms.hpp index 1d5413b..e7aba10 100644 --- a/include/boost/intrusive/detail/common_slist_algorithms.hpp +++ b/include/boost/intrusive/detail/common_slist_algorithms.hpp @@ -64,7 +64,7 @@ class common_slist_algorithms BOOST_INTRUSIVE_FORCEINLINE static bool inited(const_node_ptr this_node) BOOST_NOEXCEPT { return !NodeTraits::get_next(this_node); } - static void unlink_after(node_ptr prev_node) BOOST_NOEXCEPT + BOOST_INTRUSIVE_FORCEINLINE static void unlink_after(node_ptr prev_node) BOOST_NOEXCEPT { const_node_ptr this_node(NodeTraits::get_next(prev_node)); NodeTraits::set_next(prev_node, NodeTraits::get_next(this_node)); @@ -177,6 +177,75 @@ class common_slist_algorithms } return result; } + + //! Requires: "disposer" must be an object function + //! taking a node_ptr parameter and shouldn't throw. + //! + //! Effects: Calls + //! void disposer::operator()(node_ptr) for every node of the list + //! [p, e). + //! + //! Returns: The number of unlinked/disposed nodes + //! + //! Complexity: Linear to the number of element of the list. + //! + //! Throws: Nothing. + template + static std::size_t unlink_after_and_dispose(node_ptr bb, node_ptr e, Disposer disposer) BOOST_NOEXCEPT + { + std::size_t n = 0u; + node_ptr i = node_traits::get_next(bb); + while (i != e) { + node_ptr to_erase(i); + i = node_traits::get_next(i); + disposer(to_erase); + ++n; + } + node_traits::set_next(bb, e); + return n; + } + + //! Requires: "disposer" must be an object function + //! taking a node_ptr parameter and shouldn't throw. + //! + //! Effects: Calls + //! void disposer::operator()(node_ptr) for every node of the list + //! after p (but not for p). Works for circular or linear lists + //! + //! Complexity: Linear to the number of element of the list. + //! + //! Throws: Nothing. + template + BOOST_INTRUSIVE_FORCEINLINE static void unlink_after_and_dispose(node_ptr bb, Disposer disposer) BOOST_NOEXCEPT + { + node_ptr i = node_traits::get_next(bb); + node_traits::set_next(bb, node_traits::get_next(i)); + disposer(i); + } + + //! Requires: "disposer" must be an object function + //! taking a node_ptr parameter and shouldn't throw. + //! + //! Effects: Unlinks all nodes reachable from p (but not p) and calls + //! void disposer::operator()(node_ptr) for every node of the list + //! where p is linked. + //! + //! Complexity: Linear to the number of element of the list. + //! + //! Throws: Nothing. + template + static std::size_t detach_and_dispose(node_ptr p, Disposer disposer) BOOST_NOEXCEPT + { + std::size_t n = 0; + node_ptr i = node_traits::get_next(p); + while ( i != p || i != node_ptr() ) { + node_ptr to_erase(i); + i = node_traits::get_next(i); + disposer(to_erase); + } + node_traits::set_next(p, i); + return n; + } }; /// @endcond