//===- llvm/ADT/ilist_node.h - Intrusive Linked List Helper -----*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// /// /// \file /// This file defines the ilist_node class template, which is a convenient /// base class for creating classes that can be used with ilists. /// //===----------------------------------------------------------------------===// #ifndef LLVM_ADT_ILIST_NODE_H #define LLVM_ADT_ILIST_NODE_H #include "llvm/ADT/ilist_node_base.h" #include "llvm/ADT/ilist_node_options.h" namespace llvm { namespace ilist_detail { struct NodeAccess; /// Mixin base class that is used to add \a getParent() and /// \a setParent(ParentTy*) methods to \a ilist_node_impl iff \a ilist_parent /// has been set in the list options. template <class NodeTy, class ParentTy> class node_parent_access { … }; node_parent_access<NodeTy, void>; } // end namespace ilist_detail template <class OptionsT, bool IsReverse, bool IsConst> class ilist_iterator; template <class OptionsT, bool IsReverse, bool IsConst> class ilist_iterator_w_bits; template <class OptionsT> class ilist_sentinel; // Selector for which iterator type to pick given the iterator-bits node option. template <bool use_iterator_bits, typename Opts, bool arg1, bool arg2> class ilist_select_iterator_type { … }; ilist_select_iterator_type<true, Opts, arg1, arg2>; /// Implementation for an ilist node. /// /// Templated on an appropriate \a ilist_detail::node_options, usually computed /// by \a ilist_detail::compute_node_options. /// /// This is a wrapper around \a ilist_node_base whose main purpose is to /// provide type safety: you can't insert nodes of \a ilist_node_impl into the /// wrong \a simple_ilist or \a iplist. template <class OptionsT> class ilist_node_impl : OptionsT::node_base_type, public ilist_detail::node_parent_access<ilist_node_impl<OptionsT>, typename OptionsT::parent_ty> { … }; /// An intrusive list node. /// /// A base class to enable membership in intrusive lists, including \a /// simple_ilist, \a iplist, and \a ilist. The first template parameter is the /// \a value_type for the list. /// /// An ilist node can be configured with compile-time options to change /// behaviour and/or add API. /// /// By default, an \a ilist_node knows whether it is the list sentinel (an /// instance of \a ilist_sentinel) if and only if /// LLVM_ENABLE_ABI_BREAKING_CHECKS. The function \a isKnownSentinel() always /// returns \c false tracking is off. Sentinel tracking steals a bit from the /// "prev" link, which adds a mask operation when decrementing an iterator, but /// enables bug-finding assertions in \a ilist_iterator. /// /// To turn sentinel tracking on all the time, pass in the /// ilist_sentinel_tracking<true> template parameter. This also enables the \a /// isSentinel() function. The same option must be passed to the intrusive /// list. (ilist_sentinel_tracking<false> turns sentinel tracking off all the /// time.) /// /// A type can inherit from ilist_node multiple times by passing in different /// \a ilist_tag options. This allows a single instance to be inserted into /// multiple lists simultaneously, where each list is given the same tag. /// /// \example /// struct A {}; /// struct B {}; /// struct N : ilist_node<N, ilist_tag<A>>, ilist_node<N, ilist_tag<B>> {}; /// /// void foo() { /// simple_ilist<N, ilist_tag<A>> ListA; /// simple_ilist<N, ilist_tag<B>> ListB; /// N N1; /// ListA.push_back(N1); /// ListB.push_back(N1); /// } /// \endexample /// /// When the \a ilist_parent<ParentTy> option is passed to an ilist_node and the /// owning ilist, each node contains a pointer to the ilist's owner. This adds /// \a getParent() and \a setParent(ParentTy*) methods to the ilist_node, which /// will be used for node access by the ilist if the node class publicly /// inherits from \a ilist_node_with_parent. By default, setParent() is not /// automatically called by the ilist; a SymbolTableList will call setParent() /// on inserted nodes, but the sentinel must still be manually set after the /// list is created (e.g. SymTabList.end()->setParent(Parent)). /// /// The primary benefit of using ilist_parent is that a parent /// pointer will be stored in the sentinel, meaning that you can safely use \a /// ilist_iterator::getNodeParent() to get the node parent from any valid (i.e. /// non-null) iterator, even one that points to a sentinel value. /// /// See \a is_valid_option for steps on adding a new option. template <class T, class... Options> class ilist_node : public ilist_node_impl< typename ilist_detail::compute_node_options<T, Options...>::type> { … }; namespace ilist_detail { /// An access class for ilist_node private API. /// /// This gives access to the private parts of ilist nodes. Nodes for an ilist /// should friend this class if they inherit privately from ilist_node. /// /// Using this class outside of the ilist implementation is unsupported. struct NodeAccess { … }; template <class OptionsT> struct SpecificNodeAccess : NodeAccess { … }; } // end namespace ilist_detail template <class OptionsT> class ilist_sentinel : public ilist_node_impl<OptionsT> { … }; /// An ilist node that can access its parent list. /// /// Requires \c NodeTy to have \a getParent() to find the parent node, and the /// \c ParentTy to have \a getSublistAccess() to get a reference to the list. template <typename NodeTy, typename ParentTy, class... Options> class ilist_node_with_parent : public ilist_node<NodeTy, Options...> { … }; } // end namespace llvm #endif // LLVM_ADT_ILIST_NODE_H