// Copyright 2012 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_REF_COUNTED_H_ #define BASE_MEMORY_REF_COUNTED_H_ #include <stddef.h> #include <limits> #include <utility> #include "base/atomic_ref_count.h" #include "base/base_export.h" #include "base/check.h" #include "base/check_op.h" #include "base/compiler_specific.h" #include "base/dcheck_is_on.h" #include "base/memory/scoped_refptr.h" #include "base/sequence_checker.h" #include "base/threading/thread_collision_warner.h" #include "build/build_config.h" #include "third_party/abseil-cpp/absl/utility/utility.h" namespace base { namespace subtle { class BASE_EXPORT RefCountedBase { … }; class BASE_EXPORT RefCountedThreadSafeBase { … }; } // namespace subtle // ScopedAllowCrossThreadRefCountAccess disables the check documented on // RefCounted below for rare pre-existing use cases where thread-safety was // guaranteed through other means (e.g. explicit sequencing of calls across // execution sequences when bouncing between threads in order). New callers // should refrain from using this (callsites handling thread-safety through // locks should use RefCountedThreadSafe per the overhead of its atomics being // negligible compared to locks anyways and callsites doing explicit sequencing // should properly std::move() the ref to avoid hitting this check). // TODO(tzik): Cleanup existing use cases and remove // ScopedAllowCrossThreadRefCountAccess. class BASE_EXPORT ScopedAllowCrossThreadRefCountAccess final { … }; // // A base class for reference counted classes. Otherwise, known as a cheap // knock-off of WebKit's RefCounted<T> class. To use this, just extend your // class from it like so: // // class MyFoo : public base::RefCounted<MyFoo> { // ... // private: // friend class base::RefCounted<MyFoo>; // ~MyFoo(); // }; // // Usage Notes: // 1. You should always make your destructor non-public, to avoid any code // deleting the object accidentally while there are references to it. // 2. You should always make the ref-counted base class a friend of your class, // so that it can access the destructor. // // The ref count manipulation to RefCounted is NOT thread safe and has DCHECKs // to trap unsafe cross thread usage. A subclass instance of RefCounted can be // passed to another execution sequence only when its ref count is 1. If the ref // count is more than 1, the RefCounted class verifies the ref updates are made // on the same execution sequence as the previous ones. The subclass can also // manually call IsOnValidSequence to trap other non-thread-safe accesses; see // the documentation for that method. // // // The reference count starts from zero by default, and we intended to migrate // to start-from-one ref count. Put REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE() to // the ref counted class to opt-in. // // If an object has start-from-one ref count, the first scoped_refptr need to be // created by base::AdoptRef() or base::MakeRefCounted(). We can use // base::MakeRefCounted() to create create both type of ref counted object. // // The motivations to use start-from-one ref count are: // - Start-from-one ref count doesn't need the ref count increment for the // first reference. // - It can detect an invalid object acquisition for a being-deleted object // that has zero ref count. That tends to happen on custom deleter that // delays the deletion. // TODO(tzik): Implement invalid acquisition detection. // - Behavior parity to Blink's WTF::RefCounted, whose count starts from one. // And start-from-one ref count is a step to merge WTF::RefCounted into // base::RefCounted. // #define REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE() … template <class T, typename Traits> class RefCounted; template <typename T> struct DefaultRefCountedTraits { … }; template <class T, typename Traits = DefaultRefCountedTraits<T>> class RefCounted : public subtle::RefCountedBase { public: using RefCountPreferenceTag = subtle::StartRefCountFromZeroTag; RefCounted() : … { … } RefCounted(const RefCounted&) = delete; RefCounted& operator=(const RefCounted&) = delete; void AddRef() const { … } void Release() const { … } protected: ~RefCounted() = default; private: friend struct DefaultRefCountedTraits<T>; template <typename U> static void DeleteInternal(const U* x) { … } }; // Forward declaration. template <class T, typename Traits> class RefCountedThreadSafe; // Default traits for RefCountedThreadSafe<T>. Deletes the object when its ref // count reaches 0. Overload to delete it on a different thread etc. template<typename T> struct DefaultRefCountedThreadSafeTraits { … }; // // A thread-safe variant of RefCounted<T> // // class MyFoo : public base::RefCountedThreadSafe<MyFoo> { // ... // }; // // If you're using the default trait, then you should add compile time // asserts that no one else is deleting your object. i.e. // private: // friend class base::RefCountedThreadSafe<MyFoo>; // ~MyFoo(); // // We can use REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE() with RefCountedThreadSafe // too. See the comment above the RefCounted definition for details. template <class T, typename Traits = DefaultRefCountedThreadSafeTraits<T> > class RefCountedThreadSafe : public subtle::RefCountedThreadSafeBase { … }; // // A thread-safe wrapper for some piece of data so we can place other // things in scoped_refptrs<>. // template<typename T> class RefCountedData : public base::RefCountedThreadSafe< base::RefCountedData<T> > { … }; template <typename T> bool operator==(const RefCountedData<T>& lhs, const RefCountedData<T>& rhs) { … } template <typename T> bool operator!=(const RefCountedData<T>& lhs, const RefCountedData<T>& rhs) { … } } // namespace base #endif // BASE_MEMORY_REF_COUNTED_H_