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 + +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 InsertionOrderSet { + DenseMap Map; + typedef std::vector> VecType; + VecType Vec; + + struct Filter { + bool operator()(const Optional& In) { + return In.hasValue(); + } + }; + typedef filter_iterator FilteredIter; + +public: + typedef pointee_iterator iterator; + +private: + iterator MakeSetIterator(typename VecType::iterator I) { + return FilteredIter{I, Vec.end(), Filter{}}; + } + +public: + std::pair 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; + } + } +}; +}