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