[PATCH] D48504: [WIP] Add InsertionOrderSet, with constant-time insertion and removal.

Eli Friedman via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Fri Jun 22 12:42:26 PDT 2018


efriedma created this revision.

This is useful in places which need a consistent iteration order like a SetVector, but also need constant-time removal.

I just quickly hacked this together as a proof of concept for https://reviews.llvm.org/D48372; there's a lot of room for improvement.


Repository:
  rL LLVM

https://reviews.llvm.org/D48504

Files:
  include/llvm/ADT/InsertionOrderSet.h


Index: include/llvm/ADT/InsertionOrderSet.h
===================================================================
--- /dev/null
+++ include/llvm/ADT/InsertionOrderSet.h
@@ -0,0 +1,82 @@
+//===- InsertionOrderSet.h - Hash table--------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/Optional.h"
+#include <vector>
+
+namespace llvm {
+
+/// A hash table with constant-time insertion and removal, and iteration in
+/// insertion order. This is by contrast to a SetVector, which does not have
+/// constant-time removal (but has random-access iterators).
+///
+/// Issues with the current implementation:
+/// - It makes two copies of each item in the set.
+/// - It doesn't clean out dead entries in the vector when the set is rehashed.
+/// - InsertionOrderMap is missing.
+/// - The name could probably be improved.
+template <class ValueT>
+class InsertionOrderSet {
+  DenseMap<ValueT, size_t> Map;
+  typedef std::vector<Optional<ValueT>> VecType;
+  VecType Vec;
+
+  struct Filter {
+    bool operator()(const Optional<ValueT>& In) {
+      return In.hasValue();
+    }
+  };
+  typedef filter_iterator<typename VecType::iterator, Filter> FilteredIter;
+
+public:
+  typedef pointee_iterator<FilteredIter> iterator;
+
+private:
+  iterator MakeSetIterator(typename VecType::iterator I) {
+    return FilteredIter{I, Vec.end(), Filter{}};
+  }
+
+public:
+  std::pair<iterator, bool> insert(ValueT value) {
+    auto SetIns = Map.insert(std::make_pair(value, Vec.size()));
+    if (SetIns.second) {
+      Vec.push_back(value);
+      return { MakeSetIterator(Vec.end()-1), true };
+    }
+    return { MakeSetIterator(Vec.begin()+SetIns.first->second), false };
+  }
+
+  iterator begin() {
+    return MakeSetIterator(Vec.begin());
+  }
+  iterator end() {
+    return MakeSetIterator(Vec.end());
+  }
+
+  void clear() {
+    Vec.clear();
+    Map.clear();
+  }
+
+  size_t size() const {
+    return Vec.size();
+  }
+
+  void remove(ValueT value) {
+    auto MapFind = Map.find(value);
+    if (MapFind != Map.end()) {
+      size_t Index = MapFind->second;
+      Map.erase(MapFind);
+      Vec[Index] = None;
+    }
+  }
+};
+}


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D48504.152534.patch
Type: text/x-patch
Size: 2446 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20180622/5177493b/attachment.bin>


More information about the llvm-commits mailing list