From df8fbfc774ec06f4d2f8fd3e1b917d45cdac8fde Mon Sep 17 00:00:00 2001 From: Chandler Carruth Date: Sun, 16 Aug 2015 23:17:27 +0000 Subject: [PATCH] [ADT] Teach FoldingSet to be movable. This is a very minimal move support - it leaves the moved-from object in a zombie state that is only valid for destruction and move assignment. This seems fine to me, and leaving it in the default constructed state would require adding more state to the object and potentially allocating memory (!!!) and so seems like a Bad Idea. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@245192 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/ADT/FoldingSet.h | 18 ++++++++++++++---- lib/Support/FoldingSet.cpp | 20 ++++++++++++++++++++ 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/include/llvm/ADT/FoldingSet.h b/include/llvm/ADT/FoldingSet.h index 42e2e612d56..c9205396591 100644 --- a/include/llvm/ADT/FoldingSet.h +++ b/include/llvm/ADT/FoldingSet.h @@ -122,9 +122,10 @@ protected: /// is greater than twice the number of buckets. unsigned NumNodes; - ~FoldingSetImpl(); - explicit FoldingSetImpl(unsigned Log2InitSize = 6); + FoldingSetImpl(FoldingSetImpl &&Arg); + FoldingSetImpl &operator=(FoldingSetImpl &&RHS); + ~FoldingSetImpl(); public: //===--------------------------------------------------------------------===// @@ -391,6 +392,10 @@ DefaultContextualFoldingSetTrait::ComputeHash(T &X, /// implementation of the folding set to the node class T. T must be a /// subclass of FoldingSetNode and implement a Profile function. /// +/// Note that this set type is movable and move-assignable. However, its +/// moved-from state is not a valid state for anything other than +/// move-assigning and destroying. This is primarily to enable movable APIs +/// that incorporate these objects. template class FoldingSet final : public FoldingSetImpl { private: /// GetNodeProfile - Each instantiatation of the FoldingSet needs to provide a @@ -415,8 +420,13 @@ private: public: explicit FoldingSet(unsigned Log2InitSize = 6) - : FoldingSetImpl(Log2InitSize) - {} + : FoldingSetImpl(Log2InitSize) {} + + FoldingSet(FoldingSet &&Arg) : FoldingSetImpl(std::move(Arg)) {} + FoldingSet &operator=(FoldingSet &&RHS) { + (void)FoldingSetImpl::operator=(std::move(RHS)); + return *this; + } typedef FoldingSetIterator iterator; iterator begin() { return iterator(Buckets); } diff --git a/lib/Support/FoldingSet.cpp b/lib/Support/FoldingSet.cpp index b8538ffe1f9..bb0ec2defef 100644 --- a/lib/Support/FoldingSet.cpp +++ b/lib/Support/FoldingSet.cpp @@ -232,9 +232,29 @@ FoldingSetImpl::FoldingSetImpl(unsigned Log2InitSize) { Buckets = AllocateBuckets(NumBuckets); NumNodes = 0; } + +FoldingSetImpl::FoldingSetImpl(FoldingSetImpl &&Arg) + : Buckets(Arg.Buckets), NumBuckets(Arg.NumBuckets), NumNodes(Arg.NumNodes) { + Arg.Buckets = nullptr; + Arg.NumBuckets = 0; + Arg.NumNodes = 0; +} + +FoldingSetImpl &FoldingSetImpl::operator=(FoldingSetImpl &&RHS) { + free(Buckets); // This may be null if the set is in a moved-from state. + Buckets = RHS.Buckets; + NumBuckets = RHS.NumBuckets; + NumNodes = RHS.NumNodes; + RHS.Buckets = nullptr; + RHS.NumBuckets = 0; + RHS.NumNodes = 0; + return *this; +} + FoldingSetImpl::~FoldingSetImpl() { free(Buckets); } + void FoldingSetImpl::clear() { // Set all but the last bucket to null pointers. memset(Buckets, 0, NumBuckets*sizeof(void*)); -- 2.34.1