[compiler-rt] [scudo] Support linking with index in IntrusiveList (PR #101262)

via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 8 16:32:12 PDT 2024


================
@@ -11,17 +11,103 @@
 
 #include "internal_defs.h"
 
+// TODO: Move the helpers to a header.
+namespace {
+template <typename T> struct isPointer {
+  static constexpr bool value = false;
+};
+
+template <typename T> struct isPointer<T *> {
+  static constexpr bool value = true;
+};
+} // namespace
+
 namespace scudo {
 
 // Intrusive POD singly and doubly linked list.
 // An object with all zero fields should represent a valid empty list. clear()
 // should be called on all non-zero-initialized objects before using.
+//
+// The intrusive list requires the member `Next` (and `Prev` if doubly linked
+// list)` defined in the node type. The type of `Next`/`Prev` can be a pointer
+// or an index to an array. For example, if the storage of the nodes is an
+// array, instead of using pointer type, linking with index type can save some
+// space.
+//
+// There are two things to be noticed while using index type,
+//   1. Call init() to set up the base address of the array.
+//   2. Define `EndOfListVal` as the nil of the list.
+
+template <class T, bool LinkWithPtr = isPointer<decltype(T::Next)>::value>
+class LinkOp {
+public:
+  LinkOp() = default;
+  LinkOp(UNUSED T *BaseT) {}
+  void init(UNUSED T *LinkBase) {}
+  T *getBase() const { return nullptr; }
 
-template <class T> class IteratorBase {
+  T *getNext(T *X) const { return X->Next; }
+  void setNext(T *X, T *Next) const { X->Next = Next; }
+
+  T *getPrev(T *X) const { return X->Prev; }
+  void setPrev(T *X, T *Prev) const { X->Prev = Prev; }
+
+  T *getEndOfListVal() const { return nullptr; }
+};
+
+template <class T> class LinkOp<T, /*LinkWithPtr=*/false> {
 public:
-  explicit IteratorBase(T *CurrentT) : Current(CurrentT) {}
+  using LinkTy = decltype(T::Next);
+
+  LinkOp() = default;
+  LinkOp(T *BaseT) : Base(BaseT) {}
+  void init(T *LinkBase) { Base = LinkBase; }
+  T *getBase() const { return Base; }
+
+  T *getNext(T *X) const {
+    DCHECK_NE(getBase(), nullptr);
+    if (X->Next == getEndOfListVal())
----------------
ChiaHungDuan wrote:

good idea. Done.

https://github.com/llvm/llvm-project/pull/101262


More information about the llvm-commits mailing list