Introduce MaybeOwningPtr, a smart pointer that may (or may not) have
authorDouglas Gregor <dgregor@apple.com>
Mon, 5 Apr 2010 21:09:22 +0000 (21:09 +0000)
committerDouglas Gregor <dgregor@apple.com>
Mon, 5 Apr 2010 21:09:22 +0000 (21:09 +0000)
ownership over the pointer it contains. Useful when we want to
communicate ownership while still having several clients holding on to
the same pointer *without* introducing reference counting.

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

include/llvm/ADT/OwningPtr.h

index cc53c8c30c1216c8bdaad394ab6a147c989117a0..b40d2b7cc9f89b44ed4cd28face56e14f17fa62c 100644 (file)
@@ -128,7 +128,99 @@ inline void swap(OwningArrayPtr<T> &a, OwningArrayPtr<T> &b) {
   a.swap(b);
 }
 
+/// \brief A smart pointer that may own the object it points to.
+///
+/// An instance of \c MaybeOwningPtr may own the object it points to. If so,
+/// it will guarantee that the object will be deleted either on destructin of
+/// the OwningPtr or via an explicit reset(). Once created, ownership of the
+/// pointee object can be taken away from OwningPtr by using the \c take()
+/// method.
+template<class T>
+class MaybeOwningPtr {
+  T *Ptr;
+  bool Owned;
+  
+  struct MaybeOwningPtrRef {
+    MaybeOwningPtrRef(T *Ptr, bool &Owned) : Ptr(Ptr), Owned(Owned) { }
+    
+    T *Ptr;
+    bool &Owned;
+  };
+  
+public:
+  MaybeOwningPtr() : Ptr(0), Owned(false) { }
+  
+  explicit MaybeOwningPtr(T *P, bool OwnP) : Ptr(P), Owned(OwnP) {}
+  
+  /// \brief Take ownership of the pointer stored in \c Other.
+  MaybeOwningPtr(MaybeOwningPtr& Other) : Ptr(Other.Ptr), Owned(Other.Owned) {
+    Other.Owned = false;
+  }
+
+  MaybeOwningPtr(MaybeOwningPtrRef Other) : Ptr(Other.Ptr), Owned(Other.Owned) {
+    Other.Owned = false;
+  }
+    
+  /// \brief Take ownership of the ppinter stored in \c Other.
+  MaybeOwningPtr &operator=(MaybeOwningPtr &Other) {
+    reset(Other.Ptr, Other.Owned);
+    Other.Owned = false;
+    return *this;
+  }
+
+  ~MaybeOwningPtr() {
+    if (Owned)
+      delete Ptr;
+  }
+  
+  operator MaybeOwningPtrRef() { return MaybeOwningPtrRef(Ptr, Owned); }
+  
+  /// reset - Change the current pointee to the specified pointer.  Note that
+  /// calling this with any pointer (including a null pointer) deletes the
+  /// current pointer.
+  void reset(T *P, bool OwnP) {
+    assert(P != Ptr);
+    if (Owned)
+      delete Ptr;
+    
+    Ptr = P;
+    Owned = OwnP;
+  }
+  
+  /// take - Return the underlying pointer and take ownership of it. This
+  /// \c MaybeOwningPtr must have ownership before the call, and will 
+  /// relinquish ownership as part of the call.
+  T *take() {
+    assert(Owned && "Cannot take ownership from a non-owning pointer");
+    Owned = false;
+    return Ptr;
+  }
+  
+  T &operator*() const {
+    assert(Ptr && "Cannot dereference null pointer");
+    return *Ptr;
+  }
+  
+  T *operator->() const { return Ptr; }
+  T *get() const { return Ptr; }
+  operator bool() const { return Ptr != 0; }
+  bool operator!() const { return Ptr == 0; }
+  
+  void swap(MaybeOwningPtr &RHS) {
+    T *Tmp = RHS.Ptr;
+    RHS.Ptr = Ptr;
+    Ptr = Tmp;
+    bool TmpOwned = RHS.Owned;
+    RHS.Owned = Owned;
+    Owned = TmpOwned;
+  }
+};
 
+template<class T>
+inline void swap(MaybeOwningPtr<T> &a, MaybeOwningPtr<T> &b) {
+  a.swap(b);
+}
+  
 } // end namespace llvm
 
 #endif