//==- llvm/ADT/IntrusiveRefCntPtr.h - Smart Refcounting Pointer --*- C++ -*-==// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// /// /// \file /// This file defines the RefCountedBase, ThreadSafeRefCountedBase, and /// IntrusiveRefCntPtr classes. /// /// IntrusiveRefCntPtr is a smart pointer to an object which maintains a /// reference count. (ThreadSafe)RefCountedBase is a mixin class that adds a /// refcount member variable and methods for updating the refcount. An object /// that inherits from (ThreadSafe)RefCountedBase deletes itself when its /// refcount hits zero. /// /// For example: /// /// ``` /// class MyClass : public RefCountedBase<MyClass> {}; /// /// void foo() { /// // Constructing an IntrusiveRefCntPtr increases the pointee's refcount /// // by 1 (from 0 in this case). /// IntrusiveRefCntPtr<MyClass> Ptr1(new MyClass()); /// /// // Copying an IntrusiveRefCntPtr increases the pointee's refcount by 1. /// IntrusiveRefCntPtr<MyClass> Ptr2(Ptr1); /// /// // Constructing an IntrusiveRefCntPtr has no effect on the object's /// // refcount. After a move, the moved-from pointer is null. /// IntrusiveRefCntPtr<MyClass> Ptr3(std::move(Ptr1)); /// assert(Ptr1 == nullptr); /// /// // Clearing an IntrusiveRefCntPtr decreases the pointee's refcount by 1. /// Ptr2.reset(); /// /// // The object deletes itself when we return from the function, because /// // Ptr3's destructor decrements its refcount to 0. /// } /// ``` /// /// You can use IntrusiveRefCntPtr with isa<T>(), dyn_cast<T>(), etc.: /// /// ``` /// IntrusiveRefCntPtr<MyClass> Ptr(new MyClass()); /// OtherClass *Other = dyn_cast<OtherClass>(Ptr); // Ptr.get() not required /// ``` /// /// IntrusiveRefCntPtr works with any class that /// /// - inherits from (ThreadSafe)RefCountedBase, /// - has Retain() and Release() methods, or /// - specializes IntrusiveRefCntPtrInfo. /// //===----------------------------------------------------------------------===// #ifndef LLVM_ADT_INTRUSIVEREFCNTPTR_H #define LLVM_ADT_INTRUSIVEREFCNTPTR_H #include <atomic> #include <cassert> #include <cstddef> #include <memory> namespace llvm { /// A CRTP mixin class that adds reference counting to a type. /// /// The lifetime of an object which inherits from RefCountedBase is managed by /// calls to Release() and Retain(), which increment and decrement the object's /// refcount, respectively. When a Release() call decrements the refcount to 0, /// the object deletes itself. template <class Derived> class RefCountedBase { … }; /// A thread-safe version of \c RefCountedBase. template <class Derived> class ThreadSafeRefCountedBase { … }; /// Class you can specialize to provide custom retain/release functionality for /// a type. /// /// Usually specializing this class is not necessary, as IntrusiveRefCntPtr /// works with any type which defines Retain() and Release() functions -- you /// can define those functions yourself if RefCountedBase doesn't work for you. /// /// One case when you might want to specialize this type is if you have /// - Foo.h defines type Foo and includes Bar.h, and /// - Bar.h uses IntrusiveRefCntPtr<Foo> in inline functions. /// /// Because Foo.h includes Bar.h, Bar.h can't include Foo.h in order to pull in /// the declaration of Foo. Without the declaration of Foo, normally Bar.h /// wouldn't be able to use IntrusiveRefCntPtr<Foo>, which wants to call /// T::Retain and T::Release. /// /// To resolve this, Bar.h could include a third header, FooFwd.h, which /// forward-declares Foo and specializes IntrusiveRefCntPtrInfo<Foo>. Then /// Bar.h could use IntrusiveRefCntPtr<Foo>, although it still couldn't call any /// functions on Foo itself, because Foo would be an incomplete type. template <typename T> struct IntrusiveRefCntPtrInfo { … }; /// A smart pointer to a reference-counted object that inherits from /// RefCountedBase or ThreadSafeRefCountedBase. /// /// This class increments its pointee's reference count when it is created, and /// decrements its refcount when it's destroyed (or is changed to point to a /// different object). template <typename T> class IntrusiveRefCntPtr { … }; template <class T, class U> inline bool operator==(const IntrusiveRefCntPtr<T> &A, const IntrusiveRefCntPtr<U> &B) { … } template <class T, class U> inline bool operator!=(const IntrusiveRefCntPtr<T> &A, const IntrusiveRefCntPtr<U> &B) { … } template <class T, class U> inline bool operator==(const IntrusiveRefCntPtr<T> &A, U *B) { … } template <class T, class U> inline bool operator!=(const IntrusiveRefCntPtr<T> &A, U *B) { … } template <class T, class U> inline bool operator==(T *A, const IntrusiveRefCntPtr<U> &B) { … } template <class T, class U> inline bool operator!=(T *A, const IntrusiveRefCntPtr<U> &B) { … } template <class T> bool operator==(std::nullptr_t, const IntrusiveRefCntPtr<T> &B) { … } template <class T> bool operator==(const IntrusiveRefCntPtr<T> &A, std::nullptr_t B) { … } template <class T> bool operator!=(std::nullptr_t A, const IntrusiveRefCntPtr<T> &B) { … } template <class T> bool operator!=(const IntrusiveRefCntPtr<T> &A, std::nullptr_t B) { … } // Make IntrusiveRefCntPtr work with dyn_cast, isa, and the other idioms from // Casting.h. template <typename From> struct simplify_type; simplify_type<IntrusiveRefCntPtr<T>>; simplify_type<const IntrusiveRefCntPtr<T>>; /// Factory function for creating intrusive ref counted pointers. template <typename T, typename... Args> IntrusiveRefCntPtr<T> makeIntrusiveRefCnt(Args &&...A) { … } } // end namespace llvm #endif // LLVM_ADT_INTRUSIVEREFCNTPTR_H