• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
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 <cassert>
11 #include <iosfwd>
12 #include <type_traits>
13 
14 #include "base/atomic_ref_count.h"
15 #include "base/base_export.h"
16 #include "base/compiler_specific.h"
17 #include "base/logging.h"
18 #include "base/macros.h"
19 #include "base/sequence_checker.h"
20 #include "base/threading/thread_collision_warner.h"
21 #include "build/build_config.h"
22 
23 template <class T>
24 class scoped_refptr;
25 
26 namespace base {
27 
28 template <typename T>
29 scoped_refptr<T> AdoptRef(T* t);
30 
31 namespace subtle {
32 
33 enum AdoptRefTag { kAdoptRefTag };
34 enum StartRefCountFromZeroTag { kStartRefCountFromZeroTag };
35 enum StartRefCountFromOneTag { kStartRefCountFromOneTag };
36 
37 class BASE_EXPORT RefCountedBase {
38  public:
HasOneRef()39   bool HasOneRef() const { return ref_count_ == 1; }
40 
41  protected:
RefCountedBase(StartRefCountFromZeroTag)42   explicit RefCountedBase(StartRefCountFromZeroTag) {
43 #if DCHECK_IS_ON()
44     sequence_checker_.DetachFromSequence();
45 #endif
46   }
47 
RefCountedBase(StartRefCountFromOneTag)48   explicit RefCountedBase(StartRefCountFromOneTag) : ref_count_(1) {
49 #if DCHECK_IS_ON()
50     needs_adopt_ref_ = true;
51     sequence_checker_.DetachFromSequence();
52 #endif
53   }
54 
~RefCountedBase()55   ~RefCountedBase() {
56 #if DCHECK_IS_ON()
57     DCHECK(in_dtor_) << "RefCounted object deleted without calling Release()";
58 #endif
59   }
60 
AddRef()61   void AddRef() const {
62     // TODO(maruel): Add back once it doesn't assert 500 times/sec.
63     // Current thread books the critical section "AddRelease"
64     // without release it.
65     // DFAKE_SCOPED_LOCK_THREAD_LOCKED(add_release_);
66 #if DCHECK_IS_ON()
67     DCHECK(!in_dtor_);
68     DCHECK(!needs_adopt_ref_)
69         << "This RefCounted object is created with non-zero reference count."
70         << " The first reference to such a object has to be made by AdoptRef or"
71         << " MakeShared.";
72     if (ref_count_ >= 1) {
73       DCHECK(CalledOnValidSequence());
74     }
75 #endif
76 
77     ++ref_count_;
78   }
79 
80   // Returns true if the object should self-delete.
Release()81   bool Release() const {
82     --ref_count_;
83 
84     // TODO(maruel): Add back once it doesn't assert 500 times/sec.
85     // Current thread books the critical section "AddRelease"
86     // without release it.
87     // DFAKE_SCOPED_LOCK_THREAD_LOCKED(add_release_);
88 
89 #if DCHECK_IS_ON()
90     DCHECK(!in_dtor_);
91     if (ref_count_ == 0)
92       in_dtor_ = true;
93 
94     if (ref_count_ >= 1)
95       DCHECK(CalledOnValidSequence());
96     if (ref_count_ == 1)
97       sequence_checker_.DetachFromSequence();
98 #endif
99 
100     return ref_count_ == 0;
101   }
102 
103  private:
104   template <typename U>
105   friend scoped_refptr<U> base::AdoptRef(U*);
106 
Adopted()107   void Adopted() const {
108 #if DCHECK_IS_ON()
109     DCHECK(needs_adopt_ref_);
110     needs_adopt_ref_ = false;
111 #endif
112   }
113 
114 #if DCHECK_IS_ON()
115   bool CalledOnValidSequence() const;
116 #endif
117 
118   mutable size_t ref_count_ = 0;
119 
120 #if DCHECK_IS_ON()
121   mutable bool needs_adopt_ref_ = false;
122   mutable bool in_dtor_ = false;
123   mutable SequenceChecker sequence_checker_;
124 #endif
125 
126   DFAKE_MUTEX(add_release_);
127 
128   DISALLOW_COPY_AND_ASSIGN(RefCountedBase);
129 };
130 
131 class BASE_EXPORT RefCountedThreadSafeBase {
132  public:
133   bool HasOneRef() const;
134 
135  protected:
RefCountedThreadSafeBase(StartRefCountFromZeroTag)136   explicit RefCountedThreadSafeBase(StartRefCountFromZeroTag) {}
RefCountedThreadSafeBase(StartRefCountFromOneTag)137   explicit RefCountedThreadSafeBase(StartRefCountFromOneTag) : ref_count_(1) {
138 #if DCHECK_IS_ON()
139     needs_adopt_ref_ = true;
140 #endif
141   }
142 
143   ~RefCountedThreadSafeBase();
144 
145   void AddRef() const;
146 
147   // Returns true if the object should self-delete.
148   bool Release() const;
149 
150  private:
151   template <typename U>
152   friend scoped_refptr<U> base::AdoptRef(U*);
153 
Adopted()154   void Adopted() const {
155 #if DCHECK_IS_ON()
156     DCHECK(needs_adopt_ref_);
157     needs_adopt_ref_ = false;
158 #endif
159   }
160 
161   mutable AtomicRefCount ref_count_ = 0;
162 #if DCHECK_IS_ON()
163   mutable bool needs_adopt_ref_ = false;
164   mutable bool in_dtor_ = false;
165 #endif
166 
167   DISALLOW_COPY_AND_ASSIGN(RefCountedThreadSafeBase);
168 };
169 
170 }  // namespace subtle
171 
172 // ScopedAllowCrossThreadRefCountAccess disables the check documented on
173 // RefCounted below for rare pre-existing use cases where thread-safety was
174 // guaranteed through other means (e.g. explicit sequencing of calls across
175 // execution sequences when bouncing between threads in order). New callers
176 // should refrain from using this (callsites handling thread-safety through
177 // locks should use RefCountedThreadSafe per the overhead of its atomics being
178 // negligible compared to locks anyways and callsites doing explicit sequencing
179 // should properly std::move() the ref to avoid hitting this check).
180 // TODO(tzik): Cleanup existing use cases and remove
181 // ScopedAllowCrossThreadRefCountAccess.
182 class BASE_EXPORT ScopedAllowCrossThreadRefCountAccess final {
183  public:
184 #if DCHECK_IS_ON()
185   ScopedAllowCrossThreadRefCountAccess();
186   ~ScopedAllowCrossThreadRefCountAccess();
187 #else
188   ScopedAllowCrossThreadRefCountAccess() {}
189   ~ScopedAllowCrossThreadRefCountAccess() {}
190 #endif
191 };
192 
193 //
194 // A base class for reference counted classes.  Otherwise, known as a cheap
195 // knock-off of WebKit's RefCounted<T> class.  To use this, just extend your
196 // class from it like so:
197 //
198 //   class MyFoo : public base::RefCounted<MyFoo> {
199 //    ...
200 //    private:
201 //     friend class base::RefCounted<MyFoo>;
202 //     ~MyFoo();
203 //   };
204 //
205 // You should always make your destructor non-public, to avoid any code deleting
206 // the object accidently while there are references to it.
207 //
208 //
209 // The ref count manipulation to RefCounted is NOT thread safe and has DCHECKs
210 // to trap unsafe cross thread usage. A subclass instance of RefCounted can be
211 // passed to another execution sequence only when its ref count is 1. If the ref
212 // count is more than 1, the RefCounted class verifies the ref updates are made
213 // on the same execution sequence as the previous ones.
214 //
215 //
216 // The reference count starts from zero by default, and we intended to migrate
217 // to start-from-one ref count. Put REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE() to
218 // the ref counted class to opt-in.
219 //
220 // If an object has start-from-one ref count, the first scoped_refptr need to be
221 // created by base::AdoptRef() or base::MakeShared(). We can use
222 // base::MakeShared() to create create both type of ref counted object.
223 //
224 // The motivations to use start-from-one ref count are:
225 //  - Start-from-one ref count doesn't need the ref count increment for the
226 //    first reference.
227 //  - It can detect an invalid object acquisition for a being-deleted object
228 //    that has zero ref count. That tends to happen on custom deleter that
229 //    delays the deletion.
230 //    TODO(tzik): Implement invalid acquisition detection.
231 //  - Behavior parity to Blink's WTF::RefCounted, whose count starts from one.
232 //    And start-from-one ref count is a step to merge WTF::RefCounted into
233 //    base::RefCounted.
234 //
235 #define REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE()             \
236   static constexpr ::base::subtle::StartRefCountFromOneTag \
237       kRefCountPreference = ::base::subtle::kStartRefCountFromOneTag
238 
239 template <class T>
240 class RefCounted : public subtle::RefCountedBase {
241  public:
242   static constexpr subtle::StartRefCountFromZeroTag kRefCountPreference =
243       subtle::kStartRefCountFromZeroTag;
244 
RefCounted()245   RefCounted() : subtle::RefCountedBase(T::kRefCountPreference) {}
246 
AddRef()247   void AddRef() const {
248     subtle::RefCountedBase::AddRef();
249   }
250 
Release()251   void Release() const {
252     if (subtle::RefCountedBase::Release()) {
253       delete static_cast<const T*>(this);
254     }
255   }
256 
257  protected:
258   ~RefCounted() = default;
259 
260  private:
261   DISALLOW_COPY_AND_ASSIGN(RefCounted);
262 };
263 
264 // Forward declaration.
265 template <class T, typename Traits> class RefCountedThreadSafe;
266 
267 // Default traits for RefCountedThreadSafe<T>.  Deletes the object when its ref
268 // count reaches 0.  Overload to delete it on a different thread etc.
269 template<typename T>
270 struct DefaultRefCountedThreadSafeTraits {
DestructDefaultRefCountedThreadSafeTraits271   static void Destruct(const T* x) {
272     // Delete through RefCountedThreadSafe to make child classes only need to be
273     // friend with RefCountedThreadSafe instead of this struct, which is an
274     // implementation detail.
275     RefCountedThreadSafe<T,
276                          DefaultRefCountedThreadSafeTraits>::DeleteInternal(x);
277   }
278 };
279 
280 //
281 // A thread-safe variant of RefCounted<T>
282 //
283 //   class MyFoo : public base::RefCountedThreadSafe<MyFoo> {
284 //    ...
285 //   };
286 //
287 // If you're using the default trait, then you should add compile time
288 // asserts that no one else is deleting your object.  i.e.
289 //    private:
290 //     friend class base::RefCountedThreadSafe<MyFoo>;
291 //     ~MyFoo();
292 //
293 // We can use REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE() with RefCountedThreadSafe
294 // too. See the comment above the RefCounted definition for details.
295 template <class T, typename Traits = DefaultRefCountedThreadSafeTraits<T> >
296 class RefCountedThreadSafe : public subtle::RefCountedThreadSafeBase {
297  public:
298   static constexpr subtle::StartRefCountFromZeroTag kRefCountPreference =
299       subtle::kStartRefCountFromZeroTag;
300 
RefCountedThreadSafe()301   explicit RefCountedThreadSafe()
302       : subtle::RefCountedThreadSafeBase(T::kRefCountPreference) {}
303 
AddRef()304   void AddRef() const {
305     subtle::RefCountedThreadSafeBase::AddRef();
306   }
307 
Release()308   void Release() const {
309     if (subtle::RefCountedThreadSafeBase::Release()) {
310       Traits::Destruct(static_cast<const T*>(this));
311     }
312   }
313 
314  protected:
315   ~RefCountedThreadSafe() = default;
316 
317  private:
318   friend struct DefaultRefCountedThreadSafeTraits<T>;
319   static void DeleteInternal(const T* x) { delete x; }
320 
321   DISALLOW_COPY_AND_ASSIGN(RefCountedThreadSafe);
322 };
323 
324 //
325 // A thread-safe wrapper for some piece of data so we can place other
326 // things in scoped_refptrs<>.
327 //
328 template<typename T>
329 class RefCountedData
330     : public base::RefCountedThreadSafe< base::RefCountedData<T> > {
331  public:
332   RefCountedData() : data() {}
333   RefCountedData(const T& in_value) : data(in_value) {}
334 
335   T data;
336 
337  private:
338   friend class base::RefCountedThreadSafe<base::RefCountedData<T> >;
339   ~RefCountedData() = default;
340 };
341 
342 // Creates a scoped_refptr from a raw pointer without incrementing the reference
343 // count. Use this only for a newly created object whose reference count starts
344 // from 1 instead of 0.
345 template <typename T>
346 scoped_refptr<T> AdoptRef(T* obj) {
347   using Tag = typename std::decay<decltype(T::kRefCountPreference)>::type;
348   static_assert(std::is_same<subtle::StartRefCountFromOneTag, Tag>::value,
349                 "Use AdoptRef only for the reference count starts from one.");
350 
351   DCHECK(obj);
352   DCHECK(obj->HasOneRef());
353   obj->Adopted();
354   return scoped_refptr<T>(obj, subtle::kAdoptRefTag);
355 }
356 
357 namespace subtle {
358 
359 template <typename T>
360 scoped_refptr<T> AdoptRefIfNeeded(T* obj, StartRefCountFromZeroTag) {
361   return scoped_refptr<T>(obj);
362 }
363 
364 template <typename T>
365 scoped_refptr<T> AdoptRefIfNeeded(T* obj, StartRefCountFromOneTag) {
366   return AdoptRef(obj);
367 }
368 
369 }  // namespace subtle
370 
371 // Constructs an instance of T, which is a ref counted type, and wraps the
372 // object into a scoped_refptr.
373 template <typename T, typename... Args>
374 scoped_refptr<T> MakeShared(Args&&... args) {
375   T* obj = new T(std::forward<Args>(args)...);
376   return subtle::AdoptRefIfNeeded(obj, T::kRefCountPreference);
377 }
378 
379 }  // namespace base
380 
381 //
382 // A smart pointer class for reference counted objects.  Use this class instead
383 // of calling AddRef and Release manually on a reference counted object to
384 // avoid common memory leaks caused by forgetting to Release an object
385 // reference.  Sample usage:
386 //
387 //   class MyFoo : public RefCounted<MyFoo> {
388 //    ...
389 //    private:
390 //     friend class RefCounted<MyFoo>;  // Allow destruction by RefCounted<>.
391 //     ~MyFoo();                        // Destructor must be private/protected.
392 //   };
393 //
394 //   void some_function() {
395 //     scoped_refptr<MyFoo> foo = new MyFoo();
396 //     foo->Method(param);
397 //     // |foo| is released when this function returns
398 //   }
399 //
400 //   void some_other_function() {
401 //     scoped_refptr<MyFoo> foo = new MyFoo();
402 //     ...
403 //     foo = nullptr;  // explicitly releases |foo|
404 //     ...
405 //     if (foo)
406 //       foo->Method(param);
407 //   }
408 //
409 // The above examples show how scoped_refptr<T> acts like a pointer to T.
410 // Given two scoped_refptr<T> classes, it is also possible to exchange
411 // references between the two objects, like so:
412 //
413 //   {
414 //     scoped_refptr<MyFoo> a = new MyFoo();
415 //     scoped_refptr<MyFoo> b;
416 //
417 //     b.swap(a);
418 //     // now, |b| references the MyFoo object, and |a| references nullptr.
419 //   }
420 //
421 // To make both |a| and |b| in the above example reference the same MyFoo
422 // object, simply use the assignment operator:
423 //
424 //   {
425 //     scoped_refptr<MyFoo> a = new MyFoo();
426 //     scoped_refptr<MyFoo> b;
427 //
428 //     b = a;
429 //     // now, |a| and |b| each own a reference to the same MyFoo object.
430 //   }
431 //
432 template <class T>
433 class scoped_refptr {
434  public:
435   typedef T element_type;
436 
437   scoped_refptr() {}
438 
439   scoped_refptr(T* p) : ptr_(p) {
440     if (ptr_)
441       AddRef(ptr_);
442   }
443 
444   // Copy constructor.
445   scoped_refptr(const scoped_refptr<T>& r) : ptr_(r.ptr_) {
446     if (ptr_)
447       AddRef(ptr_);
448   }
449 
450   // Copy conversion constructor.
451   template <typename U,
452             typename = typename std::enable_if<
453                 std::is_convertible<U*, T*>::value>::type>
454   scoped_refptr(const scoped_refptr<U>& r) : ptr_(r.get()) {
455     if (ptr_)
456       AddRef(ptr_);
457   }
458 
459   // Move constructor. This is required in addition to the conversion
460   // constructor below in order for clang to warn about pessimizing moves.
461   scoped_refptr(scoped_refptr&& r) : ptr_(r.get()) { r.ptr_ = nullptr; }
462 
463   // Move conversion constructor.
464   template <typename U,
465             typename = typename std::enable_if<
466                 std::is_convertible<U*, T*>::value>::type>
467   scoped_refptr(scoped_refptr<U>&& r) : ptr_(r.get()) {
468     r.ptr_ = nullptr;
469   }
470 
471   ~scoped_refptr() {
472     if (ptr_)
473       Release(ptr_);
474   }
475 
476   T* get() const { return ptr_; }
477 
478   T& operator*() const {
479     assert(ptr_ != nullptr);
480     return *ptr_;
481   }
482 
483   T* operator->() const {
484     assert(ptr_ != nullptr);
485     return ptr_;
486   }
487 
488   scoped_refptr<T>& operator=(T* p) {
489     // AddRef first so that self assignment should work
490     if (p)
491       AddRef(p);
492     T* old_ptr = ptr_;
493     ptr_ = p;
494     if (old_ptr)
495       Release(old_ptr);
496     return *this;
497   }
498 
499   scoped_refptr<T>& operator=(const scoped_refptr<T>& r) {
500     return *this = r.ptr_;
501   }
502 
503   template <typename U>
504   scoped_refptr<T>& operator=(const scoped_refptr<U>& r) {
505     return *this = r.get();
506   }
507 
508   scoped_refptr<T>& operator=(scoped_refptr<T>&& r) {
509     scoped_refptr<T>(std::move(r)).swap(*this);
510     return *this;
511   }
512 
513   template <typename U>
514   scoped_refptr<T>& operator=(scoped_refptr<U>&& r) {
515     scoped_refptr<T>(std::move(r)).swap(*this);
516     return *this;
517   }
518 
519   void swap(scoped_refptr<T>& r) {
520     T* tmp = ptr_;
521     ptr_ = r.ptr_;
522     r.ptr_ = tmp;
523   }
524 
525   explicit operator bool() const { return ptr_ != nullptr; }
526 
527   template <typename U>
528   bool operator==(const scoped_refptr<U>& rhs) const {
529     return ptr_ == rhs.get();
530   }
531 
532   template <typename U>
533   bool operator!=(const scoped_refptr<U>& rhs) const {
534     return !operator==(rhs);
535   }
536 
537   template <typename U>
538   bool operator<(const scoped_refptr<U>& rhs) const {
539     return ptr_ < rhs.get();
540   }
541 
542  protected:
543   T* ptr_ = nullptr;
544 
545  private:
546   template <typename U>
547   friend scoped_refptr<U> base::AdoptRef(U*);
548 
549   scoped_refptr(T* p, base::subtle::AdoptRefTag) : ptr_(p) {}
550 
551   // Friend required for move constructors that set r.ptr_ to null.
552   template <typename U>
553   friend class scoped_refptr;
554 
555   // Non-inline helpers to allow:
556   //     class Opaque;
557   //     extern template class scoped_refptr<Opaque>;
558   // Otherwise the compiler will complain that Opaque is an incomplete type.
559   static void AddRef(T* ptr);
560   static void Release(T* ptr);
561 };
562 
563 // static
564 template <typename T>
565 void scoped_refptr<T>::AddRef(T* ptr) {
566   ptr->AddRef();
567 }
568 
569 // static
570 template <typename T>
571 void scoped_refptr<T>::Release(T* ptr) {
572   ptr->Release();
573 }
574 
575 // Handy utility for creating a scoped_refptr<T> out of a T* explicitly without
576 // having to retype all the template arguments
577 template <typename T>
578 scoped_refptr<T> make_scoped_refptr(T* t) {
579   return scoped_refptr<T>(t);
580 }
581 
582 template <typename T, typename U>
583 bool operator==(const scoped_refptr<T>& lhs, const U* rhs) {
584   return lhs.get() == rhs;
585 }
586 
587 template <typename T, typename U>
588 bool operator==(const T* lhs, const scoped_refptr<U>& rhs) {
589   return lhs == rhs.get();
590 }
591 
592 template <typename T>
593 bool operator==(const scoped_refptr<T>& lhs, std::nullptr_t null) {
594   return !static_cast<bool>(lhs);
595 }
596 
597 template <typename T>
598 bool operator==(std::nullptr_t null, const scoped_refptr<T>& rhs) {
599   return !static_cast<bool>(rhs);
600 }
601 
602 template <typename T, typename U>
603 bool operator!=(const scoped_refptr<T>& lhs, const U* rhs) {
604   return !operator==(lhs, rhs);
605 }
606 
607 template <typename T, typename U>
608 bool operator!=(const T* lhs, const scoped_refptr<U>& rhs) {
609   return !operator==(lhs, rhs);
610 }
611 
612 template <typename T>
613 bool operator!=(const scoped_refptr<T>& lhs, std::nullptr_t null) {
614   return !operator==(lhs, null);
615 }
616 
617 template <typename T>
618 bool operator!=(std::nullptr_t null, const scoped_refptr<T>& rhs) {
619   return !operator==(null, rhs);
620 }
621 
622 template <typename T>
623 std::ostream& operator<<(std::ostream& out, const scoped_refptr<T>& p) {
624   return out << p.get();
625 }
626 
627 #endif  // BASE_MEMORY_REF_COUNTED_H_
628