Skip to content

Commit

Permalink
ADT: Explode include/llvm/ADT/{ilist,ilist_node}.h, NFC
Browse files Browse the repository at this point in the history
I'm working on a lower-level intrusive list that can be used
stand-alone, and splitting the files up a bit will make the code easier
to organize.  Explode the ilist headers in advance to improve blame
lists in the future.
- Move ilist_node_base from ilist_node.h to ilist_node_base.h.
- Move ilist_base from ilist.h to ilist_base.h.
- Move ilist_iterator from ilist.h to ilist_iterator.h.
- Move ilist_node_access from ilist.h to ilist_node.h to support
  ilist_iterator.
- Update unit tests to #include smaller headers.
- Clang-format the moved things.

I noticed in transit that there is a simplify_type specialization for
ilist_iterator.  Since there is no longer an implicit conversion from
ilist<T>::iterator to T*, this doesn't make sense (effectively it's a
form of implicit conversion).  For now I've added a FIXME.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@280047 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
dexonsmith committed Aug 30, 2016
1 parent ff612bc commit e86c615
Show file tree
Hide file tree
Showing 7 changed files with 330 additions and 269 deletions.
240 changes: 2 additions & 238 deletions include/llvm/ADT/ilist.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
#ifndef LLVM_ADT_ILIST_H
#define LLVM_ADT_ILIST_H

