blob: 9c64ac044340576d6423c6acb27d014accca3b66 [file] [log] [blame]
The Android Open Source Projectcbb10112009-03-03 19:31:44 -08001/*
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// ---------------------------------------------------------------------------
28namespace android {
29
30template<typename T> class wp;
31
32// ---------------------------------------------------------------------------
33
34#define COMPARE(_op_) \
35inline bool operator _op_ (const sp<T>& o) const { \
36 return m_ptr _op_ o.m_ptr; \
37} \
38inline bool operator _op_ (const wp<T>& o) const { \
39 return m_ptr _op_ o.m_ptr; \
40} \
41inline bool operator _op_ (const T* o) const { \
42 return m_ptr _op_ o; \
43} \
44template<typename U> \
45inline bool operator _op_ (const sp<U>& o) const { \
46 return m_ptr _op_ o.m_ptr; \
47} \
48template<typename U> \
49inline bool operator _op_ (const wp<U>& o) const { \
50 return m_ptr _op_ o.m_ptr; \
51} \
52template<typename U> \
53inline bool operator _op_ (const U* o) const { \
54 return m_ptr _op_ o; \
55}
56
57// ---------------------------------------------------------------------------
58
59class RefBase
60{
61public:
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
112protected:
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
134private:
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
146template <class T>
147class LightRefBase
148{
149public:
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 }
Mathias Agopian019f8ed2009-05-04 14:17:04 -0700159 //! DEBUGGING ONLY: Get current strong ref count.
160 inline int32_t getStrongCount() const {
161 return mCount;
162 }
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800163
164protected:
165 inline ~LightRefBase() { }
166
167private:
168 mutable volatile int32_t mCount;
169};
170
171// ---------------------------------------------------------------------------
172
173template <typename T>
174class sp
175{
176public:
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
218private:
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
228template <typename T>
229TextOutput& operator<<(TextOutput& to, const sp<T>& val);
230
231// ---------------------------------------------------------------------------
232
233template <typename T>
234class wp
235{
236public:
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
285private:
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
293template <typename T>
294TextOutput& operator<<(TextOutput& to, const wp<T>& val);
295
296#undef COMPARE
297
298// ---------------------------------------------------------------------------
299// No user serviceable parts below here.
300
301template<typename T>
302sp<T>::sp(T* other)
303 : m_ptr(other)
304{
305 if (other) other->incStrong(this);
306}
307
308template<typename T>
309sp<T>::sp(const sp<T>& other)
310 : m_ptr(other.m_ptr)
311{
312 if (m_ptr) m_ptr->incStrong(this);
313}
314
315template<typename T> template<typename U>
316sp<T>::sp(U* other) : m_ptr(other)
317{
318 if (other) other->incStrong(this);
319}
320
321template<typename T> template<typename U>
322sp<T>::sp(const sp<U>& other)
323 : m_ptr(other.m_ptr)
324{
325 if (m_ptr) m_ptr->incStrong(this);
326}
327
328template<typename T>
329sp<T>::~sp()
330{
331 if (m_ptr) m_ptr->decStrong(this);
332}
333
334template<typename T>
335sp<T>& sp<T>::operator = (const sp<T>& other) {
Mathias Agopian7b151672010-06-24 21:49:02 -0700336 T* otherPtr(other.m_ptr);
337 if (otherPtr) otherPtr->incStrong(this);
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800338 if (m_ptr) m_ptr->decStrong(this);
Mathias Agopian7b151672010-06-24 21:49:02 -0700339 m_ptr = otherPtr;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800340 return *this;
341}
342
343template<typename T>
344sp<T>& sp<T>::operator = (T* other)
345{
346 if (other) other->incStrong(this);
347 if (m_ptr) m_ptr->decStrong(this);
348 m_ptr = other;
349 return *this;
350}
351
352template<typename T> template<typename U>
353sp<T>& sp<T>::operator = (const sp<U>& other)
354{
Mathias Agopian7b151672010-06-24 21:49:02 -0700355 U* otherPtr(other.m_ptr);
356 if (otherPtr) otherPtr->incStrong(this);
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800357 if (m_ptr) m_ptr->decStrong(this);
Mathias Agopian7b151672010-06-24 21:49:02 -0700358 m_ptr = otherPtr;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800359 return *this;
360}
361
362template<typename T> template<typename U>
363sp<T>& sp<T>::operator = (U* other)
364{
365 if (other) other->incStrong(this);
366 if (m_ptr) m_ptr->decStrong(this);
367 m_ptr = other;
368 return *this;
369}
370
371template<typename T>
372void sp<T>::force_set(T* other)
373{
374 other->forceIncStrong(this);
375 m_ptr = other;
376}
377
378template<typename T>
379void sp<T>::clear()
380{
381 if (m_ptr) {
382 m_ptr->decStrong(this);
383 m_ptr = 0;
384 }
385}
386
387template<typename T>
388sp<T>::sp(T* p, weakref_type* refs)
389 : m_ptr((p && refs->attemptIncStrong(this)) ? p : 0)
390{
391}
392
393template <typename T>
394inline TextOutput& operator<<(TextOutput& to, const sp<T>& val)
395{
396 to << "sp<>(" << val.get() << ")";
397 return to;
398}
399
400// ---------------------------------------------------------------------------
401
402template<typename T>
403wp<T>::wp(T* other)
404 : m_ptr(other)
405{
406 if (other) m_refs = other->createWeak(this);
407}
408
409template<typename T>
410wp<T>::wp(const wp<T>& other)
411 : m_ptr(other.m_ptr), m_refs(other.m_refs)
412{
413 if (m_ptr) m_refs->incWeak(this);
414}
415
416template<typename T>
417wp<T>::wp(const sp<T>& other)
418 : m_ptr(other.m_ptr)
419{
420 if (m_ptr) {
421 m_refs = m_ptr->createWeak(this);
422 }
423}
424
425template<typename T> template<typename U>
426wp<T>::wp(U* other)
427 : m_ptr(other)
428{
429 if (other) m_refs = other->createWeak(this);
430}
431
432template<typename T> template<typename U>
433wp<T>::wp(const wp<U>& other)
434 : m_ptr(other.m_ptr)
435{
436 if (m_ptr) {
437 m_refs = other.m_refs;
438 m_refs->incWeak(this);
439 }
440}
441
442template<typename T> template<typename U>
443wp<T>::wp(const sp<U>& other)
444 : m_ptr(other.m_ptr)
445{
446 if (m_ptr) {
447 m_refs = m_ptr->createWeak(this);
448 }
449}
450
451template<typename T>
452wp<T>::~wp()
453{
454 if (m_ptr) m_refs->decWeak(this);
455}
456
457template<typename T>
458wp<T>& wp<T>::operator = (T* other)
459{
460 weakref_type* newRefs =
461 other ? other->createWeak(this) : 0;
462 if (m_ptr) m_refs->decWeak(this);
463 m_ptr = other;
464 m_refs = newRefs;
465 return *this;
466}
467
468template<typename T>
469wp<T>& wp<T>::operator = (const wp<T>& other)
470{
Mathias Agopian7b151672010-06-24 21:49:02 -0700471 weakref_type* otherRefs(other.m_refs);
472 T* otherPtr(other.m_ptr);
473 if (otherPtr) otherRefs->incWeak(this);
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800474 if (m_ptr) m_refs->decWeak(this);
Mathias Agopian7b151672010-06-24 21:49:02 -0700475 m_ptr = otherPtr;
476 m_refs = otherRefs;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800477 return *this;
478}
479
480template<typename T>
481wp<T>& wp<T>::operator = (const sp<T>& other)
482{
483 weakref_type* newRefs =
484 other != NULL ? other->createWeak(this) : 0;
Mathias Agopian7b151672010-06-24 21:49:02 -0700485 T* otherPtr(other.m_ptr);
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800486 if (m_ptr) m_refs->decWeak(this);
Mathias Agopian7b151672010-06-24 21:49:02 -0700487 m_ptr = otherPtr;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800488 m_refs = newRefs;
489 return *this;
490}
491
492template<typename T> template<typename U>
493wp<T>& wp<T>::operator = (U* other)
494{
495 weakref_type* newRefs =
496 other ? other->createWeak(this) : 0;
497 if (m_ptr) m_refs->decWeak(this);
498 m_ptr = other;
499 m_refs = newRefs;
500 return *this;
501}
502
503template<typename T> template<typename U>
504wp<T>& wp<T>::operator = (const wp<U>& other)
505{
Mathias Agopian7b151672010-06-24 21:49:02 -0700506 weakref_type* otherRefs(other.m_refs);
507 U* otherPtr(other.m_ptr);
508 if (otherPtr) otherRefs->incWeak(this);
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800509 if (m_ptr) m_refs->decWeak(this);
Mathias Agopian7b151672010-06-24 21:49:02 -0700510 m_ptr = otherPtr;
511 m_refs = otherRefs;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800512 return *this;
513}
514
515template<typename T> template<typename U>
516wp<T>& wp<T>::operator = (const sp<U>& other)
517{
518 weakref_type* newRefs =
519 other != NULL ? other->createWeak(this) : 0;
Mathias Agopian7b151672010-06-24 21:49:02 -0700520 U* otherPtr(other.m_ptr);
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800521 if (m_ptr) m_refs->decWeak(this);
Mathias Agopian7b151672010-06-24 21:49:02 -0700522 m_ptr = otherPtr;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800523 m_refs = newRefs;
524 return *this;
525}
526
527template<typename T>
528void wp<T>::set_object_and_refs(T* other, weakref_type* refs)
529{
530 if (other) refs->incWeak(this);
531 if (m_ptr) m_refs->decWeak(this);
532 m_ptr = other;
533 m_refs = refs;
534}
535
536template<typename T>
537sp<T> wp<T>::promote() const
538{
539 return sp<T>(m_ptr, m_refs);
540}
541
542template<typename T>
543void wp<T>::clear()
544{
545 if (m_ptr) {
546 m_refs->decWeak(this);
547 m_ptr = 0;
548 }
549}
550
551template <typename T>
552inline TextOutput& operator<<(TextOutput& to, const wp<T>& val)
553{
554 to << "wp<>(" << val.unsafe_get() << ")";
555 return to;
556}
557
558}; // namespace android
559
560// ---------------------------------------------------------------------------
561
562#endif // ANDROID_REF_BASE_H