Add an iplist::clearAndLeakNodesUnsafely() function.
authorJakob Stoklund Olesen <stoklund@2pi.dk>
Fri, 4 Jan 2013 22:35:42 +0000 (22:35 +0000)
committerJakob Stoklund Olesen <stoklund@2pi.dk>
Fri, 4 Jan 2013 22:35:42 +0000 (22:35 +0000)
The iplist::clear() function can be quite expensive because it traverses
the entire list, calling deleteNode() and removeNodeFromList() on each
element. If node destruction and deallocation can be handled some other
way, clearAndLeakNodesUnsafely() can be used to jettison all nodes
without bringing them into cache.

The function name is meant to be ominous.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@171540 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/ADT/ilist.h
unittests/ADT/ilistTest.cpp

index 36650d43750ceff917078028cee627db6fe9681a..20cdae32554a7eed6854cc756e7f5928bf5b3f96 100644 (file)
@@ -465,6 +465,17 @@ public:
     return where;
   }
 
+  /// Remove all nodes from the list like clear(), but do not call
+  /// removeNodeFromList() or deleteNode().
+  ///
+  /// This should only be used immediately before freeing nodes in bulk to
+  /// avoid traversing the list and bringing all the nodes into cache.
+  void clearAndLeakNodesUnsafely() {
+    if (Head) {
+      Head = getTail();
+      this->setPrev(Head, Head);
+    }
+  }
 
 private:
   // transfer - The heart of the splice function.  Move linked list nodes from
index 07bd5ec601994dd23faff1bf93548415a894e3d1..0c0cd0fd56fe3cca2bf3f9fe88310227f683a717 100644 (file)
@@ -22,6 +22,7 @@ struct Node : ilist_node<Node> {
 
   Node() {}
   Node(int _Value) : Value(_Value) {}
+  ~Node() { Value = -1; }
 };
 
 TEST(ilistTest, Basic) {
@@ -62,4 +63,36 @@ TEST(ilistTest, SpliceOne) {
   EXPECT_EQ(3, List.back().Value);
 }
 
+TEST(ilistTest, UnsafeClear) {
+  ilist<Node> List;
+
+  // Before even allocating a sentinel.
+  List.clearAndLeakNodesUnsafely();
+  EXPECT_EQ(0u, List.size());
+
+  // Empty list with sentinel.
+  ilist<Node>::iterator E = List.end();
+  List.clearAndLeakNodesUnsafely();
+  EXPECT_EQ(0u, List.size());
+  // The sentinel shouldn't change.
+  EXPECT_TRUE(E == List.end());
+
+  // List with contents.
+  List.push_back(1);
+  ASSERT_EQ(1u, List.size());
+  Node *N = List.begin();
+  EXPECT_EQ(1, N->Value);
+  List.clearAndLeakNodesUnsafely();
+  EXPECT_EQ(0u, List.size());
+  ASSERT_EQ(1, N->Value);
+  delete N;
+
+  // List is still functional.
+  List.push_back(5);
+  List.push_back(6);
+  ASSERT_EQ(2u, List.size());
+  EXPECT_EQ(5, List.front().Value);
+  EXPECT_EQ(6, List.back().Value);
+}
+
 }