summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2010-04-05 21:09:22 +0000
committerDouglas Gregor <dgregor@apple.com>2010-04-05 21:09:22 +0000
commit2ee35226e5940eed3d360fcfb37be7f3a4866f27 (patch)
tree236d7621f9d9b3b18605056b3c4ce0931b69af9d
parent376ac434addd3b3652bf195c350463992e1df262 (diff)
downloadllvm-2ee35226e5940eed3d360fcfb37be7f3a4866f27.tar.gz
llvm-2ee35226e5940eed3d360fcfb37be7f3a4866f27.tar.bz2
llvm-2ee35226e5940eed3d360fcfb37be7f3a4866f27.tar.xz
Introduce MaybeOwningPtr, a smart pointer that may (or may not) have
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
-rw-r--r--include/llvm/ADT/OwningPtr.h92
1 files changed, 92 insertions, 0 deletions
diff --git a/include/llvm/ADT/OwningPtr.h b/include/llvm/ADT/OwningPtr.h
index cc53c8c30c..b40d2b7cc9 100644
--- a/include/llvm/ADT/OwningPtr.h
+++ b/include/llvm/ADT/OwningPtr.h
@@ -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