|
1 /* |
|
2 * Copyright (C) 2005 The Android Open Source Project |
|
3 * |
|
4 * Licensed under the Apache License, Version 2.0 (the "License"); |
|
5 * you may not use this file except in compliance with the License. |
|
6 * You may obtain a copy of the License at |
|
7 * |
|
8 * http://www.apache.org/licenses/LICENSE-2.0 |
|
9 * |
|
10 * Unless required by applicable law or agreed to in writing, software |
|
11 * distributed under the License is distributed on an "AS IS" BASIS, |
|
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
13 * See the License for the specific language governing permissions and |
|
14 * limitations under the License. |
|
15 */ |
|
16 |
|
17 #ifndef ANDROID_REF_BASE_H |
|
18 #define ANDROID_REF_BASE_H |
|
19 |
|
20 #include <cutils/atomic.h> |
|
21 #include <utils/TextOutput.h> |
|
22 |
|
23 #include <stdint.h> |
|
24 #include <sys/types.h> |
|
25 #include <stdlib.h> |
|
26 |
|
27 // --------------------------------------------------------------------------- |
|
28 namespace android { |
|
29 |
|
30 template<typename T> class wp; |
|
31 |
|
32 // --------------------------------------------------------------------------- |
|
33 |
|
34 #define COMPARE(_op_) \ |
|
35 inline bool operator _op_ (const sp<T>& o) const { \ |
|
36 return m_ptr _op_ o.m_ptr; \ |
|
37 } \ |
|
38 inline bool operator _op_ (const wp<T>& o) const { \ |
|
39 return m_ptr _op_ o.m_ptr; \ |
|
40 } \ |
|
41 inline bool operator _op_ (const T* o) const { \ |
|
42 return m_ptr _op_ o; \ |
|
43 } \ |
|
44 template<typename U> \ |
|
45 inline bool operator _op_ (const sp<U>& o) const { \ |
|
46 return m_ptr _op_ o.m_ptr; \ |
|
47 } \ |
|
48 template<typename U> \ |
|
49 inline bool operator _op_ (const wp<U>& o) const { \ |
|
50 return m_ptr _op_ o.m_ptr; \ |
|
51 } \ |
|
52 template<typename U> \ |
|
53 inline bool operator _op_ (const U* o) const { \ |
|
54 return m_ptr _op_ o; \ |
|
55 } |
|
56 |
|
57 // --------------------------------------------------------------------------- |
|
58 |
|
59 class RefBase |
|
60 { |
|
61 public: |
|
62 void incStrong(const void* id) const; |
|
63 void decStrong(const void* id) const; |
|
64 |
|
65 void forceIncStrong(const void* id) const; |
|
66 |
|
67 //! DEBUGGING ONLY: Get current strong ref count. |
|
68 int32_t getStrongCount() const; |
|
69 |
|
70 class weakref_type |
|
71 { |
|
72 public: |
|
73 RefBase* refBase() const; |
|
74 |
|
75 void incWeak(const void* id); |
|
76 void decWeak(const void* id); |
|
77 |
|
78 bool attemptIncStrong(const void* id); |
|
79 |
|
80 //! This is only safe if you have set OBJECT_LIFETIME_FOREVER. |
|
81 bool attemptIncWeak(const void* id); |
|
82 |
|
83 //! DEBUGGING ONLY: Get current weak ref count. |
|
84 int32_t getWeakCount() const; |
|
85 |
|
86 //! DEBUGGING ONLY: Print references held on object. |
|
87 void printRefs() const; |
|
88 |
|
89 //! DEBUGGING ONLY: Enable tracking for this object. |
|
90 // enable -- enable/disable tracking |
|
91 // retain -- when tracking is enable, if true, then we save a stack trace |
|
92 // for each reference and dereference; when retain == false, we |
|
93 // match up references and dereferences and keep only the |
|
94 // outstanding ones. |
|
95 |
|
96 void trackMe(bool enable, bool retain); |
|
97 }; |
|
98 |
|
99 weakref_type* createWeak(const void* id) const; |
|
100 |
|
101 weakref_type* getWeakRefs() const; |
|
102 |
|
103 //! DEBUGGING ONLY: Print references held on object. |
|
104 inline void printRefs() const { getWeakRefs()->printRefs(); } |
|
105 |
|
106 //! DEBUGGING ONLY: Enable tracking of object. |
|
107 inline void trackMe(bool enable, bool retain) |
|
108 { |
|
109 getWeakRefs()->trackMe(enable, retain); |
|
110 } |
|
111 |
|
112 protected: |
|
113 RefBase(); |
|
114 virtual ~RefBase(); |
|
115 |
|
116 //! Flags for extendObjectLifetime() |
|
117 enum { |
|
118 OBJECT_LIFETIME_WEAK = 0x0001, |
|
119 OBJECT_LIFETIME_FOREVER = 0x0003 |
|
120 }; |
|
121 |
|
122 void extendObjectLifetime(int32_t mode); |
|
123 |
|
124 //! Flags for onIncStrongAttempted() |
|
125 enum { |
|
126 FIRST_INC_STRONG = 0x0001 |
|
127 }; |
|
128 |
|
129 virtual void onFirstRef(); |
|
130 virtual void onLastStrongRef(const void* id); |
|
131 virtual bool onIncStrongAttempted(uint32_t flags, const void* id); |
|
132 virtual void onLastWeakRef(const void* id); |
|
133 |
|
134 private: |
|
135 friend class weakref_type; |
|
136 class weakref_impl; |
|
137 |
|
138 RefBase(const RefBase& o); |
|
139 RefBase& operator=(const RefBase& o); |
|
140 |
|
141 weakref_impl* const mRefs; |
|
142 }; |
|
143 |
|
144 // --------------------------------------------------------------------------- |
|
145 |
|
146 template <class T> |
|
147 class LightRefBase |
|
148 { |
|
149 public: |
|
150 inline LightRefBase() : mCount(0) { } |
|
151 inline void incStrong(const void* id) const { |
|
152 android_atomic_inc(&mCount); |
|
153 } |
|
154 inline void decStrong(const void* id) const { |
|
155 if (android_atomic_dec(&mCount) == 1) { |
|
156 delete static_cast<const T*>(this); |
|
157 } |
|
158 } |
|
159 //! DEBUGGING ONLY: Get current strong ref count. |
|
160 inline int32_t getStrongCount() const { |
|
161 return mCount; |
|
162 } |
|
163 |
|
164 protected: |
|
165 inline ~LightRefBase() { } |
|
166 |
|
167 private: |
|
168 mutable volatile int32_t mCount; |
|
169 }; |
|
170 |
|
171 // --------------------------------------------------------------------------- |
|
172 |
|
173 template <typename T> |
|
174 class sp |
|
175 { |
|
176 public: |
|
177 typedef typename RefBase::weakref_type weakref_type; |
|
178 |
|
179 inline sp() : m_ptr(0) { } |
|
180 |
|
181 sp(T* other); |
|
182 sp(const sp<T>& other); |
|
183 template<typename U> sp(U* other); |
|
184 template<typename U> sp(const sp<U>& other); |
|
185 |
|
186 ~sp(); |
|
187 |
|
188 // Assignment |
|
189 |
|
190 sp& operator = (T* other); |
|
191 sp& operator = (const sp<T>& other); |
|
192 |
|
193 template<typename U> sp& operator = (const sp<U>& other); |
|
194 template<typename U> sp& operator = (U* other); |
|
195 |
|
196 //! Special optimization for use by ProcessState (and nobody else). |
|
197 void force_set(T* other); |
|
198 |
|
199 // Reset |
|
200 |
|
201 void clear(); |
|
202 |
|
203 // Accessors |
|
204 |
|
205 inline T& operator* () const { return *m_ptr; } |
|
206 inline T* operator-> () const { return m_ptr; } |
|
207 inline T* get() const { return m_ptr; } |
|
208 |
|
209 // Operators |
|
210 |
|
211 COMPARE(==) |
|
212 COMPARE(!=) |
|
213 COMPARE(>) |
|
214 COMPARE(<) |
|
215 COMPARE(<=) |
|
216 COMPARE(>=) |
|
217 |
|
218 private: |
|
219 template<typename Y> friend class sp; |
|
220 template<typename Y> friend class wp; |
|
221 |
|
222 // Optimization for wp::promote(). |
|
223 sp(T* p, weakref_type* refs); |
|
224 |
|
225 T* m_ptr; |
|
226 }; |
|
227 |
|
228 template <typename T> |
|
229 TextOutput& operator<<(TextOutput& to, const sp<T>& val); |
|
230 |
|
231 // --------------------------------------------------------------------------- |
|
232 |
|
233 template <typename T> |
|
234 class wp |
|
235 { |
|
236 public: |
|
237 typedef typename RefBase::weakref_type weakref_type; |
|
238 |
|
239 inline wp() : m_ptr(0) { } |
|
240 |
|
241 wp(T* other); |
|
242 wp(const wp<T>& other); |
|
243 wp(const sp<T>& other); |
|
244 template<typename U> wp(U* other); |
|
245 template<typename U> wp(const sp<U>& other); |
|
246 template<typename U> wp(const wp<U>& other); |
|
247 |
|
248 ~wp(); |
|
249 |
|
250 // Assignment |
|
251 |
|
252 wp& operator = (T* other); |
|
253 wp& operator = (const wp<T>& other); |
|
254 wp& operator = (const sp<T>& other); |
|
255 |
|
256 template<typename U> wp& operator = (U* other); |
|
257 template<typename U> wp& operator = (const wp<U>& other); |
|
258 template<typename U> wp& operator = (const sp<U>& other); |
|
259 |
|
260 void set_object_and_refs(T* other, weakref_type* refs); |
|
261 |
|
262 // promotion to sp |
|
263 |
|
264 sp<T> promote() const; |
|
265 |
|
266 // Reset |
|
267 |
|
268 void clear(); |
|
269 |
|
270 // Accessors |
|
271 |
|
272 inline weakref_type* get_refs() const { return m_refs; } |
|
273 |
|
274 inline T* unsafe_get() const { return m_ptr; } |
|
275 |
|
276 // Operators |
|
277 |
|
278 COMPARE(==) |
|
279 COMPARE(!=) |
|
280 COMPARE(>) |
|
281 COMPARE(<) |
|
282 COMPARE(<=) |
|
283 COMPARE(>=) |
|
284 |
|
285 private: |
|
286 template<typename Y> friend class sp; |
|
287 template<typename Y> friend class wp; |
|
288 |
|
289 T* m_ptr; |
|
290 weakref_type* m_refs; |
|
291 }; |
|
292 |
|
293 template <typename T> |
|
294 TextOutput& operator<<(TextOutput& to, const wp<T>& val); |
|
295 |
|
296 #undef COMPARE |
|
297 |
|
298 // --------------------------------------------------------------------------- |
|
299 // No user serviceable parts below here. |
|
300 |
|
301 template<typename T> |
|
302 sp<T>::sp(T* other) |
|
303 : m_ptr(other) |
|
304 { |
|
305 if (other) other->incStrong(this); |
|
306 } |
|
307 |
|
308 template<typename T> |
|
309 sp<T>::sp(const sp<T>& other) |
|
310 : m_ptr(other.m_ptr) |
|
311 { |
|
312 if (m_ptr) m_ptr->incStrong(this); |
|
313 } |
|
314 |
|
315 template<typename T> template<typename U> |
|
316 sp<T>::sp(U* other) : m_ptr(other) |
|
317 { |
|
318 if (other) other->incStrong(this); |
|
319 } |
|
320 |
|
321 template<typename T> template<typename U> |
|
322 sp<T>::sp(const sp<U>& other) |
|
323 : m_ptr(other.m_ptr) |
|
324 { |
|
325 if (m_ptr) m_ptr->incStrong(this); |
|
326 } |
|
327 |
|
328 template<typename T> |
|
329 sp<T>::~sp() |
|
330 { |
|
331 if (m_ptr) m_ptr->decStrong(this); |
|
332 } |
|
333 |
|
334 template<typename T> |
|
335 sp<T>& sp<T>::operator = (const sp<T>& other) { |
|
336 if (other.m_ptr) other.m_ptr->incStrong(this); |
|
337 if (m_ptr) m_ptr->decStrong(this); |
|
338 m_ptr = other.m_ptr; |
|
339 return *this; |
|
340 } |
|
341 |
|
342 template<typename T> |
|
343 sp<T>& sp<T>::operator = (T* other) |
|
344 { |
|
345 if (other) other->incStrong(this); |
|
346 if (m_ptr) m_ptr->decStrong(this); |
|
347 m_ptr = other; |
|
348 return *this; |
|
349 } |
|
350 |
|
351 template<typename T> template<typename U> |
|
352 sp<T>& sp<T>::operator = (const sp<U>& other) |
|
353 { |
|
354 if (other.m_ptr) other.m_ptr->incStrong(this); |
|
355 if (m_ptr) m_ptr->decStrong(this); |
|
356 m_ptr = other.m_ptr; |
|
357 return *this; |
|
358 } |
|
359 |
|
360 template<typename T> template<typename U> |
|
361 sp<T>& sp<T>::operator = (U* other) |
|
362 { |
|
363 if (other) other->incStrong(this); |
|
364 if (m_ptr) m_ptr->decStrong(this); |
|
365 m_ptr = other; |
|
366 return *this; |
|
367 } |
|
368 |
|
369 template<typename T> |
|
370 void sp<T>::force_set(T* other) |
|
371 { |
|
372 other->forceIncStrong(this); |
|
373 m_ptr = other; |
|
374 } |
|
375 |
|
376 template<typename T> |
|
377 void sp<T>::clear() |
|
378 { |
|
379 if (m_ptr) { |
|
380 m_ptr->decStrong(this); |
|
381 m_ptr = 0; |
|
382 } |
|
383 } |
|
384 |
|
385 template<typename T> |
|
386 sp<T>::sp(T* p, weakref_type* refs) |
|
387 : m_ptr((p && refs->attemptIncStrong(this)) ? p : 0) |
|
388 { |
|
389 } |
|
390 |
|
391 template <typename T> |
|
392 inline TextOutput& operator<<(TextOutput& to, const sp<T>& val) |
|
393 { |
|
394 to << "sp<>(" << val.get() << ")"; |
|
395 return to; |
|
396 } |
|
397 |
|
398 // --------------------------------------------------------------------------- |
|
399 |
|
400 template<typename T> |
|
401 wp<T>::wp(T* other) |
|
402 : m_ptr(other) |
|
403 { |
|
404 if (other) m_refs = other->createWeak(this); |
|
405 } |
|
406 |
|
407 template<typename T> |
|
408 wp<T>::wp(const wp<T>& other) |
|
409 : m_ptr(other.m_ptr), m_refs(other.m_refs) |
|
410 { |
|
411 if (m_ptr) m_refs->incWeak(this); |
|
412 } |
|
413 |
|
414 template<typename T> |
|
415 wp<T>::wp(const sp<T>& other) |
|
416 : m_ptr(other.m_ptr) |
|
417 { |
|
418 if (m_ptr) { |
|
419 m_refs = m_ptr->createWeak(this); |
|
420 } |
|
421 } |
|
422 |
|
423 template<typename T> template<typename U> |
|
424 wp<T>::wp(U* other) |
|
425 : m_ptr(other) |
|
426 { |
|
427 if (other) m_refs = other->createWeak(this); |
|
428 } |
|
429 |
|
430 template<typename T> template<typename U> |
|
431 wp<T>::wp(const wp<U>& other) |
|
432 : m_ptr(other.m_ptr) |
|
433 { |
|
434 if (m_ptr) { |
|
435 m_refs = other.m_refs; |
|
436 m_refs->incWeak(this); |
|
437 } |
|
438 } |
|
439 |
|
440 template<typename T> template<typename U> |
|
441 wp<T>::wp(const sp<U>& other) |
|
442 : m_ptr(other.m_ptr) |
|
443 { |
|
444 if (m_ptr) { |
|
445 m_refs = m_ptr->createWeak(this); |
|
446 } |
|
447 } |
|
448 |
|
449 template<typename T> |
|
450 wp<T>::~wp() |
|
451 { |
|
452 if (m_ptr) m_refs->decWeak(this); |
|
453 } |
|
454 |
|
455 template<typename T> |
|
456 wp<T>& wp<T>::operator = (T* other) |
|
457 { |
|
458 weakref_type* newRefs = |
|
459 other ? other->createWeak(this) : 0; |
|
460 if (m_ptr) m_refs->decWeak(this); |
|
461 m_ptr = other; |
|
462 m_refs = newRefs; |
|
463 return *this; |
|
464 } |
|
465 |
|
466 template<typename T> |
|
467 wp<T>& wp<T>::operator = (const wp<T>& other) |
|
468 { |
|
469 if (other.m_ptr) other.m_refs->incWeak(this); |
|
470 if (m_ptr) m_refs->decWeak(this); |
|
471 m_ptr = other.m_ptr; |
|
472 m_refs = other.m_refs; |
|
473 return *this; |
|
474 } |
|
475 |
|
476 template<typename T> |
|
477 wp<T>& wp<T>::operator = (const sp<T>& other) |
|
478 { |
|
479 weakref_type* newRefs = |
|
480 other != NULL ? other->createWeak(this) : 0; |
|
481 if (m_ptr) m_refs->decWeak(this); |
|
482 m_ptr = other.get(); |
|
483 m_refs = newRefs; |
|
484 return *this; |
|
485 } |
|
486 |
|
487 template<typename T> template<typename U> |
|
488 wp<T>& wp<T>::operator = (U* other) |
|
489 { |
|
490 weakref_type* newRefs = |
|
491 other ? other->createWeak(this) : 0; |
|
492 if (m_ptr) m_refs->decWeak(this); |
|
493 m_ptr = other; |
|
494 m_refs = newRefs; |
|
495 return *this; |
|
496 } |
|
497 |
|
498 template<typename T> template<typename U> |
|
499 wp<T>& wp<T>::operator = (const wp<U>& other) |
|
500 { |
|
501 if (other.m_ptr) other.m_refs->incWeak(this); |
|
502 if (m_ptr) m_refs->decWeak(this); |
|
503 m_ptr = other.m_ptr; |
|
504 m_refs = other.m_refs; |
|
505 return *this; |
|
506 } |
|
507 |
|
508 template<typename T> template<typename U> |
|
509 wp<T>& wp<T>::operator = (const sp<U>& other) |
|
510 { |
|
511 weakref_type* newRefs = |
|
512 other != NULL ? other->createWeak(this) : 0; |
|
513 if (m_ptr) m_refs->decWeak(this); |
|
514 m_ptr = other.get(); |
|
515 m_refs = newRefs; |
|
516 return *this; |
|
517 } |
|
518 |
|
519 template<typename T> |
|
520 void wp<T>::set_object_and_refs(T* other, weakref_type* refs) |
|
521 { |
|
522 if (other) refs->incWeak(this); |
|
523 if (m_ptr) m_refs->decWeak(this); |
|
524 m_ptr = other; |
|
525 m_refs = refs; |
|
526 } |
|
527 |
|
528 template<typename T> |
|
529 sp<T> wp<T>::promote() const |
|
530 { |
|
531 return sp<T>(m_ptr, m_refs); |
|
532 } |
|
533 |
|
534 template<typename T> |
|
535 void wp<T>::clear() |
|
536 { |
|
537 if (m_ptr) { |
|
538 m_refs->decWeak(this); |
|
539 m_ptr = 0; |
|
540 } |
|
541 } |
|
542 |
|
543 template <typename T> |
|
544 inline TextOutput& operator<<(TextOutput& to, const wp<T>& val) |
|
545 { |
|
546 to << "wp<>(" << val.unsafe_get() << ")"; |
|
547 return to; |
|
548 } |
|
549 |
|
550 }; // namespace android |
|
551 |
|
552 // --------------------------------------------------------------------------- |
|
553 |
|
554 #endif // ANDROID_REF_BASE_H |