123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456 |
- #ifndef BASE_MEMORY_REF_COUNTED_H_
- #define BASE_MEMORY_REF_COUNTED_H_
- #include <stddef.h>
- #include <utility>
- #include "base/atomic_ref_count.h"
- #include "base/base_export.h"
- #include "base/check_op.h"
- #include "base/compiler_specific.h"
- #include "base/gtest_prod_util.h"
- #include "base/macros.h"
- #include "base/memory/scoped_refptr.h"
- #include "base/sequence_checker.h"
- #include "base/threading/thread_collision_warner.h"
- #include "build/build_config.h"
- namespace base {
- namespace subtle {
- class BASE_EXPORT RefCountedBase {
- public:
- bool HasOneRef() const { return ref_count_ == 1; }
- bool HasAtLeastOneRef() const { return ref_count_ >= 1; }
- protected:
- explicit RefCountedBase(StartRefCountFromZeroTag) {
- #if DCHECK_IS_ON()
- sequence_checker_.DetachFromSequence();
- #endif
- }
- explicit RefCountedBase(StartRefCountFromOneTag) : ref_count_(1) {
- #if DCHECK_IS_ON()
- needs_adopt_ref_ = true;
- sequence_checker_.DetachFromSequence();
- #endif
- }
- ~RefCountedBase() {
- #if DCHECK_IS_ON()
- DCHECK(in_dtor_) << "RefCounted object deleted without calling Release()";
- #endif
- }
- void AddRef() const {
- #if DCHECK_IS_ON()
- DCHECK(!in_dtor_);
- DCHECK(!needs_adopt_ref_)
- << "This RefCounted object is created with non-zero reference count."
- << " The first reference to such a object has to be made by AdoptRef or"
- << " MakeRefCounted.";
- if (ref_count_ >= 1) {
- DCHECK(CalledOnValidSequence());
- }
- #endif
- AddRefImpl();
- }
-
- bool Release() const {
- ReleaseImpl();
- #if DCHECK_IS_ON()
- DCHECK(!in_dtor_);
- if (ref_count_ == 0)
- in_dtor_ = true;
- if (ref_count_ >= 1)
- DCHECK(CalledOnValidSequence());
- if (ref_count_ == 1)
- sequence_checker_.DetachFromSequence();
- #endif
- return ref_count_ == 0;
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
- bool IsOnValidSequence() const {
- #if DCHECK_IS_ON()
- return ref_count_ <= 1 || CalledOnValidSequence();
- #else
- return true;
- #endif
- }
- private:
- template <typename U>
- friend scoped_refptr<U> base::AdoptRef(U*);
- FRIEND_TEST_ALL_PREFIXES(RefCountedDeathTest, TestOverflowCheck);
- void Adopted() const {
- #if DCHECK_IS_ON()
- DCHECK(needs_adopt_ref_);
- needs_adopt_ref_ = false;
- #endif
- }
- #if defined(ARCH_CPU_64_BITS)
- void AddRefImpl() const;
- void ReleaseImpl() const;
- #else
- void AddRefImpl() const { ++ref_count_; }
- void ReleaseImpl() const { --ref_count_; }
- #endif
- #if DCHECK_IS_ON()
- bool CalledOnValidSequence() const;
- #endif
- mutable uint32_t ref_count_ = 0;
- static_assert(std::is_unsigned<decltype(ref_count_)>::value,
- "ref_count_ must be an unsigned type.");
- #if DCHECK_IS_ON()
- mutable bool needs_adopt_ref_ = false;
- mutable bool in_dtor_ = false;
- mutable SequenceChecker sequence_checker_;
- #endif
- DFAKE_MUTEX(add_release_);
- DISALLOW_COPY_AND_ASSIGN(RefCountedBase);
- };
- class BASE_EXPORT RefCountedThreadSafeBase {
- public:
- bool HasOneRef() const;
- bool HasAtLeastOneRef() const;
- protected:
- explicit constexpr RefCountedThreadSafeBase(StartRefCountFromZeroTag) {}
- explicit constexpr RefCountedThreadSafeBase(StartRefCountFromOneTag)
- : ref_count_(1) {
- #if DCHECK_IS_ON()
- needs_adopt_ref_ = true;
- #endif
- }
- #if DCHECK_IS_ON()
- ~RefCountedThreadSafeBase();
- #else
- ~RefCountedThreadSafeBase() = default;
- #endif
- #if defined(ARCH_CPU_X86_FAMILY)
-
- bool Release() const { return ReleaseImpl(); }
- void AddRef() const { AddRefImpl(); }
- void AddRefWithCheck() const { AddRefWithCheckImpl(); }
- #else
-
- bool Release() const;
- void AddRef() const;
- void AddRefWithCheck() const;
- #endif
- private:
- template <typename U>
- friend scoped_refptr<U> base::AdoptRef(U*);
- void Adopted() const {
- #if DCHECK_IS_ON()
- DCHECK(needs_adopt_ref_);
- needs_adopt_ref_ = false;
- #endif
- }
- ALWAYS_INLINE void AddRefImpl() const {
- #if DCHECK_IS_ON()
- DCHECK(!in_dtor_);
- DCHECK(!needs_adopt_ref_)
- << "This RefCounted object is created with non-zero reference count."
- << " The first reference to such a object has to be made by AdoptRef or"
- << " MakeRefCounted.";
- #endif
- ref_count_.Increment();
- }
- ALWAYS_INLINE void AddRefWithCheckImpl() const {
- #if DCHECK_IS_ON()
- DCHECK(!in_dtor_);
- DCHECK(!needs_adopt_ref_)
- << "This RefCounted object is created with non-zero reference count."
- << " The first reference to such a object has to be made by AdoptRef or"
- << " MakeRefCounted.";
- #endif
- CHECK(ref_count_.Increment() > 0);
- }
- ALWAYS_INLINE bool ReleaseImpl() const {
- #if DCHECK_IS_ON()
- DCHECK(!in_dtor_);
- DCHECK(!ref_count_.IsZero());
- #endif
- if (!ref_count_.Decrement()) {
- #if DCHECK_IS_ON()
- in_dtor_ = true;
- #endif
- return true;
- }
- return false;
- }
- mutable AtomicRefCount ref_count_{0};
- #if DCHECK_IS_ON()
- mutable bool needs_adopt_ref_ = false;
- mutable bool in_dtor_ = false;
- #endif
- DISALLOW_COPY_AND_ASSIGN(RefCountedThreadSafeBase);
- };
- }
- class BASE_EXPORT ScopedAllowCrossThreadRefCountAccess final {
- public:
- #if DCHECK_IS_ON()
- ScopedAllowCrossThreadRefCountAccess();
- ~ScopedAllowCrossThreadRefCountAccess();
- #else
- ScopedAllowCrossThreadRefCountAccess() {}
- ~ScopedAllowCrossThreadRefCountAccess() {}
- #endif
- };
- #define REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE() \
- static constexpr ::base::subtle::StartRefCountFromOneTag \
- kRefCountPreference = ::base::subtle::kStartRefCountFromOneTag
- template <class T, typename Traits>
- class RefCounted;
- template <typename T>
- struct DefaultRefCountedTraits {
- static void Destruct(const T* x) {
- RefCounted<T, DefaultRefCountedTraits>::DeleteInternal(x);
- }
- };
- template <class T, typename Traits = DefaultRefCountedTraits<T>>
- class RefCounted : public subtle::RefCountedBase {
- public:
- static constexpr subtle::StartRefCountFromZeroTag kRefCountPreference =
- subtle::kStartRefCountFromZeroTag;
- RefCounted() : subtle::RefCountedBase(T::kRefCountPreference) {}
- void AddRef() const {
- subtle::RefCountedBase::AddRef();
- }
- void Release() const {
- if (subtle::RefCountedBase::Release()) {
-
-
-
- ANALYZER_SKIP_THIS_PATH();
- Traits::Destruct(static_cast<const T*>(this));
- }
- }
- protected:
- ~RefCounted() = default;
- private:
- friend struct DefaultRefCountedTraits<T>;
- template <typename U>
- static void DeleteInternal(const U* x) {
- delete x;
- }
- DISALLOW_COPY_AND_ASSIGN(RefCounted);
- };
- template <class T, typename Traits> class RefCountedThreadSafe;
- template<typename T>
- struct DefaultRefCountedThreadSafeTraits {
- static void Destruct(const T* x) {
-
-
-
- RefCountedThreadSafe<T,
- DefaultRefCountedThreadSafeTraits>::DeleteInternal(x);
- }
- };
- template <class T, typename Traits = DefaultRefCountedThreadSafeTraits<T> >
- class RefCountedThreadSafe : public subtle::RefCountedThreadSafeBase {
- public:
- static constexpr subtle::StartRefCountFromZeroTag kRefCountPreference =
- subtle::kStartRefCountFromZeroTag;
- explicit RefCountedThreadSafe()
- : subtle::RefCountedThreadSafeBase(T::kRefCountPreference) {}
- void AddRef() const { AddRefImpl(T::kRefCountPreference); }
- void Release() const {
- if (subtle::RefCountedThreadSafeBase::Release()) {
- ANALYZER_SKIP_THIS_PATH();
- Traits::Destruct(static_cast<const T*>(this));
- }
- }
- protected:
- ~RefCountedThreadSafe() = default;
- private:
- friend struct DefaultRefCountedThreadSafeTraits<T>;
- template <typename U>
- static void DeleteInternal(const U* x) {
- delete x;
- }
- void AddRefImpl(subtle::StartRefCountFromZeroTag) const {
- subtle::RefCountedThreadSafeBase::AddRef();
- }
- void AddRefImpl(subtle::StartRefCountFromOneTag) const {
- subtle::RefCountedThreadSafeBase::AddRefWithCheck();
- }
- DISALLOW_COPY_AND_ASSIGN(RefCountedThreadSafe);
- };
- template<typename T>
- class RefCountedData
- : public base::RefCountedThreadSafe< base::RefCountedData<T> > {
- public:
- RefCountedData() : data() {}
- RefCountedData(const T& in_value) : data(in_value) {}
- RefCountedData(T&& in_value) : data(std::move(in_value)) {}
- T data;
- private:
- friend class base::RefCountedThreadSafe<base::RefCountedData<T> >;
- ~RefCountedData() = default;
- };
- template <typename T>
- bool operator==(const RefCountedData<T>& lhs, const RefCountedData<T>& rhs) {
- return lhs.data == rhs.data;
- }
- template <typename T>
- bool operator!=(const RefCountedData<T>& lhs, const RefCountedData<T>& rhs) {
- return !(lhs == rhs);
- }
- }
- #endif
|