Add end_node, is_empty, is_sentinel, set_sentinel, transfer_after and detach_and_dispose functions

This commit is contained in:
Ion Gaztañaga 2022-05-04 22:54:38 +02:00
parent d70f8667e1
commit dbde900bf9
2 changed files with 142 additions and 0 deletions

View File

@ -18,6 +18,7 @@
#include <boost/intrusive/detail/config_begin.hpp>
#include <boost/intrusive/intrusive_fwd.hpp>
#include <boost/intrusive/detail/common_slist_algorithms.hpp>
#include <boost/intrusive/detail/uncast.hpp>
#include <boost/intrusive/detail/algo_type.hpp>
#if defined(BOOST_HAS_PRAGMA_ONCE)
@ -131,6 +132,10 @@ class circular_slist_algorithms
//!
//! <b>Throws</b>: Nothing.
static void transfer_after(node_ptr p, node_ptr b, node_ptr e) BOOST_NOEXCEPT;
#else
using base_t::transfer_after;
#endif //#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
@ -144,6 +149,41 @@ class circular_slist_algorithms
BOOST_INTRUSIVE_FORCEINLINE static void init_header(node_ptr this_node) BOOST_NOEXCEPT
{ NodeTraits::set_next(this_node, this_node); }
//! <b>Requires</b>: 'p' is the first node of a list.
//!
//! <b>Effects</b>: Returns a pointer to a node that represents the "end" (one past end) node
//!
//! <b>Complexity</b>: Constant time.
//!
//! <b>Throws</b>: Nothing.
BOOST_INTRUSIVE_FORCEINLINE static node_ptr end_node(const_node_ptr p) BOOST_NOEXCEPT
{ return detail::uncast(p); }
//! <b>Effects</b>: Returns true if this_node_points to an empty list.
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
BOOST_INTRUSIVE_FORCEINLINE static bool is_empty(const_node_ptr this_node) BOOST_NOEXCEPT
{ return NodeTraits::get_next(this_node) == this_node; }
//! <b>Effects</b>: Returns true if this_node points to a sentinel node.
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
BOOST_INTRUSIVE_FORCEINLINE static bool is_sentinel(const_node_ptr this_node) BOOST_NOEXCEPT
{ return NodeTraits::get_next(this_node) == node_ptr(); }
//! <b>Effects</b>: Marks this node as a "sentinel" node, a special state that is different from "empty",
//! that can be used to mark a special state of the list
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
BOOST_INTRUSIVE_FORCEINLINE static void set_sentinel(node_ptr this_node) BOOST_NOEXCEPT
{ NodeTraits::set_next(this_node, node_ptr()); }
//! <b>Requires</b>: this_node and prev_init_node must be in the same circular list.
//!
//! <b>Effects</b>: Returns the previous node of this_node in the circular list starting.
@ -386,6 +426,35 @@ class circular_slist_algorithms
base_t::link_after(new_last, p);
return new_last;
}
//! <b>Requires</b>: other must be a list and p must be a node of a different list.
//!
//! <b>Effects</b>: Transfers all nodes from other after p in p's list.
//!
//! <b>Complexity</b>: Linear
//!
//! <b>Throws</b>: Nothing.
static void transfer_after(node_ptr p, node_ptr other) BOOST_NOEXCEPT
{
node_ptr other_last((get_previous_node)(other));
base_t::transfer_after(p, other, other_last);
}
//! <b>Requires</b>: "disposer" must be an object function
//! taking a node_ptr parameter and shouldn't throw.
//!
//! <b>Effects</b>: Unlinks all nodes reachable from p (but not p) and calls
//! <tt>void disposer::operator()(node_ptr)</tt> for every node of the list
//! where p is linked.
//!
//! <b>Returns</b>: The number of disposed nodes
//!
//! <b>Complexity</b>: Linear to the number of element of the list.
//!
//! <b>Throws</b>: Nothing.
template<class Disposer>
BOOST_INTRUSIVE_FORCEINLINE static std::size_t detach_and_dispose(node_ptr p, Disposer disposer) BOOST_NOEXCEPT
{ return base_t::unlink_after_and_dispose(p, p, disposer); }
};
/// @cond

