Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:38:42

0001 /////////////////////////////////////////////////////////////////////////////
0002 //
0003 // (C) Copyright Olaf Krzikalla 2004-2006.
0004 // (C) Copyright Ion Gaztanaga  2006-2014
0005 //
0006 // Distributed under the Boost Software License, Version 1.0.
0007 //    (See accompanying file LICENSE_1_0.txt or copy at
0008 //          http://www.boost.org/LICENSE_1_0.txt)
0009 //
0010 // See http://www.boost.org/libs/intrusive for documentation.
0011 //
0012 /////////////////////////////////////////////////////////////////////////////
0013 
0014 #ifndef BOOST_INTRUSIVE_LINEAR_SLIST_ALGORITHMS_HPP
0015 #define BOOST_INTRUSIVE_LINEAR_SLIST_ALGORITHMS_HPP
0016 
0017 #include <boost/intrusive/detail/config_begin.hpp>
0018 #include <boost/intrusive/intrusive_fwd.hpp>
0019 #include <boost/intrusive/detail/common_slist_algorithms.hpp>
0020 #include <boost/intrusive/detail/algo_type.hpp>
0021 #include <cstddef>
0022 #include <boost/intrusive/detail/twin.hpp>   //for node_pair
0023 
0024 #if defined(BOOST_HAS_PRAGMA_ONCE)
0025 #  pragma once
0026 #endif
0027 
0028 namespace boost {
0029 namespace intrusive {
0030 
0031 //! linear_slist_algorithms provides basic algorithms to manipulate nodes
0032 //! forming a linear singly linked list.
0033 //!
0034 //! linear_slist_algorithms is configured with a NodeTraits class, which encapsulates the
0035 //! information about the node to be manipulated. NodeTraits must support the
0036 //! following interface:
0037 //!
0038 //! <b>Typedefs</b>:
0039 //!
0040 //! <tt>node</tt>: The type of the node that forms the linear list
0041 //!
0042 //! <tt>node_ptr</tt>: A pointer to a node
0043 //!
0044 //! <tt>const_node_ptr</tt>: A pointer to a const node
0045 //!
0046 //! <b>Static functions</b>:
0047 //!
0048 //! <tt>static node_ptr get_next(const_node_ptr n);</tt>
0049 //!
0050 //! <tt>static void set_next(node_ptr n, node_ptr next);</tt>
0051 template<class NodeTraits>
0052 class linear_slist_algorithms
0053    /// @cond
0054    : public detail::common_slist_algorithms<NodeTraits>
0055    /// @endcond
0056 {
0057    /// @cond
0058    typedef detail::common_slist_algorithms<NodeTraits> base_t;
0059    /// @endcond
0060    public:
0061    typedef typename NodeTraits::node            node;
0062    typedef typename NodeTraits::node_ptr        node_ptr;
0063    typedef typename NodeTraits::const_node_ptr  const_node_ptr;
0064    typedef NodeTraits                           node_traits;
0065    //A simple struct containing:
0066    //
0067    // typedef node_ptr type;
0068    // node_ptr first;
0069    // node_ptr second;
0070    typedef twin<node_ptr>                  node_pair;
0071 
0072    #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
0073 
0074    //! <b>Effects</b>: Constructs an non-used list element, putting the next
0075    //!   pointer to null:
0076    //!  <tt>NodeTraits::get_next(this_node) == node_ptr()</tt>
0077    //!
0078    //! <b>Complexity</b>: Constant
0079    //!
0080    //! <b>Throws</b>: Nothing.
0081    static void init(node_ptr this_node) BOOST_NOEXCEPT;
0082 
0083    //! <b>Requires</b>: this_node must be in a circular list or be an empty circular list.
0084    //!
0085    //! <b>Effects</b>: Returns true is "this_node" is the only node of a circular list:
0086    //!  or it's a not inserted node:
0087    //!  <tt>return node_ptr() == NodeTraits::get_next(this_node) || NodeTraits::get_next(this_node) == this_node</tt>
0088    //!
0089    //! <b>Complexity</b>: Constant
0090    //!
0091    //! <b>Throws</b>: Nothing.
0092    static bool unique(const_node_ptr this_node) BOOST_NOEXCEPT;
0093 
0094    //! <b>Effects</b>: Returns true is "this_node" has the same state as if
0095    //!  it was inited using "init(node_ptr)"
0096    //!
0097    //! <b>Complexity</b>: Constant
0098    //!
0099    //! <b>Throws</b>: Nothing.
0100    static bool inited(const_node_ptr this_node) BOOST_NOEXCEPT;
0101 
0102    //! <b>Requires</b>: prev_node must be in a circular list or be an empty circular list.
0103    //!
0104    //! <b>Effects</b>: Unlinks the next node of prev_node from the circular list.
0105    //!
0106    //! <b>Complexity</b>: Constant
0107    //!
0108    //! <b>Throws</b>: Nothing.
0109    static void unlink_after(node_ptr prev_node) BOOST_NOEXCEPT;
0110 
0111    //! <b>Requires</b>: prev_node and last_node must be in a circular list
0112    //!  or be an empty circular list.
0113    //!
0114    //! <b>Effects</b>: Unlinks the range (prev_node, last_node) from the linear list.
0115    //!
0116    //! <b>Complexity</b>: Constant
0117    //!
0118    //! <b>Throws</b>: Nothing.
0119    static void unlink_after(node_ptr prev_node, node_ptr last_node) BOOST_NOEXCEPT;
0120 
0121    //! <b>Requires</b>: prev_node must be a node of a linear list.
0122    //!
0123    //! <b>Effects</b>: Links this_node after prev_node in the linear list.
0124    //!
0125    //! <b>Complexity</b>: Constant
0126    //!
0127    //! <b>Throws</b>: Nothing.
0128    static void link_after(node_ptr prev_node, node_ptr this_node) BOOST_NOEXCEPT;
0129 
0130    //! <b>Requires</b>: b and e must be nodes of the same linear list or an empty range.
0131    //!   and p must be a node of a different linear list.
0132    //!
0133    //! <b>Effects</b>: Removes the nodes from (b, e] range from their linear list and inserts
0134    //!   them after p in p's linear list.
0135    //!
0136    //! <b>Complexity</b>: Constant
0137    //!
0138    //! <b>Throws</b>: Nothing.
0139    static void transfer_after(node_ptr p, node_ptr b, node_ptr e) BOOST_NOEXCEPT;
0140 
0141    #else
0142 
0143    using base_t::transfer_after;
0144 
0145    #endif   //#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
0146 
0147    //! <b>Effects</b>: Constructs an empty list, making this_node the only
0148    //!   node of the circular list:
0149    //!  <tt>NodeTraits::get_next(this_node) == this_node</tt>.
0150    //!
0151    //! <b>Complexity</b>: Constant
0152    //!
0153    //! <b>Throws</b>: Nothing.
0154    BOOST_INTRUSIVE_FORCEINLINE static void init_header(node_ptr this_node) BOOST_NOEXCEPT
0155    {  NodeTraits::set_next(this_node, node_ptr ());  }
0156 
0157    //! <b>Requires</b>: 'p' is the first node of a list.
0158    //!
0159    //! <b>Effects</b>: Returns a pointer to a node that represents the "end" (one past end) node
0160    //!
0161    //! <b>Complexity</b>: Constant time.
0162    //!
0163    //! <b>Throws</b>: Nothing.
0164    BOOST_INTRUSIVE_FORCEINLINE static node_ptr end_node(const_node_ptr) BOOST_NOEXCEPT
0165    {  return node_ptr();   }
0166 
0167    //! <b>Effects</b>: Returns true if this_node_points to an empty list.
0168    //! 
0169    //! <b>Complexity</b>: Constant
0170    //!
0171    //! <b>Throws</b>: Nothing.
0172    BOOST_INTRUSIVE_FORCEINLINE static bool is_empty(const_node_ptr this_node) BOOST_NOEXCEPT
0173    {  return !NodeTraits::get_next(this_node);  }
0174 
0175    //! <b>Effects</b>: Returns true if this_node points to a sentinel node.
0176    //! 
0177    //! <b>Complexity</b>: Constant
0178    //!
0179    //! <b>Throws</b>: Nothing.
0180    BOOST_INTRUSIVE_FORCEINLINE static bool is_sentinel(const_node_ptr this_node) BOOST_NOEXCEPT
0181    {  return NodeTraits::get_next(this_node) == this_node;  }
0182 
0183    //! <b>Effects</b>: Marks this node as a "sentinel" node, a special state that is different from "empty",
0184    //!                 that can be used to mark a special state of the list
0185    //!
0186    //! <b>Complexity</b>: Constant
0187    //!
0188    //! <b>Throws</b>: Nothing.
0189    BOOST_INTRUSIVE_FORCEINLINE static void set_sentinel(node_ptr this_node) BOOST_NOEXCEPT
0190    {  NodeTraits::set_next(this_node, this_node);   }
0191 
0192    //! <b>Requires</b>: this_node and prev_init_node must be in the same linear list.
0193    //!
0194    //! <b>Effects</b>: Returns the previous node of this_node in the linear list starting.
0195    //!   the search from prev_init_node. The first node checked for equality
0196    //!   is NodeTraits::get_next(prev_init_node).
0197    //!
0198    //! <b>Complexity</b>: Linear to the number of elements between prev_init_node and this_node.
0199    //!
0200    //! <b>Throws</b>: Nothing.
0201    BOOST_INTRUSIVE_FORCEINLINE static node_ptr
0202       get_previous_node(node_ptr prev_init_node, node_ptr this_node) BOOST_NOEXCEPT
0203    {  return base_t::get_previous_node(prev_init_node, this_node);   }
0204 
0205    //! <b>Requires</b>: this_node must be in a linear list or be an empty linear list.
0206    //!
0207    //! <b>Effects</b>: Returns the number of nodes in a linear list. If the linear list
0208    //!  is empty, returns 1.
0209    //!
0210    //! <b>Complexity</b>: Linear
0211    //!
0212    //! <b>Throws</b>: Nothing.
0213    static std::size_t count(const_node_ptr this_node) BOOST_NOEXCEPT
0214    {
0215       std::size_t result = 0;
0216       const_node_ptr p = this_node;
0217       do{
0218          p = NodeTraits::get_next(p);
0219          ++result;
0220       } while (p);
0221       return result;
0222    }
0223 
0224    //! <b>Requires</b>: this_node and other_node must be nodes inserted
0225    //!  in linear lists or be empty linear lists.
0226    //!
0227    //! <b>Effects</b>: Moves all the nodes previously chained after this_node after other_node
0228    //!   and vice-versa.
0229    //!
0230    //! <b>Complexity</b>: Constant
0231    //!
0232    //! <b>Throws</b>: Nothing.
0233    BOOST_INTRUSIVE_FORCEINLINE static void swap_trailing_nodes(node_ptr this_node, node_ptr other_node) BOOST_NOEXCEPT
0234    {
0235       node_ptr this_nxt    = NodeTraits::get_next(this_node);
0236       node_ptr other_nxt   = NodeTraits::get_next(other_node);
0237       NodeTraits::set_next(this_node, other_nxt);
0238       NodeTraits::set_next(other_node, this_nxt);
0239    }
0240 
0241    //! <b>Effects</b>: Reverses the order of elements in the list.
0242    //!
0243    //! <b>Returns</b>: The new first node of the list.
0244    //!
0245    //! <b>Throws</b>: Nothing.
0246    //!
0247    //! <b>Complexity</b>: This function is linear to the contained elements.
0248    static node_ptr reverse(node_ptr p) BOOST_NOEXCEPT
0249    {
0250       if(!p) return node_ptr();
0251       node_ptr i = NodeTraits::get_next(p);
0252       node_ptr first(p);
0253       while(i){
0254          node_ptr nxti(NodeTraits::get_next(i));
0255          base_t::unlink_after(p);
0256          NodeTraits::set_next(i, first);
0257          first = i;
0258          i = nxti;
0259       }
0260       return first;
0261    }
0262 
0263    //! <b>Effects</b>: Moves the first n nodes starting at p to the end of the list.
0264    //!
0265    //! <b>Returns</b>: A pair containing the new first and last node of the list or
0266    //!   if there has been any movement, a null pair if n leads to no movement.
0267    //!
0268    //! <b>Throws</b>: Nothing.
0269    //!
0270    //! <b>Complexity</b>: Linear to the number of elements plus the number moved positions.
0271    static node_pair move_first_n_backwards(node_ptr p, std::size_t n) BOOST_NOEXCEPT
0272    {
0273       node_pair ret;
0274       //Null shift, or count() == 0 or 1, nothing to do
0275       if(!n || !p || !NodeTraits::get_next(p)){
0276          return ret;
0277       }
0278 
0279       node_ptr first = p;
0280       bool end_found = false;
0281       node_ptr new_last = node_ptr();
0282       node_ptr old_last = node_ptr();
0283 
0284       //Now find the new last node according to the shift count.
0285       //If we find 0 before finding the new last node
0286       //unlink p, shortcut the search now that we know the size of the list
0287       //and continue.
0288       for(std::size_t i = 1; i <= n; ++i){
0289          new_last = first;
0290          first = NodeTraits::get_next(first);
0291          if(first == node_ptr()){
0292             //Shortcut the shift with the modulo of the size of the list
0293             n %= i;
0294             if(!n)   return ret;
0295             old_last = new_last;
0296             i = 0;
0297             //Unlink p and continue the new first node search
0298             first = p;
0299             //unlink_after(new_last);
0300             end_found = true;
0301          }
0302       }
0303 
0304       //If the p has not been found in the previous loop, find it
0305       //starting in the new first node and unlink it
0306       if(!end_found){
0307          old_last = base_t::get_previous_node(first, node_ptr());
0308       }
0309 
0310       //Now link p after the new last node
0311       NodeTraits::set_next(old_last, p);
0312       NodeTraits::set_next(new_last, node_ptr());
0313       ret.first   = first;
0314       ret.second  = new_last;
0315       return ret;
0316    }
0317 
0318    //! <b>Effects</b>: Moves the first n nodes starting at p to the beginning of the list.
0319    //!
0320    //! <b>Returns</b>: A pair containing the new first and last node of the list or
0321    //!   if there has been any movement, a null pair if n leads to no movement.
0322    //!
0323    //! <b>Throws</b>: Nothing.
0324    //!
0325    //! <b>Complexity</b>: Linear to the number of elements plus the number moved positions.
0326    static node_pair move_first_n_forward(node_ptr p, std::size_t n) BOOST_NOEXCEPT
0327    {
0328       node_pair ret;
0329       //Null shift, or count() == 0 or 1, nothing to do
0330       if(!n || !p || !NodeTraits::get_next(p))
0331          return ret;
0332 
0333       node_ptr first  = p;
0334 
0335       //Iterate until p is found to know where the current last node is.
0336       //If the shift count is less than the size of the list, we can also obtain
0337       //the position of the new last node after the shift.
0338       node_ptr old_last(first), next_to_it, new_last(p);
0339       std::size_t distance = 1;
0340       while(!!(next_to_it = node_traits::get_next(old_last))){
0341          if(distance++ > n)
0342             new_last = node_traits::get_next(new_last);
0343          old_last = next_to_it;
0344       }
0345       //If the shift was bigger or equal than the size, obtain the equivalent
0346       //forward shifts and find the new last node.
0347       if(distance <= n){
0348          //Now find the equivalent forward shifts.
0349          //Shortcut the shift with the modulo of the size of the list
0350          std::size_t new_before_last_pos = (distance - (n % distance))% distance;
0351          //If the shift is a multiple of the size there is nothing to do
0352          if(!new_before_last_pos)
0353             return ret;
0354 
0355          for( new_last = p
0356             ; --new_before_last_pos
0357             ; new_last = node_traits::get_next(new_last)){
0358             //empty
0359          }
0360       }
0361 
0362       //Get the first new node
0363       node_ptr new_first(node_traits::get_next(new_last));
0364       //Now put the old beginning after the old end
0365       NodeTraits::set_next(old_last, p);
0366       NodeTraits::set_next(new_last, node_ptr());
0367       ret.first   = new_first;
0368       ret.second  = new_last;
0369       return ret;
0370    }
0371 
0372    //! <b>Requires</b>: other must be a list and p must be a node of a different linear list.
0373    //!
0374    //! <b>Effects</b>: Transfers all nodes from other after p in p's linear list.
0375    //!
0376    //! <b>Complexity</b>: Linear
0377    //!
0378    //! <b>Throws</b>: Nothing.
0379    static void transfer_after(node_ptr p, node_ptr other) BOOST_NOEXCEPT
0380    {
0381       if ((is_empty)(p)) {
0382          (swap_trailing_nodes)(p, other);
0383       }
0384       else {
0385          node_ptr other_last((get_previous_node)(other, node_ptr()));
0386          base_t::transfer_after(p, other, other_last);
0387       }
0388    }
0389 
0390    //! <b>Requires</b>: "disposer" must be an object function
0391    //!   taking a node_ptr parameter and shouldn't throw.
0392    //!
0393    //! <b>Effects</b>: Unlinks all nodes reachable from p (but not p) and calls
0394    //!   <tt>void disposer::operator()(node_ptr)</tt> for every node of the list
0395    //!    where p is linked.
0396    //!
0397    //! <b>Returns</b>: The number of disposed nodes
0398    //!
0399    //! <b>Complexity</b>: Linear to the number of element of the list.
0400    //!
0401    //! <b>Throws</b>: Nothing.
0402    template<class Disposer>
0403    BOOST_INTRUSIVE_FORCEINLINE static std::size_t detach_and_dispose(node_ptr p, Disposer disposer) BOOST_NOEXCEPT
0404    {  return base_t::unlink_after_and_dispose(p, node_ptr(), disposer);   }
0405 };
0406 
0407 /// @cond
0408 
0409 template<class NodeTraits>
0410 struct get_algo<LinearSListAlgorithms, NodeTraits>
0411 {
0412    typedef linear_slist_algorithms<NodeTraits> type;
0413 };
0414 
0415 /// @endcond
0416 
0417 } //namespace intrusive
0418 } //namespace boost
0419 
0420 #include <boost/intrusive/detail/config_end.hpp>
0421 
0422 #endif //BOOST_INTRUSIVE_LINEAR_SLIST_ALGORITHMS_HPP