1 // Copyright 2013 The Flutter 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 // Provides a base class for reference-counted classes. 6 7 #ifndef FLUTTER_FML_MEMORY_REF_COUNTED_H_ 8 #define FLUTTER_FML_MEMORY_REF_COUNTED_H_ 9 10 #include "flutter/fml/macros.h" 11 #include "flutter/fml/memory/ref_counted_internal.h" 12 #include "flutter/fml/memory/ref_ptr.h" 13 14 namespace fml { 15 16 // A base class for (thread-safe) reference-counted classes. Use like: 17 // 18 // class Foo : public RefCountedThreadSafe<Foo> { 19 // ... 20 // }; 21 // 22 // |~Foo()| *may* be made private (e.g., to avoid accidental deletion of objects 23 // while there are still references to them), |Foo| should friend 24 // |RefCountedThreadSafe<Foo>|; use |FML_FRIEND_REF_COUNTED_THREAD_SAFE()| 25 // for this: 26 // 27 // class Foo : public RefCountedThreadSafe<Foo> { 28 // ... 29 // private: 30 // FML_FRIEND_REF_COUNTED_THREAD_SAFE(Foo); 31 // ~Foo(); 32 // ... 33 // }; 34 // 35 // Similarly, |Foo(...)| may be made private. In this case, there should either 36 // be a static factory method performing the requisite adoption: 37 // 38 // class Foo : public RefCountedThreadSafe<Foo> { 39 // ... 40 // public: 41 // inline static RefPtr<Foo> Create() { return AdoptRef(new Foo()); } 42 // ... 43 // private: 44 // Foo(); 45 // ... 46 // }; 47 // 48 // Or, to allow |MakeRefCounted()| to be used, use 49 // |FML_FRIEND_MAKE_REF_COUNTED()|: 50 // 51 // class Foo : public RefCountedThreadSafe<Foo> { 52 // ... 53 // private: 54 // FML_FRIEND_MAKE_REF_COUNTED(Foo); 55 // Foo(); 56 // Foo(const Bar& bar, bool maybe); 57 // ... 58 // }; 59 // 60 // For now, we only have thread-safe reference counting, since that's all we 61 // need. It's easy enough to add thread-unsafe versions if necessary. 62 template <typename T> 63 class RefCountedThreadSafe : public internal::RefCountedThreadSafeBase { 64 public: 65 // Adds a reference to this object. 66 // Inherited from the internal superclass: 67 // void AddRef() const; 68 69 // Releases a reference to this object. This will destroy this object once the 70 // last reference is released. Release()71 void Release() const { 72 if (internal::RefCountedThreadSafeBase::Release()) 73 delete static_cast<const T*>(this); 74 } 75 76 // Returns true if there is exactly one reference to this object. Use of this 77 // is subtle, and should usually be avoided. To assert that there is only one 78 // reference (typically held by the calling thread, possibly in a local 79 // variable), use |AssertHasOneRef()| instead. However, a use is: 80 // 81 // if (foo->HasOneRef()) { 82 // // Do something "fast", since |foo| is the only reference and no other 83 // // thread can get another reference. 84 // ... 85 // } else { 86 // // Do something slower, but still valid even if there were only one 87 // // reference. 88 // ... 89 // } 90 // 91 // Inherited from the internal superclass: 92 // bool HasOneRef(); 93 94 // Asserts that there is exactly one reference to this object; does nothing in 95 // Release builds (when |NDEBUG| is defined). 96 // Inherited from the internal superclass: 97 // void AssertHasOneRef(); 98 99 protected: 100 // Constructor. Note that the object is constructed with a reference count of 101 // 1, and then must be adopted (see |AdoptRef()| in ref_ptr.h). RefCountedThreadSafe()102 RefCountedThreadSafe() {} 103 104 // Destructor. Note that this object should only be destroyed via |Release()| 105 // (see above), or something that calls |Release()| (see, e.g., |RefPtr<>| in 106 // ref_ptr.h). ~RefCountedThreadSafe()107 ~RefCountedThreadSafe() {} 108 109 private: 110 #ifndef NDEBUG 111 template <typename U> 112 friend RefPtr<U> AdoptRef(U*); 113 // Marks the initial reference (assumed on construction) as adopted. This is 114 // only required for Debug builds (when |NDEBUG| is not defined). 115 // TODO(vtl): Should this really be private? This makes manual ref-counting 116 // and also writing one's own ref pointer class impossible. Adopt()117 void Adopt() { internal::RefCountedThreadSafeBase::Adopt(); } 118 #endif 119 120 FML_DISALLOW_COPY_AND_ASSIGN(RefCountedThreadSafe); 121 }; 122 123 // If you subclass |RefCountedThreadSafe| and want to keep your destructor 124 // private, use this. (See the example above |RefCountedThreadSafe|.) 125 #define FML_FRIEND_REF_COUNTED_THREAD_SAFE(T) \ 126 friend class ::fml::RefCountedThreadSafe<T> 127 128 // If you want to keep your constructor(s) private and still want to use 129 // |MakeRefCounted<T>()|, use this. (See the example above 130 // |RefCountedThreadSafe|.) 131 #define FML_FRIEND_MAKE_REF_COUNTED(T) \ 132 friend class ::fml::internal::MakeRefCountedHelper<T> 133 134 } // namespace fml 135 136 #endif // FLUTTER_FML_MEMORY_REF_COUNTED_H_ 137