// Copyright 2017 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef BASE_MEMORY_SCOPED_REFPTR_H_ #define BASE_MEMORY_SCOPED_REFPTR_H_ #include <stddef.h> #include <compare> #include <concepts> #include <iosfwd> #include <type_traits> #include <utility> #include "base/check.h" #include "base/compiler_specific.h" #include "base/memory/raw_ptr_exclusion.h" template <class T> class scoped_refptr; namespace base { template <class, typename> class RefCounted; template <class, typename> class RefCountedThreadSafe; template <class> class RefCountedDeleteOnSequence; class SequencedTaskRunner; template <typename T> scoped_refptr<T> AdoptRef(T* t); namespace subtle { enum AdoptRefTag { … }; enum StartRefCountFromZeroTag { … }; enum StartRefCountFromOneTag { … }; template <typename TagType> struct RefCountPreferenceTagTraits; template <> struct RefCountPreferenceTagTraits<StartRefCountFromZeroTag> { … }; template <> struct RefCountPreferenceTagTraits<StartRefCountFromOneTag> { … }; template <typename T, typename Tag = typename T::RefCountPreferenceTag> constexpr Tag GetRefCountPreference() { … } // scoped_refptr<T> is typically used with one of several RefCounted<T> base // classes or with custom AddRef and Release methods. These overloads dispatch // on which was used. template <typename T, typename U, typename V> constexpr bool IsRefCountPreferenceOverridden(const T*, const RefCounted<U, V>*) { … } template <typename T, typename U, typename V> constexpr bool IsRefCountPreferenceOverridden( const T*, const RefCountedThreadSafe<U, V>*) { … } template <typename T, typename U> constexpr bool IsRefCountPreferenceOverridden( const T*, const RefCountedDeleteOnSequence<U>*) { … } constexpr bool IsRefCountPreferenceOverridden(...) { … } template <typename T, typename U, typename V> constexpr void AssertRefCountBaseMatches(const T*, const RefCounted<U, V>*) { … } template <typename T, typename U, typename V> constexpr void AssertRefCountBaseMatches(const T*, const RefCountedThreadSafe<U, V>*) { … } template <typename T, typename U> constexpr void AssertRefCountBaseMatches(const T*, const RefCountedDeleteOnSequence<U>*) { … } constexpr void AssertRefCountBaseMatches(...) { … } } // namespace subtle // Creates a scoped_refptr from a raw pointer without incrementing the reference // count. Use this only for a newly created object whose reference count starts // from 1 instead of 0. template <typename T> scoped_refptr<T> AdoptRef(T* obj) { … } namespace subtle { template <typename T> scoped_refptr<T> AdoptRefIfNeeded(T* obj, StartRefCountFromZeroTag) { … } template <typename T> scoped_refptr<T> AdoptRefIfNeeded(T* obj, StartRefCountFromOneTag) { … } } // namespace subtle // Constructs an instance of T, which is a ref counted type, and wraps the // object into a scoped_refptr<T>. template <typename T, typename... Args> scoped_refptr<T> MakeRefCounted(Args&&... args) { … } // Takes an instance of T, which is a ref counted type, and wraps the object // into a scoped_refptr<T>. template <typename T> scoped_refptr<T> WrapRefCounted(T* t) { … } } // namespace base // // A smart pointer class for reference counted objects. Use this class instead // of calling AddRef and Release manually on a reference counted object to // avoid common memory leaks caused by forgetting to Release an object // reference. Sample usage: // // class MyFoo : public RefCounted<MyFoo> { // ... // private: // friend class RefCounted<MyFoo>; // Allow destruction by RefCounted<>. // ~MyFoo(); // Destructor must be private/protected. // }; // // void some_function() { // scoped_refptr<MyFoo> foo = MakeRefCounted<MyFoo>(); // foo->Method(param); // // |foo| is released when this function returns // } // // void some_other_function() { // scoped_refptr<MyFoo> foo = MakeRefCounted<MyFoo>(); // ... // foo.reset(); // explicitly releases |foo| // ... // if (foo) // foo->Method(param); // } // // The above examples show how scoped_refptr<T> acts like a pointer to T. // Given two scoped_refptr<T> classes, it is also possible to exchange // references between the two objects, like so: // // { // scoped_refptr<MyFoo> a = MakeRefCounted<MyFoo>(); // scoped_refptr<MyFoo> b; // // b.swap(a); // // now, |b| references the MyFoo object, and |a| references nullptr. // } // // To make both |a| and |b| in the above example reference the same MyFoo // object, simply use the assignment operator: // // { // scoped_refptr<MyFoo> a = MakeRefCounted<MyFoo>(); // scoped_refptr<MyFoo> b; // // b = a; // // now, |a| and |b| each own a reference to the same MyFoo object. // } // // Also see Chromium's ownership and calling conventions: // https://chromium.googlesource.com/chromium/src/+/lkgr/styleguide/c++/c++.md#object-ownership-and-calling-conventions // Specifically: // If the function (at least sometimes) takes a ref on a refcounted object, // declare the param as scoped_refptr<T>. The caller can decide whether it // wishes to transfer ownership (by calling std::move(t) when passing t) or // retain its ref (by simply passing t directly). // In other words, use scoped_refptr like you would a std::unique_ptr except // in the odd case where it's required to hold on to a ref while handing one // to another component (if a component merely needs to use t on the stack // without keeping a ref: pass t as a raw T*). template <class T> class TRIVIAL_ABI scoped_refptr { … }; template <typename T> T* scoped_refptr<T>::release() { … } // static template <typename T> void scoped_refptr<T>::AddRef(T* ptr) { … } // static template <typename T> void scoped_refptr<T>::Release(T* ptr) { … } template <typename T> std::ostream& operator<<(std::ostream& out, const scoped_refptr<T>& p) { … } template <typename T> void swap(scoped_refptr<T>& lhs, scoped_refptr<T>& rhs) noexcept { … } #endif // BASE_MEMORY_SCOPED_REFPTR_H_