blob: bd7f28cae3a178456857af0e430c11c24a4b3504 [file] [log] [blame]
The Android Open Source Projectedbf3b62009-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 Agopian0926f502009-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 Projectedbf3b62009-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) {
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
342template<typename T>
343sp<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
351template<typename T> template<typename U>
352sp<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
360template<typename T> template<typename U>
361sp<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
369template<typename T>
370void sp<T>::force_set(T* other)
371{
372 other->forceIncStrong(this);
373 m_ptr = other;
374}
375
376template<typename T>
377void sp<T>::clear()
378{
379 if (m_ptr) {
380 m_ptr->decStrong(this);
381 m_ptr = 0;
382 }
383}
384
385template<typename T>
386sp<T>::sp(T* p, weakref_type* refs)
387 : m_ptr((p && refs->attemptIncStrong(this)) ? p : 0)
388{
389}
390
391template <typename T>
392inline TextOutput& operator<<(TextOutput& to, const sp<T>& val)
393{
394 to << "sp<>(" << val.get() << ")";
395 return to;
396}
397
398// ---------------------------------------------------------------------------
399
400template<typename T>
401wp<T>::wp(T* other)
402 : m_ptr(other)
403{
404 if (other) m_refs = other->createWeak(this);
405}
406
407template<typename T>
408wp<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
414template<typename T>
415wp<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
423template<typename T> template<typename U>
424wp<T>::wp(U* other)
425 : m_ptr(other)
426{
427 if (other) m_refs = other->createWeak(this);
428}
429
430template<typename T> template<typename U>
431wp<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
440template<typename T> template<typename U>
441wp<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
449template<typename T>
450wp<T>::~wp()
451{
452 if (m_ptr) m_refs->decWeak(this);
453}
454
455template<typename T>
456wp<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
466template<typename T>
467wp<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
476template<typename T>
477wp<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
487template<typename T> template<typename U>
488wp<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
498template<typename T> template<typename U>
499wp<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
508template<typename T> template<typename U>
509wp<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
519template<typename T>
520void 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
528template<typename T>
529sp<T> wp<T>::promote() const
530{
531 return sp<T>(m_ptr, m_refs);
532}
533
534template<typename T>
535void wp<T>::clear()
536{
537 if (m_ptr) {
538 m_refs->decWeak(this);
539 m_ptr = 0;
540 }
541}
542
543template <typename T>
544inline 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