Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:43:05

0001 //==-- llvm/ADT/ilist.h - Intrusive Linked List Template ---------*- C++ -*-==//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 ///
0009 /// \file
0010 /// This file defines classes to implement an intrusive doubly linked list class
0011 /// (i.e. each node of the list must contain a next and previous field for the
0012 /// list.
0013 ///
0014 /// The ilist class itself should be a plug in replacement for list.  This list
0015 /// replacement does not provide a constant time size() method, so be careful to
0016 /// use empty() when you really want to know if it's empty.
0017 ///
0018 /// The ilist class is implemented as a circular list.  The list itself contains
0019 /// a sentinel node, whose Next points at begin() and whose Prev points at
0020 /// rbegin().  The sentinel node itself serves as end() and rend().
0021 ///
0022 //===----------------------------------------------------------------------===//
0023 
0024 #ifndef LLVM_ADT_ILIST_H
0025 #define LLVM_ADT_ILIST_H
0026 
0027 #include "llvm/ADT/simple_ilist.h"
0028 #include <cassert>
0029 #include <cstddef>
0030 #include <iterator>
0031 
0032 namespace llvm {
0033 
0034 /// Use delete by default for iplist and ilist.
0035 ///
0036 /// Specialize this to get different behaviour for ownership-related API.  (If
0037 /// you really want ownership semantics, consider using std::list or building
0038 /// something like \a BumpPtrList.)
0039 ///
0040 /// \see ilist_noalloc_traits
0041 template <typename NodeTy> struct ilist_alloc_traits {
0042   static void deleteNode(NodeTy *V) { delete V; }
0043 };
0044 
0045 /// Custom traits to do nothing on deletion.
0046 ///
0047 /// Specialize ilist_alloc_traits to inherit from this to disable the
0048 /// non-intrusive deletion in iplist (which implies ownership).
0049 ///
0050 /// If you want purely intrusive semantics with no callbacks, consider using \a
0051 /// simple_ilist instead.
0052 ///
0053 /// \code
0054 /// template <>
0055 /// struct ilist_alloc_traits<MyType> : ilist_noalloc_traits<MyType> {};
0056 /// \endcode
0057 template <typename NodeTy> struct ilist_noalloc_traits {
0058   static void deleteNode(NodeTy *V) {}
0059 };
0060 
0061 /// Callbacks do nothing by default in iplist and ilist.
0062 ///
0063 /// Specialize this for to use callbacks for when nodes change their list
0064 /// membership.
0065 template <typename NodeTy> struct ilist_callback_traits {
0066   void addNodeToList(NodeTy *) {}
0067   void removeNodeFromList(NodeTy *) {}
0068 
0069   /// Callback before transferring nodes to this list. The nodes may already be
0070   /// in this same list.
0071   template <class Iterator>
0072   void transferNodesFromList(ilist_callback_traits &OldList, Iterator /*first*/,
0073                              Iterator /*last*/) {
0074     (void)OldList;
0075   }
0076 };
0077 
0078 /// A fragment for template traits for intrusive list that provides default
0079 /// node related operations.
0080 ///
0081 /// TODO: Remove this layer of indirection.  It's not necessary.
0082 template <typename NodeTy>
0083 struct ilist_node_traits : ilist_alloc_traits<NodeTy>,
0084                            ilist_callback_traits<NodeTy> {};
0085 
0086 /// Template traits for intrusive list.
0087 ///
0088 /// Customize callbacks and allocation semantics.
0089 template <typename NodeTy>
0090 struct ilist_traits : public ilist_node_traits<NodeTy> {};
0091 
0092 /// Const traits should never be instantiated.
0093 template <typename Ty> struct ilist_traits<const Ty> {};
0094 
0095 //===----------------------------------------------------------------------===//
0096 //
0097 /// A wrapper around an intrusive list with callbacks and non-intrusive
0098 /// ownership.
0099 ///
0100 /// This wraps a purely intrusive list (like simple_ilist) with a configurable
0101 /// traits class.  The traits can implement callbacks and customize the
0102 /// ownership semantics.
0103 ///
0104 /// This is a subset of ilist functionality that can safely be used on nodes of
0105 /// polymorphic types, i.e. a heterogeneous list with a common base class that
0106 /// holds the next/prev pointers.  The only state of the list itself is an
0107 /// ilist_sentinel, which holds pointers to the first and last nodes in the
0108 /// list.
0109 template <class IntrusiveListT, class TraitsT>
0110 class iplist_impl : public TraitsT, IntrusiveListT {
0111   typedef IntrusiveListT base_list_type;
0112 
0113 public:
0114   typedef typename base_list_type::pointer pointer;
0115   typedef typename base_list_type::const_pointer const_pointer;
0116   typedef typename base_list_type::reference reference;
0117   typedef typename base_list_type::const_reference const_reference;
0118   typedef typename base_list_type::value_type value_type;
0119   typedef typename base_list_type::size_type size_type;
0120   typedef typename base_list_type::difference_type difference_type;
0121   typedef typename base_list_type::iterator iterator;
0122   typedef typename base_list_type::const_iterator const_iterator;
0123   typedef typename base_list_type::reverse_iterator reverse_iterator;
0124   typedef
0125       typename base_list_type::const_reverse_iterator const_reverse_iterator;
0126 
0127 private:
0128   static bool op_less(const_reference L, const_reference R) { return L < R; }
0129   static bool op_equal(const_reference L, const_reference R) { return L == R; }
0130 
0131 public:
0132   iplist_impl() = default;
0133 
0134   iplist_impl(const iplist_impl &) = delete;
0135   iplist_impl &operator=(const iplist_impl &) = delete;
0136 
0137   iplist_impl(iplist_impl &&X)
0138       : TraitsT(std::move(static_cast<TraitsT &>(X))),
0139         IntrusiveListT(std::move(static_cast<IntrusiveListT &>(X))) {}
0140   iplist_impl &operator=(iplist_impl &&X) {
0141     *static_cast<TraitsT *>(this) = std::move(static_cast<TraitsT &>(X));
0142     *static_cast<IntrusiveListT *>(this) =
0143         std::move(static_cast<IntrusiveListT &>(X));
0144     return *this;
0145   }
0146 
0147   ~iplist_impl() { clear(); }
0148 
0149   // Miscellaneous inspection routines.
0150   size_type max_size() const { return size_type(-1); }
0151 
0152   using base_list_type::begin;
0153   using base_list_type::end;
0154   using base_list_type::rbegin;
0155   using base_list_type::rend;
0156   using base_list_type::empty;
0157   using base_list_type::front;
0158   using base_list_type::back;
0159 
0160   void swap(iplist_impl &RHS) {
0161     assert(0 && "Swap does not use list traits callback correctly yet!");
0162     base_list_type::swap(RHS);
0163   }
0164 
0165   iterator insert(iterator where, pointer New) {
0166     this->addNodeToList(New); // Notify traits that we added a node...
0167     return base_list_type::insert(where, *New);
0168   }
0169 
0170   iterator insert(iterator where, const_reference New) {
0171     return this->insert(where, new value_type(New));
0172   }
0173 
0174   iterator insertAfter(iterator where, pointer New) {
0175     if (empty())
0176       return insert(begin(), New);
0177     else
0178       return insert(++where, New);
0179   }
0180 
0181   /// Clone another list.
0182   template <class Cloner> void cloneFrom(const iplist_impl &L2, Cloner clone) {
0183     clear();
0184     for (const_reference V : L2)
0185       push_back(clone(V));
0186   }
0187 
0188   pointer remove(iterator &IT) {
0189     pointer Node = &*IT++;
0190     this->removeNodeFromList(Node); // Notify traits that we removed a node...
0191     base_list_type::remove(*Node);
0192     return Node;
0193   }
0194 
0195   pointer remove(const iterator &IT) {
0196     iterator MutIt = IT;
0197     return remove(MutIt);
0198   }
0199 
0200   pointer remove(pointer IT) { return remove(iterator(IT)); }
0201   pointer remove(reference IT) { return remove(iterator(IT)); }
0202 
0203   // erase - remove a node from the controlled sequence... and delete it.
0204   iterator erase(iterator where) {
0205     this->deleteNode(remove(where));
0206     return where;
0207   }
0208 
0209   iterator erase(pointer IT) { return erase(iterator(IT)); }
0210   iterator erase(reference IT) { return erase(iterator(IT)); }
0211 
0212   /// Remove all nodes from the list like clear(), but do not call
0213   /// removeNodeFromList() or deleteNode().
0214   ///
0215   /// This should only be used immediately before freeing nodes in bulk to
0216   /// avoid traversing the list and bringing all the nodes into cache.
0217   void clearAndLeakNodesUnsafely() { base_list_type::clear(); }
0218 
0219 private:
0220   // transfer - The heart of the splice function.  Move linked list nodes from
0221   // [first, last) into position.
0222   //
0223   void transfer(iterator position, iplist_impl &L2, iterator first, iterator last) {
0224     if (position == last)
0225       return;
0226 
0227     // Notify traits we moved the nodes...
0228     this->transferNodesFromList(L2, first, last);
0229 
0230     base_list_type::splice(position, L2, first, last);
0231   }
0232 
0233 public:
0234   //===----------------------------------------------------------------------===
0235   // Functionality derived from other functions defined above...
0236   //
0237 
0238   using base_list_type::size;
0239 
0240   iterator erase(iterator first, iterator last) {
0241     while (first != last)
0242       first = erase(first);
0243     return last;
0244   }
0245 
0246   void clear() { erase(begin(), end()); }
0247 
0248   // Front and back inserters...
0249   void push_front(pointer val) { insert(begin(), val); }
0250   void push_back(pointer val) { insert(end(), val); }
0251   void pop_front() {
0252     assert(!empty() && "pop_front() on empty list!");
0253     erase(begin());
0254   }
0255   void pop_back() {
0256     assert(!empty() && "pop_back() on empty list!");
0257     iterator t = end(); erase(--t);
0258   }
0259 
0260   // Special forms of insert...
0261   template<class InIt> void insert(iterator where, InIt first, InIt last) {
0262     for (; first != last; ++first) insert(where, *first);
0263   }
0264 
0265   // Splice members - defined in terms of transfer...
0266   void splice(iterator where, iplist_impl &L2) {
0267     if (!L2.empty())
0268       transfer(where, L2, L2.begin(), L2.end());
0269   }
0270   void splice(iterator where, iplist_impl &L2, iterator first) {
0271     iterator last = first; ++last;
0272     if (where == first || where == last) return; // No change
0273     transfer(where, L2, first, last);
0274   }
0275   void splice(iterator where, iplist_impl &L2, iterator first, iterator last) {
0276     if (first != last) transfer(where, L2, first, last);
0277   }
0278   void splice(iterator where, iplist_impl &L2, reference N) {
0279     splice(where, L2, iterator(N));
0280   }
0281   void splice(iterator where, iplist_impl &L2, pointer N) {
0282     splice(where, L2, iterator(N));
0283   }
0284 
0285   template <class Compare>
0286   void merge(iplist_impl &Right, Compare comp) {
0287     if (this == &Right)
0288       return;
0289     this->transferNodesFromList(Right, Right.begin(), Right.end());
0290     base_list_type::merge(Right, comp);
0291   }
0292   void merge(iplist_impl &Right) { return merge(Right, op_less); }
0293 
0294   using base_list_type::sort;
0295 
0296   /// Get the previous node, or \c nullptr for the list head.
0297   pointer getPrevNode(reference N) const {
0298     auto I = N.getIterator();
0299     if (I == begin())
0300       return nullptr;
0301     return &*std::prev(I);
0302   }
0303   /// Get the previous node, or \c nullptr for the list head.
0304   const_pointer getPrevNode(const_reference N) const {
0305     return getPrevNode(const_cast<reference >(N));
0306   }
0307 
0308   /// Get the next node, or \c nullptr for the list tail.
0309   pointer getNextNode(reference N) const {
0310     auto Next = std::next(N.getIterator());
0311     if (Next == end())
0312       return nullptr;
0313     return &*Next;
0314   }
0315   /// Get the next node, or \c nullptr for the list tail.
0316   const_pointer getNextNode(const_reference N) const {
0317     return getNextNode(const_cast<reference >(N));
0318   }
0319 };
0320 
0321 /// An intrusive list with ownership and callbacks specified/controlled by
0322 /// ilist_traits, only with API safe for polymorphic types.
0323 ///
0324 /// The \p Options parameters are the same as those for \a simple_ilist.  See
0325 /// there for a description of what's available.
0326 template <class T, class... Options>
0327 class iplist
0328     : public iplist_impl<simple_ilist<T, Options...>, ilist_traits<T>> {
0329   using iplist_impl_type = typename iplist::iplist_impl;
0330 
0331 public:
0332   iplist() = default;
0333 
0334   iplist(const iplist &X) = delete;
0335   iplist &operator=(const iplist &X) = delete;
0336 
0337   iplist(iplist &&X) : iplist_impl_type(std::move(X)) {}
0338   iplist &operator=(iplist &&X) {
0339     *static_cast<iplist_impl_type *>(this) = std::move(X);
0340     return *this;
0341   }
0342 };
0343 
0344 template <class T, class... Options> using ilist = iplist<T, Options...>;
0345 
0346 } // end namespace llvm
0347 
0348 namespace std {
0349 
0350   // Ensure that swap uses the fast list swap...
0351   template<class Ty>
0352   void swap(llvm::iplist<Ty> &Left, llvm::iplist<Ty> &Right) {
0353     Left.swap(Right);
0354   }
0355 
0356 } // end namespace std
0357 
0358 #endif // LLVM_ADT_ILIST_H