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