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. |
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). |
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). |
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. |
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 | |