View File

@ -138,6 +138,10 @@ class linear_slist_algorithms
//! <b>Throws</b>: Nothing.
static void transfer_after(node_ptr p, node_ptr b, node_ptr e) BOOST_NOEXCEPT;
#else
using base_t::transfer_after;
#endif //#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
//! <b>Effects</b>: Constructs an empty list, making this_node the only
@ -150,6 +154,41 @@ class linear_slist_algorithms
BOOST_INTRUSIVE_FORCEINLINE static void init_header(node_ptr this_node) BOOST_NOEXCEPT
{ NodeTraits::set_next(this_node, node_ptr ()); }
//! <b>Requires</b>: 'p' is the first node of a list.
//!
//! <b>Effects</b>: Returns a pointer to a node that represents the "end" (one past end) node
//!
//! <b>Complexity</b>: Constant time.
//!
//! <b>Throws</b>: Nothing.
BOOST_INTRUSIVE_FORCEINLINE static node_ptr end_node(const_node_ptr) BOOST_NOEXCEPT
{ return node_ptr(); }
//! <b>Effects</b>: Returns true if this_node_points to an empty list.
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
BOOST_INTRUSIVE_FORCEINLINE static bool is_empty(const_node_ptr this_node) BOOST_NOEXCEPT
{ return !NodeTraits::get_next(this_node); }
//! <b>Effects</b>: Returns true if this_node points to a sentinel node.
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
BOOST_INTRUSIVE_FORCEINLINE static bool is_sentinel(const_node_ptr this_node) BOOST_NOEXCEPT
{ return NodeTraits::get_next(this_node) == this_node; }
//! <b>Effects</b>: Marks this node as a "sentinel" node, a special state that is different from "empty",
//! that can be used to mark a special state of the list
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
BOOST_INTRUSIVE_FORCEINLINE static void set_sentinel(node_ptr this_node) BOOST_NOEXCEPT
{ NodeTraits::set_next(this_node, this_node); }
//! <b>Requires</b>: this_node and prev_init_node must be in the same linear list.
//!
//! <b>Effects</b>: Returns the previous node of this_node in the linear list starting.
@ -329,6 +368,40 @@ class linear_slist_algorithms
ret.second = new_last;
return ret;
}
//! <b>Requires</b>: other must be a list and p must be a node of a different linear list.
//!
//! <b>Effects</b>: Transfers all nodes from other after p in p's linear list.
//!
//! <b>Complexity</b>: Linear
//!
//! <b>Throws</b>: Nothing.
static void transfer_after(node_ptr p, node_ptr other) BOOST_NOEXCEPT
{
if ((is_empty)(p)) {
(swap_trailing_nodes)(p, other);
}
else {
node_ptr other_last((get_previous_node)(other, node_ptr()));
base_t::transfer_after(p, other, other_last);
}
}
//! <b>Requires</b>: "disposer" must be an object function
//! taking a node_ptr parameter and shouldn't throw.
//!
//! <b>Effects</b>: Unlinks all nodes reachable from p (but not p) and calls
//! <tt>void disposer::operator()(node_ptr)</tt> for every node of the list
//! where p is linked.
//!
//! <b>Returns</b>: The number of disposed nodes
//!
//! <b>Complexity</b>: Linear to the number of element of the list.
//!
//! <b>Throws</b>: Nothing.
template<class Disposer>
BOOST_INTRUSIVE_FORCEINLINE static std::size_t detach_and_dispose(node_ptr p, Disposer disposer) BOOST_NOEXCEPT
{ return base_t::unlink_after_and_dispose(p, node_ptr(), disposer); }
};
/// @cond