|
1 |
|
2 /* |
|
3 * Copyright 2006 The Android Open Source Project |
|
4 * |
|
5 * Use of this source code is governed by a BSD-style license that can be |
|
6 * found in the LICENSE file. |
|
7 */ |
|
8 |
|
9 |
|
10 #ifndef SkRefCnt_DEFINED |
|
11 #define SkRefCnt_DEFINED |
|
12 |
|
13 #include "SkDynamicAnnotations.h" |
|
14 #include "SkThread.h" |
|
15 #include "SkInstCnt.h" |
|
16 #include "SkTemplates.h" |
|
17 |
|
18 /** \class SkRefCntBase |
|
19 |
|
20 SkRefCntBase is the base class for objects that may be shared by multiple |
|
21 objects. When an existing owner wants to share a reference, it calls ref(). |
|
22 When an owner wants to release its reference, it calls unref(). When the |
|
23 shared object's reference count goes to zero as the result of an unref() |
|
24 call, its (virtual) destructor is called. It is an error for the |
|
25 destructor to be called explicitly (or via the object going out of scope on |
|
26 the stack or calling delete) if getRefCnt() > 1. |
|
27 */ |
|
28 class SK_API SkRefCntBase : public SkNoncopyable { |
|
29 public: |
|
30 SK_DECLARE_INST_COUNT_ROOT(SkRefCntBase) |
|
31 |
|
32 /** Default construct, initializing the reference count to 1. |
|
33 */ |
|
34 SkRefCntBase() : fRefCnt(1) {} |
|
35 |
|
36 /** Destruct, asserting that the reference count is 1. |
|
37 */ |
|
38 virtual ~SkRefCntBase() { |
|
39 #ifdef SK_DEBUG |
|
40 SkASSERT(fRefCnt == 1); |
|
41 fRefCnt = 0; // illegal value, to catch us if we reuse after delete |
|
42 #endif |
|
43 } |
|
44 |
|
45 /** Return the reference count. Use only for debugging. */ |
|
46 int32_t getRefCnt() const { return fRefCnt; } |
|
47 |
|
48 /** May return true if the caller is the only owner. |
|
49 * Ensures that all previous owner's actions are complete. |
|
50 */ |
|
51 bool unique() const { |
|
52 // We believe we're reading fRefCnt in a safe way here, so we stifle the TSAN warning about |
|
53 // an unproctected read. Generally, don't read fRefCnt, and don't stifle this warning. |
|
54 bool const unique = (1 == SK_ANNOTATE_UNPROTECTED_READ(fRefCnt)); |
|
55 if (unique) { |
|
56 // Acquire barrier (L/SL), if not provided by load of fRefCnt. |
|
57 // Prevents user's 'unique' code from happening before decrements. |
|
58 //TODO: issue the barrier. |
|
59 } |
|
60 return unique; |
|
61 } |
|
62 |
|
63 /** Increment the reference count. Must be balanced by a call to unref(). |
|
64 */ |
|
65 void ref() const { |
|
66 SkASSERT(fRefCnt > 0); |
|
67 sk_atomic_inc(&fRefCnt); // No barrier required. |
|
68 } |
|
69 |
|
70 /** Decrement the reference count. If the reference count is 1 before the |
|
71 decrement, then delete the object. Note that if this is the case, then |
|
72 the object needs to have been allocated via new, and not on the stack. |
|
73 */ |
|
74 void unref() const { |
|
75 SkASSERT(fRefCnt > 0); |
|
76 // Release barrier (SL/S), if not provided below. |
|
77 if (sk_atomic_dec(&fRefCnt) == 1) { |
|
78 // Acquire barrier (L/SL), if not provided above. |
|
79 // Prevents code in dispose from happening before the decrement. |
|
80 sk_membar_acquire__after_atomic_dec(); |
|
81 internal_dispose(); |
|
82 } |
|
83 } |
|
84 |
|
85 #ifdef SK_DEBUG |
|
86 void validate() const { |
|
87 SkASSERT(fRefCnt > 0); |
|
88 } |
|
89 #endif |
|
90 |
|
91 protected: |
|
92 /** |
|
93 * Allow subclasses to call this if they've overridden internal_dispose |
|
94 * so they can reset fRefCnt before the destructor is called. Should only |
|
95 * be called right before calling through to inherited internal_dispose() |
|
96 * or before calling the destructor. |
|
97 */ |
|
98 void internal_dispose_restore_refcnt_to_1() const { |
|
99 #ifdef SK_DEBUG |
|
100 SkASSERT(0 == fRefCnt); |
|
101 fRefCnt = 1; |
|
102 #endif |
|
103 } |
|
104 |
|
105 private: |
|
106 /** |
|
107 * Called when the ref count goes to 0. |
|
108 */ |
|
109 virtual void internal_dispose() const { |
|
110 this->internal_dispose_restore_refcnt_to_1(); |
|
111 SkDELETE(this); |
|
112 } |
|
113 |
|
114 // The following friends are those which override internal_dispose() |
|
115 // and conditionally call SkRefCnt::internal_dispose(). |
|
116 friend class GrTexture; |
|
117 friend class SkWeakRefCnt; |
|
118 |
|
119 mutable int32_t fRefCnt; |
|
120 |
|
121 typedef SkNoncopyable INHERITED; |
|
122 }; |
|
123 |
|
124 #ifdef SK_REF_CNT_MIXIN_INCLUDE |
|
125 // It is the responsibility of the following include to define the type SkRefCnt. |
|
126 // This SkRefCnt should normally derive from SkRefCntBase. |
|
127 #include SK_REF_CNT_MIXIN_INCLUDE |
|
128 #else |
|
129 class SK_API SkRefCnt : public SkRefCntBase { }; |
|
130 #endif |
|
131 |
|
132 /////////////////////////////////////////////////////////////////////////////// |
|
133 |
|
134 /** Helper macro to safely assign one SkRefCnt[TS]* to another, checking for |
|
135 null in on each side of the assignment, and ensuring that ref() is called |
|
136 before unref(), in case the two pointers point to the same object. |
|
137 */ |
|
138 #define SkRefCnt_SafeAssign(dst, src) \ |
|
139 do { \ |
|
140 if (src) src->ref(); \ |
|
141 if (dst) dst->unref(); \ |
|
142 dst = src; \ |
|
143 } while (0) |
|
144 |
|
145 |
|
146 /** Call obj->ref() and return obj. The obj must not be NULL. |
|
147 */ |
|
148 template <typename T> static inline T* SkRef(T* obj) { |
|
149 SkASSERT(obj); |
|
150 obj->ref(); |
|
151 return obj; |
|
152 } |
|
153 |
|
154 /** Check if the argument is non-null, and if so, call obj->ref() and return obj. |
|
155 */ |
|
156 template <typename T> static inline T* SkSafeRef(T* obj) { |
|
157 if (obj) { |
|
158 obj->ref(); |
|
159 } |
|
160 return obj; |
|
161 } |
|
162 |
|
163 /** Check if the argument is non-null, and if so, call obj->unref() |
|
164 */ |
|
165 template <typename T> static inline void SkSafeUnref(T* obj) { |
|
166 if (obj) { |
|
167 obj->unref(); |
|
168 } |
|
169 } |
|
170 |
|
171 template<typename T> static inline void SkSafeSetNull(T*& obj) { |
|
172 if (NULL != obj) { |
|
173 obj->unref(); |
|
174 obj = NULL; |
|
175 } |
|
176 } |
|
177 |
|
178 /////////////////////////////////////////////////////////////////////////////// |
|
179 |
|
180 /** |
|
181 * Utility class that simply unref's its argument in the destructor. |
|
182 */ |
|
183 template <typename T> class SkAutoTUnref : SkNoncopyable { |
|
184 public: |
|
185 explicit SkAutoTUnref(T* obj = NULL) : fObj(obj) {} |
|
186 ~SkAutoTUnref() { SkSafeUnref(fObj); } |
|
187 |
|
188 T* get() const { return fObj; } |
|
189 |
|
190 T* reset(T* obj) { |
|
191 SkSafeUnref(fObj); |
|
192 fObj = obj; |
|
193 return obj; |
|
194 } |
|
195 |
|
196 void swap(SkAutoTUnref* other) { |
|
197 T* tmp = fObj; |
|
198 fObj = other->fObj; |
|
199 other->fObj = tmp; |
|
200 } |
|
201 |
|
202 /** |
|
203 * Return the hosted object (which may be null), transferring ownership. |
|
204 * The reference count is not modified, and the internal ptr is set to NULL |
|
205 * so unref() will not be called in our destructor. A subsequent call to |
|
206 * detach() will do nothing and return null. |
|
207 */ |
|
208 T* detach() { |
|
209 T* obj = fObj; |
|
210 fObj = NULL; |
|
211 return obj; |
|
212 } |
|
213 |
|
214 /** |
|
215 * BlockRef<B> is a type which inherits from B, cannot be created, |
|
216 * cannot be deleted, and makes ref and unref private. |
|
217 */ |
|
218 template<typename B> class BlockRef : public B { |
|
219 private: |
|
220 BlockRef(); |
|
221 ~BlockRef(); |
|
222 void ref() const; |
|
223 void unref() const; |
|
224 }; |
|
225 |
|
226 /** If T is const, the type returned from operator-> will also be const. */ |
|
227 typedef typename SkTConstType<BlockRef<T>, SkTIsConst<T>::value>::type BlockRefType; |
|
228 |
|
229 /** |
|
230 * SkAutoTUnref assumes ownership of the ref. As a result, it is an error |
|
231 * for the user to ref or unref through SkAutoTUnref. Therefore |
|
232 * SkAutoTUnref::operator-> returns BlockRef<T>*. This prevents use of |
|
233 * skAutoTUnrefInstance->ref() and skAutoTUnrefInstance->unref(). |
|
234 */ |
|
235 BlockRefType *operator->() const { |
|
236 return static_cast<BlockRefType*>(fObj); |
|
237 } |
|
238 operator T*() { return fObj; } |
|
239 |
|
240 private: |
|
241 T* fObj; |
|
242 }; |
|
243 // Can't use the #define trick below to guard a bare SkAutoTUnref(...) because it's templated. :( |
|
244 |
|
245 class SkAutoUnref : public SkAutoTUnref<SkRefCnt> { |
|
246 public: |
|
247 SkAutoUnref(SkRefCnt* obj) : SkAutoTUnref<SkRefCnt>(obj) {} |
|
248 }; |
|
249 #define SkAutoUnref(...) SK_REQUIRE_LOCAL_VAR(SkAutoUnref) |
|
250 |
|
251 class SkAutoRef : SkNoncopyable { |
|
252 public: |
|
253 SkAutoRef(SkRefCnt* obj) : fObj(obj) { SkSafeRef(obj); } |
|
254 ~SkAutoRef() { SkSafeUnref(fObj); } |
|
255 private: |
|
256 SkRefCnt* fObj; |
|
257 }; |
|
258 #define SkAutoRef(...) SK_REQUIRE_LOCAL_VAR(SkAutoRef) |
|
259 |
|
260 /** Wrapper class for SkRefCnt pointers. This manages ref/unref of a pointer to |
|
261 a SkRefCnt (or subclass) object. |
|
262 */ |
|
263 template <typename T> class SkRefPtr { |
|
264 public: |
|
265 SkRefPtr() : fObj(NULL) {} |
|
266 SkRefPtr(T* obj) : fObj(obj) { SkSafeRef(fObj); } |
|
267 SkRefPtr(const SkRefPtr& o) : fObj(o.fObj) { SkSafeRef(fObj); } |
|
268 ~SkRefPtr() { SkSafeUnref(fObj); } |
|
269 |
|
270 SkRefPtr& operator=(const SkRefPtr& rp) { |
|
271 SkRefCnt_SafeAssign(fObj, rp.fObj); |
|
272 return *this; |
|
273 } |
|
274 SkRefPtr& operator=(T* obj) { |
|
275 SkRefCnt_SafeAssign(fObj, obj); |
|
276 return *this; |
|
277 } |
|
278 |
|
279 T* get() const { return fObj; } |
|
280 T& operator*() const { return *fObj; } |
|
281 T* operator->() const { return fObj; } |
|
282 |
|
283 typedef T* SkRefPtr::*unspecified_bool_type; |
|
284 operator unspecified_bool_type() const { |
|
285 return fObj ? &SkRefPtr::fObj : NULL; |
|
286 } |
|
287 |
|
288 private: |
|
289 T* fObj; |
|
290 }; |
|
291 |
|
292 #endif |