#include "llvm/ADT/ilist_base.h"
#include "llvm/ADT/ilist_iterator.h"
#include "llvm/ADT/ilist_node.h"
#include "llvm/Support/Compiler.h"
#include <algorithm>
Expand All @@ -35,36 +37,6 @@
namespace llvm {

template<typename NodeTy, typename Traits> class iplist;
template <typename NodeTy, bool IsReverse> class ilist_iterator;

/// 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.
///
/// It's strongly discouraged to *use* this class outside of the ilist
/// implementation.
struct ilist_node_access {
template <typename T> static ilist_node<T> *getNodePtr(T *N) { return N; }
template <typename T> static const ilist_node<T> *getNodePtr(const T *N) {
return N;
}

template <typename T> static ilist_node<T> *getPrev(ilist_node<T> &N) {
return N.getPrev();
}
template <typename T> static ilist_node<T> *getNext(ilist_node<T> &N) {
return N.getNext();
}
template <typename T>
static const ilist_node<T> *getPrev(const ilist_node<T> &N) {
return N.getPrev();
}
template <typename T>
static const ilist_node<T> *getNext(const ilist_node<T> &N) {
return N.getNext();
}
};

namespace ilist_detail {

Expand Down Expand Up @@ -139,214 +111,6 @@ struct ilist_traits : public ilist_default_traits<NodeTy> {};
template<typename Ty>
struct ilist_traits<const Ty> : public ilist_traits<Ty> {};

namespace ilist_detail {
template <class NodeTy> struct ConstCorrectNodeType {
typedef ilist_node<NodeTy> type;
};
template <class NodeTy> struct ConstCorrectNodeType<const NodeTy> {
typedef const ilist_node<NodeTy> type;
};

template <bool IsReverse = false> struct IteratorHelper {
template <class T> static void increment(T *&I) {
I = ilist_node_access::getNext(*I);
}
template <class T> static void decrement(T *&I) {
I = ilist_node_access::getPrev(*I);
}
};
template <> struct IteratorHelper<true> {
template <class T> static void increment(T *&I) {
IteratorHelper<false>::decrement(I);
}
template <class T> static void decrement(T *&I) {
IteratorHelper<false>::increment(I);
}
};

} // end namespace ilist_detail

//===----------------------------------------------------------------------===//
// Iterator for intrusive list.
//
template <typename NodeTy, bool IsReverse>
class ilist_iterator
: public std::iterator<std::bidirectional_iterator_tag, NodeTy, ptrdiff_t> {
public:
typedef std::iterator<std::bidirectional_iterator_tag, NodeTy, ptrdiff_t>
super;

typedef typename super::value_type value_type;
typedef typename super::difference_type difference_type;
typedef typename super::pointer pointer;
typedef typename super::reference reference;

typedef typename std::add_const<value_type>::type *const_pointer;
typedef typename std::add_const<value_type>::type &const_reference;

typedef typename ilist_detail::ConstCorrectNodeType<NodeTy>::type node_type;
typedef node_type *node_pointer;
typedef node_type &node_reference;

private:
node_pointer NodePtr;

public:
/// Create from an ilist_node.
explicit ilist_iterator(node_reference N) : NodePtr(&N) {}

explicit ilist_iterator(pointer NP) : NodePtr(NP) {}
explicit ilist_iterator(reference NR) : NodePtr(&NR) {}
ilist_iterator() : NodePtr(nullptr) {}

// This is templated so that we can allow constructing a const iterator from
// a nonconst iterator...
template <class node_ty>
ilist_iterator(
const ilist_iterator<node_ty, IsReverse> &RHS,
typename std::enable_if<std::is_convertible<node_ty *, NodeTy *>::value,
void *>::type = nullptr)
: NodePtr(RHS.getNodePtr()) {}

// This is templated so that we can allow assigning to a const iterator from
// a nonconst iterator...
template <class node_ty>
const ilist_iterator &
operator=(const ilist_iterator<node_ty, IsReverse> &RHS) {
NodePtr = RHS.getNodePtr();
return *this;
}

/// Convert from an iterator to its reverse.
///
/// TODO: Roll this into the implicit constructor once we're sure that no one
/// is relying on the std::reverse_iterator off-by-one semantics.
ilist_iterator<NodeTy, !IsReverse> getReverse() const {
if (NodePtr)
return ilist_iterator<NodeTy, !IsReverse>(*NodePtr);
return ilist_iterator<NodeTy, !IsReverse>();
}

void reset(pointer NP) { NodePtr = NP; }

// Accessors...
reference operator*() const {
assert(!NodePtr->isKnownSentinel());
return static_cast<NodeTy &>(*getNodePtr());
}
pointer operator->() const { return &operator*(); }

// Comparison operators
friend bool operator==(const ilist_iterator &LHS, const ilist_iterator &RHS) {
return LHS.NodePtr == RHS.NodePtr;
}
friend bool operator!=(const ilist_iterator &LHS, const ilist_iterator &RHS) {
return LHS.NodePtr != RHS.NodePtr;
}

// Increment and decrement operators...
ilist_iterator &operator--() {
ilist_detail::IteratorHelper<IsReverse>::decrement(NodePtr);
return *this;
}
ilist_iterator &operator++() {
ilist_detail::IteratorHelper<IsReverse>::increment(NodePtr);
return *this;
}
ilist_iterator operator--(int) {
ilist_iterator tmp = *this;
--*this;
return tmp;
}
ilist_iterator operator++(int) {
ilist_iterator tmp = *this;
++*this;
return tmp;
}

/// Get the underlying ilist_node.
node_pointer getNodePtr() const { return static_cast<node_pointer>(NodePtr); }
};

// Allow ilist_iterators to convert into pointers to a node automatically when
// used by the dyn_cast, cast, isa mechanisms...

template<typename From> struct simplify_type;

template<typename NodeTy> struct simplify_type<ilist_iterator<NodeTy> > {
typedef NodeTy* SimpleType;

static SimpleType getSimplifiedValue(ilist_iterator<NodeTy> &Node) {
return &*Node;
}
};
template<typename NodeTy> struct simplify_type<const ilist_iterator<NodeTy> > {
typedef /*const*/ NodeTy* SimpleType;

static SimpleType getSimplifiedValue(const ilist_iterator<NodeTy> &Node) {
return &*Node;
}
};

/// Implementations of list algorithms using ilist_node_base.
class ilist_base {
public:
static void insertBeforeImpl(ilist_node_base &Next, ilist_node_base &N) {
ilist_node_base &Prev = *Next.getPrev();
N.setNext(&Next);
N.setPrev(&Prev);
Prev.setNext(&N);
Next.setPrev(&N);
}

static void removeImpl(ilist_node_base &N) {
ilist_node_base *Prev = N.getPrev();
ilist_node_base *Next = N.getNext();
Next->setPrev(Prev);
Prev->setNext(Next);

// Not strictly necessary, but helps catch a class of bugs.
N.setPrev(nullptr);
N.setNext(nullptr);
}

static void transferBeforeImpl(ilist_node_base &Next, ilist_node_base &First,
ilist_node_base &Last) {
assert(&Next != &Last && "Should be checked by callers");
assert(&First != &Last && "Should be checked by callers");
// Position cannot be contained in the range to be transferred.
assert(&Next != &First &&
// Check for the most common mistake.
"Insertion point can't be one of the transferred nodes");

ilist_node_base &Final = *Last.getPrev();

// Detach from old list/position.
First.getPrev()->setNext(&Last);
Last.setPrev(First.getPrev());

// Splice [First, Final] into its new list/position.
ilist_node_base &Prev = *Next.getPrev();
Final.setNext(&Next);
First.setPrev(&Prev);
Prev.setNext(&First);
Next.setPrev(&Final);
}

template <class T>
static void insertBefore(ilist_node<T> &Next, ilist_node<T> &N) {
insertBeforeImpl(Next, N);
}

template <class T> static void remove(ilist_node<T> &N) { removeImpl(N); }

template <class T>
static void transferBefore(ilist_node<T> &Next, ilist_node<T> &First,
ilist_node<T> &Last) {
transferBeforeImpl(Next, First, Last);
}
};

//===----------------------------------------------------------------------===//
//
/// The subset of list functionality that can safely be used on nodes of
Expand Down
78 changes: 78 additions & 0 deletions include/llvm/ADT/ilist_base.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
//===- llvm/ADT/ilist_base.h - Intrusive List Base ---------------*- C++ -*-==//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_ADT_ILIST_BASE_H
#define LLVM_ADT_ILIST_BASE_H

#include "llvm/ADT/ilist_node_base.h"
#include <cassert>
#include <cstddef>
#include <type_traits>

namespace llvm {

/// Implementations of list algorithms using ilist_node_base.
class ilist_base {
public:
static void insertBeforeImpl(ilist_node_base &Next, ilist_node_base &N) {
ilist_node_base &Prev = *Next.getPrev();
N.setNext(&Next);
N.setPrev(&Prev);
Prev.setNext(&N);
Next.setPrev(&N);
}

static void removeImpl(ilist_node_base &N) {
ilist_node_base *Prev = N.getPrev();
ilist_node_base *Next = N.getNext();
Next->setPrev(Prev);
Prev->setNext(Next);

// Not strictly necessary, but helps catch a class of bugs.
N.setPrev(nullptr);
N.setNext(nullptr);
}

static void transferBeforeImpl(ilist_node_base &Next, ilist_node_base &First,
ilist_node_base &Last) {
assert(&Next != &Last && "Should be checked by callers");
assert(&First != &Last && "Should be checked by callers");
// Position cannot be contained in the range to be transferred.
assert(&Next != &First &&
// Check for the most common mistake.
"Insertion point can't be one of the transferred nodes");

ilist_node_base &Final = *Last.getPrev();

// Detach from old list/position.
First.getPrev()->setNext(&Last);
Last.setPrev(First.getPrev());

// Splice [First, Final] into its new list/position.
ilist_node_base &Prev = *Next.getPrev();
Final.setNext(&Next);
First.setPrev(&Prev);
Prev.setNext(&First);
Next.setPrev(&Final);
}

template <class T> static void insertBefore(T &Next, T &N) {
insertBeforeImpl(Next, N);
}

template <class T> static void remove(T &N) { removeImpl(N); }

template <class T> static void transferBefore(T &Next, T &First, T &Last) {
transferBeforeImpl(Next, First, Last);
}
};

} // end namespace llvm

#endif // LLVM_ADT_ILIST_BASE_H
Loading

0 comments on commit e86c615

Please sign in to comment.