blob: c24c0dbcb28ff654f0ee5b4d6fc8ac08284e14ea [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
Mathias Agopianff49de72011-02-09 18:38:55 -080034#define COMPARE_WEAK(_op_) \
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080035inline bool operator _op_ (const sp<T>& o) const { \
36 return m_ptr _op_ o.m_ptr; \
37} \
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080038inline bool operator _op_ (const T* o) const { \
39 return m_ptr _op_ o; \
40} \
41template<typename U> \
42inline bool operator _op_ (const sp<U>& o) const { \
43 return m_ptr _op_ o.m_ptr; \
44} \
45template<typename U> \
Mathias Agopianff49de72011-02-09 18:38:55 -080046inline bool operator _op_ (const U* o) const { \
47 return m_ptr _op_ o; \
48}
49
50#define COMPARE(_op_) \
51COMPARE_WEAK(_op_) \
52inline bool operator _op_ (const wp<T>& o) const { \
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080053 return m_ptr _op_ o.m_ptr; \
54} \
55template<typename U> \
Mathias Agopianff49de72011-02-09 18:38:55 -080056inline bool operator _op_ (const wp<U>& o) const { \
57 return m_ptr _op_ o.m_ptr; \
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080058}
59
60// ---------------------------------------------------------------------------
61
62class RefBase
63{
64public:
65 void incStrong(const void* id) const;
66 void decStrong(const void* id) const;
67
68 void forceIncStrong(const void* id) const;
69
70 //! DEBUGGING ONLY: Get current strong ref count.
71 int32_t getStrongCount() const;
72
73 class weakref_type
74 {
75 public:
76 RefBase* refBase() const;
77
78 void incWeak(const void* id);
79 void decWeak(const void* id);
80
81 bool attemptIncStrong(const void* id);
82
83 //! This is only safe if you have set OBJECT_LIFETIME_FOREVER.
84 bool attemptIncWeak(const void* id);
85
86 //! DEBUGGING ONLY: Get current weak ref count.
87 int32_t getWeakCount() const;
88
89 //! DEBUGGING ONLY: Print references held on object.
90 void printRefs() const;
91
92 //! DEBUGGING ONLY: Enable tracking for this object.
93 // enable -- enable/disable tracking
94 // retain -- when tracking is enable, if true, then we save a stack trace
95 // for each reference and dereference; when retain == false, we
96 // match up references and dereferences and keep only the
97 // outstanding ones.
98
99 void trackMe(bool enable, bool retain);
100 };
101
102 weakref_type* createWeak(const void* id) const;
103
104 weakref_type* getWeakRefs() const;
105
106 //! DEBUGGING ONLY: Print references held on object.
107 inline void printRefs() const { getWeakRefs()->printRefs(); }
108
109 //! DEBUGGING ONLY: Enable tracking of object.
110 inline void trackMe(bool enable, bool retain)
111 {
112 getWeakRefs()->trackMe(enable, retain);
113 }
114
115protected:
116 RefBase();
117 virtual ~RefBase();
118
119 //! Flags for extendObjectLifetime()
120 enum {
121 OBJECT_LIFETIME_WEAK = 0x0001,
122 OBJECT_LIFETIME_FOREVER = 0x0003
123 };
124
125 void extendObjectLifetime(int32_t mode);
126
127 //! Flags for onIncStrongAttempted()
128 enum {
129 FIRST_INC_STRONG = 0x0001
130 };
131
132 virtual void onFirstRef();
133 virtual void onLastStrongRef(const void* id);
134 virtual bool onIncStrongAttempted(uint32_t flags, const void* id);
135 virtual void onLastWeakRef(const void* id);
136
137private:
138 friend class weakref_type;
139 class weakref_impl;
140
141 RefBase(const RefBase& o);
142 RefBase& operator=(const RefBase& o);
143
144 weakref_impl* const mRefs;
145};
146
147// ---------------------------------------------------------------------------
148
149template <class T>
150class LightRefBase
151{
152public:
153 inline LightRefBase() : mCount(0) { }
154 inline void incStrong(const void* id) const {
155 android_atomic_inc(&mCount);
156 }
157 inline void decStrong(const void* id) const {
158 if (android_atomic_dec(&mCount) == 1) {
159 delete static_cast<const T*>(this);
160 }
161 }
Mathias Agopian019f8ed2009-05-04 14:17:04 -0700162 //! DEBUGGING ONLY: Get current strong ref count.
163 inline int32_t getStrongCount() const {
164 return mCount;
165 }
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800166
167protected:
168 inline ~LightRefBase() { }
169
170private:
171 mutable volatile int32_t mCount;
172};
173
174// ---------------------------------------------------------------------------
175
176template <typename T>
177class sp
178{
179public:
180 typedef typename RefBase::weakref_type weakref_type;
181
182 inline sp() : m_ptr(0) { }
183
184 sp(T* other);
185 sp(const sp<T>& other);
186 template<typename U> sp(U* other);
187 template<typename U> sp(const sp<U>& other);
188
189 ~sp();
190
191 // Assignment
192
193 sp& operator = (T* other);
194 sp& operator = (const sp<T>& other);
195
196 template<typename U> sp& operator = (const sp<U>& other);
197 template<typename U> sp& operator = (U* other);
198
199 //! Special optimization for use by ProcessState (and nobody else).
200 void force_set(T* other);
201
202 // Reset
203
204 void clear();
205
206 // Accessors
207
208 inline T& operator* () const { return *m_ptr; }
209 inline T* operator-> () const { return m_ptr; }
210 inline T* get() const { return m_ptr; }
211
212 // Operators
213
214 COMPARE(==)
215 COMPARE(!=)
216 COMPARE(>)
217 COMPARE(<)
218 COMPARE(<=)
219 COMPARE(>=)
220
221private:
222 template<typename Y> friend class sp;
223 template<typename Y> friend class wp;
224
225 // Optimization for wp::promote().
226 sp(T* p, weakref_type* refs);
227
228 T* m_ptr;
229};
230
231template <typename T>
232TextOutput& operator<<(TextOutput& to, const sp<T>& val);
233
234// ---------------------------------------------------------------------------
235
236template <typename T>
237class wp
238{
239public:
240 typedef typename RefBase::weakref_type weakref_type;
241
242 inline wp() : m_ptr(0) { }
243
244 wp(T* other);
245 wp(const wp<T>& other);
246 wp(const sp<T>& other);
247 template<typename U> wp(U* other);
248 template<typename U> wp(const sp<U>& other);
249 template<typename U> wp(const wp<U>& other);
250
251 ~wp();
252
253 // Assignment
254
255 wp& operator = (T* other);
256 wp& operator = (const wp<T>& other);
257 wp& operator = (const sp<T>& other);
258
259 template<typename U> wp& operator = (U* other);
260 template<typename U> wp& operator = (const wp<U>& other);
261 template<typename U> wp& operator = (const sp<U>& other);
262
263 void set_object_and_refs(T* other, weakref_type* refs);
264
265 // promotion to sp
266
267 sp<T> promote() const;
268
269 // Reset
270
271 void clear();
272
273 // Accessors
274
275 inline weakref_type* get_refs() const { return m_refs; }
276
277 inline T* unsafe_get() const { return m_ptr; }
278
279 // Operators
Mathias Agopianff49de72011-02-09 18:38:55 -0800280
281 COMPARE_WEAK(==)
282 COMPARE_WEAK(!=)
283 COMPARE_WEAK(>)
284 COMPARE_WEAK(<)
285 COMPARE_WEAK(<=)
286 COMPARE_WEAK(>=)
287
288 inline bool operator == (const wp<T>& o) const {
289 return (m_ptr == o.m_ptr) && (m_refs == o.m_refs);
290 }
291 template<typename U>
292 inline bool operator == (const wp<U>& o) const {
293 return m_ptr == o.m_ptr;
294 }
295
296 inline bool operator > (const wp<T>& o) const {
297 return (m_ptr == o.m_ptr) ? (m_refs > o.m_refs) : (m_ptr > o.m_ptr);
298 }
299 template<typename U>
300 inline bool operator > (const wp<U>& o) const {
301 return (m_ptr == o.m_ptr) ? (m_refs > o.m_refs) : (m_ptr > o.m_ptr);
302 }
303
304 inline bool operator < (const wp<T>& o) const {
305 return (m_ptr == o.m_ptr) ? (m_refs < o.m_refs) : (m_ptr < o.m_ptr);
306 }
307 template<typename U>
308 inline bool operator < (const wp<U>& o) const {
309 return (m_ptr == o.m_ptr) ? (m_refs < o.m_refs) : (m_ptr < o.m_ptr);
310 }
311 inline bool operator != (const wp<T>& o) const { return m_refs != o.m_refs; }
312 template<typename U> inline bool operator != (const wp<U>& o) const { return !operator == (o); }
313 inline bool operator <= (const wp<T>& o) const { return !operator > (o); }
314 template<typename U> inline bool operator <= (const wp<U>& o) const { return !operator > (o); }
315 inline bool operator >= (const wp<T>& o) const { return !operator < (o); }
316 template<typename U> inline bool operator >= (const wp<U>& o) const { return !operator < (o); }
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800317
318private:
319 template<typename Y> friend class sp;
320 template<typename Y> friend class wp;
321
322 T* m_ptr;
323 weakref_type* m_refs;
324};
325
326template <typename T>
327TextOutput& operator<<(TextOutput& to, const wp<T>& val);
328
329#undef COMPARE
Mathias Agopianff49de72011-02-09 18:38:55 -0800330#undef COMPARE_WEAK
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800331
332// ---------------------------------------------------------------------------
333// No user serviceable parts below here.
334
335template<typename T>
336sp<T>::sp(T* other)
337 : m_ptr(other)
338{
339 if (other) other->incStrong(this);
340}
341
342template<typename T>
343sp<T>::sp(const sp<T>& other)
344 : m_ptr(other.m_ptr)
345{
346 if (m_ptr) m_ptr->incStrong(this);
347}
348
349template<typename T> template<typename U>
350sp<T>::sp(U* other) : m_ptr(other)
351{
352 if (other) other->incStrong(this);
353}
354
355template<typename T> template<typename U>
356sp<T>::sp(const sp<U>& other)
357 : m_ptr(other.m_ptr)
358{
359 if (m_ptr) m_ptr->incStrong(this);
360}
361
362template<typename T>
363sp<T>::~sp()
364{
365 if (m_ptr) m_ptr->decStrong(this);
366}
367
368template<typename T>
369sp<T>& sp<T>::operator = (const sp<T>& other) {
Mathias Agopian7b151672010-06-24 21:49:02 -0700370 T* otherPtr(other.m_ptr);
371 if (otherPtr) otherPtr->incStrong(this);
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800372 if (m_ptr) m_ptr->decStrong(this);
Mathias Agopian7b151672010-06-24 21:49:02 -0700373 m_ptr = otherPtr;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800374 return *this;
375}
376
377template<typename T>
378sp<T>& sp<T>::operator = (T* other)
379{
380 if (other) other->incStrong(this);
381 if (m_ptr) m_ptr->decStrong(this);
382 m_ptr = other;
383 return *this;
384}
385
386template<typename T> template<typename U>
387sp<T>& sp<T>::operator = (const sp<U>& other)
388{
Mathias Agopian7b151672010-06-24 21:49:02 -0700389 U* otherPtr(other.m_ptr);
390 if (otherPtr) otherPtr->incStrong(this);
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800391 if (m_ptr) m_ptr->decStrong(this);
Mathias Agopian7b151672010-06-24 21:49:02 -0700392 m_ptr = otherPtr;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800393 return *this;
394}
395
396template<typename T> template<typename U>
397sp<T>& sp<T>::operator = (U* other)
398{
399 if (other) other->incStrong(this);
400 if (m_ptr) m_ptr->decStrong(this);
401 m_ptr = other;
402 return *this;
403}
404
405template<typename T>
406void sp<T>::force_set(T* other)
407{
408 other->forceIncStrong(this);
409 m_ptr = other;
410}
411
412template<typename T>
413void sp<T>::clear()
414{
415 if (m_ptr) {
416 m_ptr->decStrong(this);
417 m_ptr = 0;
418 }
419}
420
421template<typename T>
422sp<T>::sp(T* p, weakref_type* refs)
423 : m_ptr((p && refs->attemptIncStrong(this)) ? p : 0)
424{
425}
426
427template <typename T>
428inline TextOutput& operator<<(TextOutput& to, const sp<T>& val)
429{
430 to << "sp<>(" << val.get() << ")";
431 return to;
432}
433
434// ---------------------------------------------------------------------------
435
436template<typename T>
437wp<T>::wp(T* other)
438 : m_ptr(other)
439{
440 if (other) m_refs = other->createWeak(this);
441}
442
443template<typename T>
444wp<T>::wp(const wp<T>& other)
445 : m_ptr(other.m_ptr), m_refs(other.m_refs)
446{
447 if (m_ptr) m_refs->incWeak(this);
448}
449
450template<typename T>
451wp<T>::wp(const sp<T>& other)
452 : m_ptr(other.m_ptr)
453{
454 if (m_ptr) {
455 m_refs = m_ptr->createWeak(this);
456 }
457}
458
459template<typename T> template<typename U>
460wp<T>::wp(U* other)
461 : m_ptr(other)
462{
463 if (other) m_refs = other->createWeak(this);
464}
465
466template<typename T> template<typename U>
467wp<T>::wp(const wp<U>& other)
468 : m_ptr(other.m_ptr)
469{
470 if (m_ptr) {
471 m_refs = other.m_refs;
472 m_refs->incWeak(this);
473 }
474}
475
476template<typename T> template<typename U>
477wp<T>::wp(const sp<U>& other)
478 : m_ptr(other.m_ptr)
479{
480 if (m_ptr) {
481 m_refs = m_ptr->createWeak(this);
482 }
483}
484
485template<typename T>
486wp<T>::~wp()
487{
488 if (m_ptr) m_refs->decWeak(this);
489}
490
491template<typename T>
492wp<T>& wp<T>::operator = (T* other)
493{
494 weakref_type* newRefs =
495 other ? other->createWeak(this) : 0;
496 if (m_ptr) m_refs->decWeak(this);
497 m_ptr = other;
498 m_refs = newRefs;
499 return *this;
500}
501
502template<typename T>
503wp<T>& wp<T>::operator = (const wp<T>& other)
504{
Mathias Agopian7b151672010-06-24 21:49:02 -0700505 weakref_type* otherRefs(other.m_refs);
506 T* otherPtr(other.m_ptr);
507 if (otherPtr) otherRefs->incWeak(this);
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800508 if (m_ptr) m_refs->decWeak(this);
Mathias Agopian7b151672010-06-24 21:49:02 -0700509 m_ptr = otherPtr;
510 m_refs = otherRefs;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800511 return *this;
512}
513
514template<typename T>
515wp<T>& wp<T>::operator = (const sp<T>& other)
516{
517 weakref_type* newRefs =
518 other != NULL ? other->createWeak(this) : 0;
Mathias Agopian7b151672010-06-24 21:49:02 -0700519 T* otherPtr(other.m_ptr);
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800520 if (m_ptr) m_refs->decWeak(this);
Mathias Agopian7b151672010-06-24 21:49:02 -0700521 m_ptr = otherPtr;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800522 m_refs = newRefs;
523 return *this;
524}
525
526template<typename T> template<typename U>
527wp<T>& wp<T>::operator = (U* other)
528{
529 weakref_type* newRefs =
530 other ? other->createWeak(this) : 0;
531 if (m_ptr) m_refs->decWeak(this);
532 m_ptr = other;
533 m_refs = newRefs;
534 return *this;
535}
536
537template<typename T> template<typename U>
538wp<T>& wp<T>::operator = (const wp<U>& other)
539{
Mathias Agopian7b151672010-06-24 21:49:02 -0700540 weakref_type* otherRefs(other.m_refs);
541 U* otherPtr(other.m_ptr);
542 if (otherPtr) otherRefs->incWeak(this);
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800543 if (m_ptr) m_refs->decWeak(this);
Mathias Agopian7b151672010-06-24 21:49:02 -0700544 m_ptr = otherPtr;
545 m_refs = otherRefs;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800546 return *this;
547}
548
549template<typename T> template<typename U>
550wp<T>& wp<T>::operator = (const sp<U>& other)
551{
552 weakref_type* newRefs =
553 other != NULL ? other->createWeak(this) : 0;
Mathias Agopian7b151672010-06-24 21:49:02 -0700554 U* otherPtr(other.m_ptr);
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800555 if (m_ptr) m_refs->decWeak(this);
Mathias Agopian7b151672010-06-24 21:49:02 -0700556 m_ptr = otherPtr;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800557 m_refs = newRefs;
558 return *this;
559}
560
561template<typename T>
562void wp<T>::set_object_and_refs(T* other, weakref_type* refs)
563{
564 if (other) refs->incWeak(this);
565 if (m_ptr) m_refs->decWeak(this);
566 m_ptr = other;
567 m_refs = refs;
568}
569
570template<typename T>
571sp<T> wp<T>::promote() const
572{
573 return sp<T>(m_ptr, m_refs);
574}
575
576template<typename T>
577void wp<T>::clear()
578{
579 if (m_ptr) {
580 m_refs->decWeak(this);
581 m_ptr = 0;
582 }
583}
584
585template <typename T>
586inline TextOutput& operator<<(TextOutput& to, const wp<T>& val)
587{
588 to << "wp<>(" << val.unsafe_get() << ")";
589 return to;
590}
591
592}; // namespace android
593
594// ---------------------------------------------------------------------------
595
596#endif // ANDROID_REF_BASE_H