1 // Copyright 2012 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef BASE_MEMORY_REF_COUNTED_H_ 6 #define BASE_MEMORY_REF_COUNTED_H_ 7 8 #include <stddef.h> 9 10 #include <utility> 11 12 #include "base/atomic_ref_count.h" 13 #include "base/base_export.h" 14 #include "base/check.h" 15 #include "base/check_op.h" 16 #include "base/compiler_specific.h" 17 #include "base/dcheck_is_on.h" 18 // TODO(dcheng): Remove this separately. 19 #include "base/gtest_prod_util.h" 20 #include "base/memory/scoped_refptr.h" 21 #include "base/sequence_checker.h" 22 #include "base/template_util.h" 23 #include "base/threading/thread_collision_warner.h" 24 #include "build/build_config.h" 25 #include "third_party/abseil-cpp/absl/utility/utility.h" 26 27 namespace base { 28 namespace subtle { 29 30 class BASE_EXPORT RefCountedBase { 31 public: 32 RefCountedBase(const RefCountedBase&) = delete; 33 RefCountedBase& operator=(const RefCountedBase&) = delete; 34 HasOneRef()35 bool HasOneRef() const { return ref_count_ == 1; } HasAtLeastOneRef()36 bool HasAtLeastOneRef() const { return ref_count_ >= 1; } 37 38 protected: RefCountedBase(StartRefCountFromZeroTag)39 explicit RefCountedBase(StartRefCountFromZeroTag) { 40 #if DCHECK_IS_ON() 41 sequence_checker_.DetachFromSequence(); 42 #endif 43 } 44 RefCountedBase(StartRefCountFromOneTag)45 explicit RefCountedBase(StartRefCountFromOneTag) : ref_count_(1) { 46 #if DCHECK_IS_ON() 47 needs_adopt_ref_ = true; 48 sequence_checker_.DetachFromSequence(); 49 #endif 50 } 51 ~RefCountedBase()52 ~RefCountedBase() { 53 #if DCHECK_IS_ON() 54 // RefCounted object deleted without calling Release() 55 DCHECK(in_dtor_); 56 #endif 57 } 58 AddRef()59 void AddRef() const { 60 #if DCHECK_IS_ON() 61 DCHECK(!in_dtor_); 62 // This RefCounted object is created with non-zero reference count. 63 // The first reference to such a object has to be made by AdoptRef or 64 // MakeRefCounted. 65 DCHECK(!needs_adopt_ref_); 66 if (ref_count_ >= 1) { 67 DCHECK(CalledOnValidSequence()); 68 } 69 #endif 70 71 AddRefImpl(); 72 } 73 74 // Returns true if the object should self-delete. Release()75 bool Release() const { 76 ReleaseImpl(); 77 78 #if DCHECK_IS_ON() 79 DCHECK(!in_dtor_); 80 if (ref_count_ == 0) 81 in_dtor_ = true; 82 83 if (ref_count_ >= 1) 84 DCHECK(CalledOnValidSequence()); 85 if (ref_count_ == 1) 86 sequence_checker_.DetachFromSequence(); 87 #endif 88 89 return ref_count_ == 0; 90 } 91 92 // Returns true if it is safe to read or write the object, from a thread 93 // safety standpoint. Should be DCHECK'd from the methods of RefCounted 94 // classes if there is a danger of objects being shared across threads. 95 // 96 // This produces fewer false positives than adding a separate SequenceChecker 97 // into the subclass, because it automatically detaches from the sequence when 98 // the reference count is 1 (and never fails if there is only one reference). 99 // 100 // This means unlike a separate SequenceChecker, it will permit a singly 101 // referenced object to be passed between threads (not holding a reference on 102 // the sending thread), but will trap if the sending thread holds onto a 103 // reference, or if the object is accessed from multiple threads 104 // simultaneously. IsOnValidSequence()105 bool IsOnValidSequence() const { 106 #if DCHECK_IS_ON() 107 return ref_count_ <= 1 || CalledOnValidSequence(); 108 #else 109 return true; 110 #endif 111 } 112 113 private: 114 template <typename U> 115 friend scoped_refptr<U> base::AdoptRef(U*); 116 117 friend class RefCountedOverflowTest; 118 Adopted()119 void Adopted() const { 120 #if DCHECK_IS_ON() 121 DCHECK(needs_adopt_ref_); 122 needs_adopt_ref_ = false; 123 #endif 124 } 125 126 #if defined(ARCH_CPU_64_BITS) 127 void AddRefImpl() const; 128 void ReleaseImpl() const; 129 #else AddRefImpl()130 void AddRefImpl() const { ++ref_count_; } ReleaseImpl()131 void ReleaseImpl() const { --ref_count_; } 132 #endif 133 134 #if DCHECK_IS_ON() 135 bool CalledOnValidSequence() const; 136 #endif 137 138 mutable uint32_t ref_count_ = 0; 139 static_assert(std::is_unsigned<decltype(ref_count_)>::value, 140 "ref_count_ must be an unsigned type."); 141 142 #if DCHECK_IS_ON() 143 mutable bool needs_adopt_ref_ = false; 144 mutable bool in_dtor_ = false; 145 mutable SequenceChecker sequence_checker_; 146 #endif 147 148 DFAKE_MUTEX(add_release_); 149 }; 150 151 class BASE_EXPORT RefCountedThreadSafeBase { 152 public: 153 RefCountedThreadSafeBase(const RefCountedThreadSafeBase&) = delete; 154 RefCountedThreadSafeBase& operator=(const RefCountedThreadSafeBase&) = delete; 155 156 bool HasOneRef() const; 157 bool HasAtLeastOneRef() const; 158 159 protected: RefCountedThreadSafeBase(StartRefCountFromZeroTag)160 explicit constexpr RefCountedThreadSafeBase(StartRefCountFromZeroTag) {} RefCountedThreadSafeBase(StartRefCountFromOneTag)161 explicit constexpr RefCountedThreadSafeBase(StartRefCountFromOneTag) 162 : ref_count_(1) { 163 #if DCHECK_IS_ON() 164 needs_adopt_ref_ = true; 165 #endif 166 } 167 168 #if DCHECK_IS_ON() 169 ~RefCountedThreadSafeBase(); 170 #else 171 ~RefCountedThreadSafeBase() = default; 172 #endif 173 174 // Release and AddRef are suitable for inlining on X86 because they generate 175 // very small code sequences. 176 // 177 // ARM64 devices supporting ARMv8.1-A atomic instructions generate very little 178 // code, e.g. fetch_add() with acquire ordering is a single instruction (ldadd), 179 // vs LL/SC in previous ARM architectures. Inline it there as well. 180 // 181 // On other platforms (e.g. ARM), it causes a size regression and is probably 182 // not worth it. 183 #if defined(ARCH_CPU_X86_FAMILY) || defined(__ARM_FEATURE_ATOMICS) 184 // Returns true if the object should self-delete. Release()185 bool Release() const { return ReleaseImpl(); } AddRef()186 void AddRef() const { AddRefImpl(); } AddRefWithCheck()187 void AddRefWithCheck() const { AddRefWithCheckImpl(); } 188 #else 189 // Returns true if the object should self-delete. 190 bool Release() const; 191 void AddRef() const; 192 void AddRefWithCheck() const; 193 #endif 194 195 private: 196 template <typename U> 197 friend scoped_refptr<U> base::AdoptRef(U*); 198 199 friend class RefCountedOverflowTest; 200 Adopted()201 void Adopted() const { 202 #if DCHECK_IS_ON() 203 DCHECK(needs_adopt_ref_); 204 needs_adopt_ref_ = false; 205 #endif 206 } 207 AddRefImpl()208 ALWAYS_INLINE void AddRefImpl() const { 209 #if DCHECK_IS_ON() 210 DCHECK(!in_dtor_); 211 // This RefCounted object is created with non-zero reference count. 212 // The first reference to such a object has to be made by AdoptRef or 213 // MakeRefCounted. 214 DCHECK(!needs_adopt_ref_); 215 #endif 216 CHECK_NE(ref_count_.Increment(), std::numeric_limits<int>::max()); 217 } 218 AddRefWithCheckImpl()219 ALWAYS_INLINE void AddRefWithCheckImpl() const { 220 #if DCHECK_IS_ON() 221 DCHECK(!in_dtor_); 222 // This RefCounted object is created with non-zero reference count. 223 // The first reference to such a object has to be made by AdoptRef or 224 // MakeRefCounted. 225 DCHECK(!needs_adopt_ref_); 226 #endif 227 int pre_increment_count = ref_count_.Increment(); 228 CHECK_GT(pre_increment_count, 0); 229 CHECK_NE(pre_increment_count, std::numeric_limits<int>::max()); 230 } 231 ReleaseImpl()232 ALWAYS_INLINE bool ReleaseImpl() const { 233 #if DCHECK_IS_ON() 234 DCHECK(!in_dtor_); 235 DCHECK(!ref_count_.IsZero()); 236 #endif 237 if (!ref_count_.Decrement()) { 238 #if DCHECK_IS_ON() 239 in_dtor_ = true; 240 #endif 241 return true; 242 } 243 return false; 244 } 245 246 mutable AtomicRefCount ref_count_{0}; 247 #if DCHECK_IS_ON() 248 mutable bool needs_adopt_ref_ = false; 249 mutable bool in_dtor_ = false; 250 #endif 251 }; 252 253 } // namespace subtle 254 255 // ScopedAllowCrossThreadRefCountAccess disables the check documented on 256 // RefCounted below for rare pre-existing use cases where thread-safety was 257 // guaranteed through other means (e.g. explicit sequencing of calls across 258 // execution sequences when bouncing between threads in order). New callers 259 // should refrain from using this (callsites handling thread-safety through 260 // locks should use RefCountedThreadSafe per the overhead of its atomics being 261 // negligible compared to locks anyways and callsites doing explicit sequencing 262 // should properly std::move() the ref to avoid hitting this check). 263 // TODO(tzik): Cleanup existing use cases and remove 264 // ScopedAllowCrossThreadRefCountAccess. 265 class BASE_EXPORT ScopedAllowCrossThreadRefCountAccess final { 266 public: 267 #if DCHECK_IS_ON() 268 ScopedAllowCrossThreadRefCountAccess(); 269 ~ScopedAllowCrossThreadRefCountAccess(); 270 #else 271 ScopedAllowCrossThreadRefCountAccess() {} 272 ~ScopedAllowCrossThreadRefCountAccess() {} 273 #endif 274 }; 275 276 // 277 // A base class for reference counted classes. Otherwise, known as a cheap 278 // knock-off of WebKit's RefCounted<T> class. To use this, just extend your 279 // class from it like so: 280 // 281 // class MyFoo : public base::RefCounted<MyFoo> { 282 // ... 283 // private: 284 // friend class base::RefCounted<MyFoo>; 285 // ~MyFoo(); 286 // }; 287 // 288 // Usage Notes: 289 // 1. You should always make your destructor non-public, to avoid any code 290 // deleting the object accidentally while there are references to it. 291 // 2. You should always make the ref-counted base class a friend of your class, 292 // so that it can access the destructor. 293 // 294 // The ref count manipulation to RefCounted is NOT thread safe and has DCHECKs 295 // to trap unsafe cross thread usage. A subclass instance of RefCounted can be 296 // passed to another execution sequence only when its ref count is 1. If the ref 297 // count is more than 1, the RefCounted class verifies the ref updates are made 298 // on the same execution sequence as the previous ones. The subclass can also 299 // manually call IsOnValidSequence to trap other non-thread-safe accesses; see 300 // the documentation for that method. 301 // 302 // 303 // The reference count starts from zero by default, and we intended to migrate 304 // to start-from-one ref count. Put REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE() to 305 // the ref counted class to opt-in. 306 // 307 // If an object has start-from-one ref count, the first scoped_refptr need to be 308 // created by base::AdoptRef() or base::MakeRefCounted(). We can use 309 // base::MakeRefCounted() to create create both type of ref counted object. 310 // 311 // The motivations to use start-from-one ref count are: 312 // - Start-from-one ref count doesn't need the ref count increment for the 313 // first reference. 314 // - It can detect an invalid object acquisition for a being-deleted object 315 // that has zero ref count. That tends to happen on custom deleter that 316 // delays the deletion. 317 // TODO(tzik): Implement invalid acquisition detection. 318 // - Behavior parity to Blink's WTF::RefCounted, whose count starts from one. 319 // And start-from-one ref count is a step to merge WTF::RefCounted into 320 // base::RefCounted. 321 // 322 #define REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE() \ 323 using RefCountPreferenceTag = ::base::subtle::StartRefCountFromOneTag 324 325 template <class T, typename Traits> 326 class RefCounted; 327 328 template <typename T> 329 struct DefaultRefCountedTraits { DestructDefaultRefCountedTraits330 static void Destruct(const T* x) { 331 RefCounted<T, DefaultRefCountedTraits>::DeleteInternal(x); 332 } 333 }; 334 335 template <class T, typename Traits = DefaultRefCountedTraits<T>> 336 class RefCounted : public subtle::RefCountedBase { 337 public: 338 using RefCountPreferenceTag = subtle::StartRefCountFromZeroTag; 339 RefCounted()340 RefCounted() : subtle::RefCountedBase(subtle::GetRefCountPreference<T>()) {} 341 342 RefCounted(const RefCounted&) = delete; 343 RefCounted& operator=(const RefCounted&) = delete; 344 AddRef()345 void AddRef() const { 346 subtle::RefCountedBase::AddRef(); 347 } 348 Release()349 void Release() const { 350 if (subtle::RefCountedBase::Release()) { 351 // Prune the code paths which the static analyzer may take to simulate 352 // object destruction. Use-after-free errors aren't possible given the 353 // lifetime guarantees of the refcounting system. 354 ANALYZER_SKIP_THIS_PATH(); 355 356 Traits::Destruct(static_cast<const T*>(this)); 357 } 358 } 359 360 protected: 361 ~RefCounted() = default; 362 363 private: 364 friend struct DefaultRefCountedTraits<T>; 365 template <typename U> 366 static void DeleteInternal(const U* x) { 367 delete x; 368 } 369 }; 370 371 // Forward declaration. 372 template <class T, typename Traits> class RefCountedThreadSafe; 373 374 // Default traits for RefCountedThreadSafe<T>. Deletes the object when its ref 375 // count reaches 0. Overload to delete it on a different thread etc. 376 template<typename T> 377 struct DefaultRefCountedThreadSafeTraits { 378 static void Destruct(const T* x) { 379 // Delete through RefCountedThreadSafe to make child classes only need to be 380 // friend with RefCountedThreadSafe instead of this struct, which is an 381 // implementation detail. 382 RefCountedThreadSafe<T, 383 DefaultRefCountedThreadSafeTraits>::DeleteInternal(x); 384 } 385 }; 386 387 // 388 // A thread-safe variant of RefCounted<T> 389 // 390 // class MyFoo : public base::RefCountedThreadSafe<MyFoo> { 391 // ... 392 // }; 393 // 394 // If you're using the default trait, then you should add compile time 395 // asserts that no one else is deleting your object. i.e. 396 // private: 397 // friend class base::RefCountedThreadSafe<MyFoo>; 398 // ~MyFoo(); 399 // 400 // We can use REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE() with RefCountedThreadSafe 401 // too. See the comment above the RefCounted definition for details. 402 template <class T, typename Traits = DefaultRefCountedThreadSafeTraits<T> > 403 class RefCountedThreadSafe : public subtle::RefCountedThreadSafeBase { 404 public: 405 using RefCountPreferenceTag = subtle::StartRefCountFromZeroTag; 406 407 explicit RefCountedThreadSafe() 408 : subtle::RefCountedThreadSafeBase(subtle::GetRefCountPreference<T>()) {} 409 410 RefCountedThreadSafe(const RefCountedThreadSafe&) = delete; 411 RefCountedThreadSafe& operator=(const RefCountedThreadSafe&) = delete; 412 413 void AddRef() const { AddRefImpl(subtle::GetRefCountPreference<T>()); } 414 415 void Release() const { 416 if (subtle::RefCountedThreadSafeBase::Release()) { 417 ANALYZER_SKIP_THIS_PATH(); 418 Traits::Destruct(static_cast<const T*>(this)); 419 } 420 } 421 422 protected: 423 ~RefCountedThreadSafe() = default; 424 425 private: 426 friend struct DefaultRefCountedThreadSafeTraits<T>; 427 template <typename U> 428 static void DeleteInternal(const U* x) { 429 delete x; 430 } 431 432 void AddRefImpl(subtle::StartRefCountFromZeroTag) const { 433 subtle::RefCountedThreadSafeBase::AddRef(); 434 } 435 436 void AddRefImpl(subtle::StartRefCountFromOneTag) const { 437 subtle::RefCountedThreadSafeBase::AddRefWithCheck(); 438 } 439 }; 440 441 // 442 // A thread-safe wrapper for some piece of data so we can place other 443 // things in scoped_refptrs<>. 444 // 445 template<typename T> 446 class RefCountedData 447 : public base::RefCountedThreadSafe< base::RefCountedData<T> > { 448 public: 449 RefCountedData() : data() {} 450 RefCountedData(const T& in_value) : data(in_value) {} 451 RefCountedData(T&& in_value) : data(std::move(in_value)) {} 452 template <typename... Args> 453 explicit RefCountedData(absl::in_place_t, Args&&... args) 454 : data(std::forward<Args>(args)...) {} 455 456 T data; 457 458 private: 459 friend class base::RefCountedThreadSafe<base::RefCountedData<T> >; 460 ~RefCountedData() = default; 461 }; 462 463 template <typename T> 464 bool operator==(const RefCountedData<T>& lhs, const RefCountedData<T>& rhs) { 465 return lhs.data == rhs.data; 466 } 467 468 template <typename T> 469 bool operator!=(const RefCountedData<T>& lhs, const RefCountedData<T>& rhs) { 470 return !(lhs == rhs); 471 } 472 473 } // namespace base 474 475 #endif // BASE_MEMORY_REF_COUNTED_H_ 476