blob: 1b4a310008ade7fdd9d8cdbdd950e2b9586cba04 [file] [log] [blame]
The Android Open Source Project9066cfe2009-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 Agopian951d3fe2011-02-09 18:38:55 -080034#define COMPARE_WEAK(_op_) \
The Android Open Source Project9066cfe2009-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 Project9066cfe2009-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 Agopian951d3fe2011-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 Project9066cfe2009-03-03 19:31:44 -080053 return m_ptr _op_ o.m_ptr; \
54} \
55template<typename U> \
Mathias Agopian951d3fe2011-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 Project9066cfe2009-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();
Mathias Agopian9e763662011-05-19 18:03:31 -0700118
119 // called when the last reference goes away. this is responsible for
120 // calling the destructor. The default implementation just does
121 // "delete this;".
122 // Make sure to never acquire a strong reference from this function. The
123 // same restrictions than for destructors apply.
124 virtual void destroy() const;
125
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800126 //! Flags for extendObjectLifetime()
127 enum {
128 OBJECT_LIFETIME_WEAK = 0x0001,
129 OBJECT_LIFETIME_FOREVER = 0x0003
130 };
131
132 void extendObjectLifetime(int32_t mode);
133
134 //! Flags for onIncStrongAttempted()
135 enum {
136 FIRST_INC_STRONG = 0x0001
137 };
138
139 virtual void onFirstRef();
140 virtual void onLastStrongRef(const void* id);
141 virtual bool onIncStrongAttempted(uint32_t flags, const void* id);
142 virtual void onLastWeakRef(const void* id);
143
144private:
145 friend class weakref_type;
146 class weakref_impl;
147
148 RefBase(const RefBase& o);
149 RefBase& operator=(const RefBase& o);
150
151 weakref_impl* const mRefs;
152};
153
154// ---------------------------------------------------------------------------
155
156template <class T>
157class LightRefBase
158{
159public:
160 inline LightRefBase() : mCount(0) { }
161 inline void incStrong(const void* id) const {
162 android_atomic_inc(&mCount);
163 }
164 inline void decStrong(const void* id) const {
165 if (android_atomic_dec(&mCount) == 1) {
166 delete static_cast<const T*>(this);
167 }
168 }
Mathias Agopiandff8e582009-05-04 14:17:04 -0700169 //! DEBUGGING ONLY: Get current strong ref count.
170 inline int32_t getStrongCount() const {
171 return mCount;
172 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800173
174protected:
175 inline ~LightRefBase() { }
176
177private:
178 mutable volatile int32_t mCount;
179};
180
181// ---------------------------------------------------------------------------
182
183template <typename T>
184class sp
185{
186public:
187 typedef typename RefBase::weakref_type weakref_type;
188
189 inline sp() : m_ptr(0) { }
190
191 sp(T* other);
192 sp(const sp<T>& other);
193 template<typename U> sp(U* other);
194 template<typename U> sp(const sp<U>& other);
195
196 ~sp();
197
198 // Assignment
199
200 sp& operator = (T* other);
201 sp& operator = (const sp<T>& other);
202
203 template<typename U> sp& operator = (const sp<U>& other);
204 template<typename U> sp& operator = (U* other);
205
206 //! Special optimization for use by ProcessState (and nobody else).
207 void force_set(T* other);
208
209 // Reset
210
211 void clear();
212
213 // Accessors
214
215 inline T& operator* () const { return *m_ptr; }
216 inline T* operator-> () const { return m_ptr; }
217 inline T* get() const { return m_ptr; }
218
219 // Operators
220
221 COMPARE(==)
222 COMPARE(!=)
223 COMPARE(>)
224 COMPARE(<)
225 COMPARE(<=)
226 COMPARE(>=)
227
228private:
229 template<typename Y> friend class sp;
230 template<typename Y> friend class wp;
231
232 // Optimization for wp::promote().
233 sp(T* p, weakref_type* refs);
234
235 T* m_ptr;
236};
237
238template <typename T>
239TextOutput& operator<<(TextOutput& to, const sp<T>& val);
240
241// ---------------------------------------------------------------------------
242
243template <typename T>
244class wp
245{
246public:
247 typedef typename RefBase::weakref_type weakref_type;
248
249 inline wp() : m_ptr(0) { }
250
251 wp(T* other);
252 wp(const wp<T>& other);
253 wp(const sp<T>& other);
254 template<typename U> wp(U* other);
255 template<typename U> wp(const sp<U>& other);
256 template<typename U> wp(const wp<U>& other);
257
258 ~wp();
259
260 // Assignment
261
262 wp& operator = (T* other);
263 wp& operator = (const wp<T>& other);
264 wp& operator = (const sp<T>& other);
265
266 template<typename U> wp& operator = (U* other);
267 template<typename U> wp& operator = (const wp<U>& other);
268 template<typename U> wp& operator = (const sp<U>& other);
269
270 void set_object_and_refs(T* other, weakref_type* refs);
271
272 // promotion to sp
273
274 sp<T> promote() const;
275
276 // Reset
277
278 void clear();
279
280 // Accessors
281
282 inline weakref_type* get_refs() const { return m_refs; }
283
284 inline T* unsafe_get() const { return m_ptr; }
285
286 // Operators
Mathias Agopian951d3fe2011-02-09 18:38:55 -0800287
288 COMPARE_WEAK(==)
289 COMPARE_WEAK(!=)
290 COMPARE_WEAK(>)
291 COMPARE_WEAK(<)
292 COMPARE_WEAK(<=)
293 COMPARE_WEAK(>=)
294
295 inline bool operator == (const wp<T>& o) const {
296 return (m_ptr == o.m_ptr) && (m_refs == o.m_refs);
297 }
298 template<typename U>
299 inline bool operator == (const wp<U>& o) const {
300 return m_ptr == o.m_ptr;
301 }
302
303 inline bool operator > (const wp<T>& o) const {
304 return (m_ptr == o.m_ptr) ? (m_refs > o.m_refs) : (m_ptr > o.m_ptr);
305 }
306 template<typename U>
307 inline bool operator > (const wp<U>& o) const {
308 return (m_ptr == o.m_ptr) ? (m_refs > o.m_refs) : (m_ptr > o.m_ptr);
309 }
310
311 inline bool operator < (const wp<T>& o) const {
312 return (m_ptr == o.m_ptr) ? (m_refs < o.m_refs) : (m_ptr < o.m_ptr);
313 }
314 template<typename U>
315 inline bool operator < (const wp<U>& o) const {
316 return (m_ptr == o.m_ptr) ? (m_refs < o.m_refs) : (m_ptr < o.m_ptr);
317 }
318 inline bool operator != (const wp<T>& o) const { return m_refs != o.m_refs; }
319 template<typename U> inline bool operator != (const wp<U>& o) const { return !operator == (o); }
320 inline bool operator <= (const wp<T>& o) const { return !operator > (o); }
321 template<typename U> inline bool operator <= (const wp<U>& o) const { return !operator > (o); }
322 inline bool operator >= (const wp<T>& o) const { return !operator < (o); }
323 template<typename U> inline bool operator >= (const wp<U>& o) const { return !operator < (o); }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800324
325private:
326 template<typename Y> friend class sp;
327 template<typename Y> friend class wp;
328
329 T* m_ptr;
330 weakref_type* m_refs;
331};
332
333template <typename T>
334TextOutput& operator<<(TextOutput& to, const wp<T>& val);
335
336#undef COMPARE
Mathias Agopian951d3fe2011-02-09 18:38:55 -0800337#undef COMPARE_WEAK
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800338
339// ---------------------------------------------------------------------------
340// No user serviceable parts below here.
341
342template<typename T>
343sp<T>::sp(T* other)
344 : m_ptr(other)
345{
346 if (other) other->incStrong(this);
347}
348
349template<typename T>
350sp<T>::sp(const sp<T>& other)
351 : m_ptr(other.m_ptr)
352{
353 if (m_ptr) m_ptr->incStrong(this);
354}
355
356template<typename T> template<typename U>
357sp<T>::sp(U* other) : m_ptr(other)
358{
359 if (other) other->incStrong(this);
360}
361
362template<typename T> template<typename U>
363sp<T>::sp(const sp<U>& other)
364 : m_ptr(other.m_ptr)
365{
366 if (m_ptr) m_ptr->incStrong(this);
367}
368
369template<typename T>
370sp<T>::~sp()
371{
372 if (m_ptr) m_ptr->decStrong(this);
373}
374
375template<typename T>
376sp<T>& sp<T>::operator = (const sp<T>& other) {
Mathias Agopian51a6aef2010-06-24 21:49:02 -0700377 T* otherPtr(other.m_ptr);
378 if (otherPtr) otherPtr->incStrong(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800379 if (m_ptr) m_ptr->decStrong(this);
Mathias Agopian51a6aef2010-06-24 21:49:02 -0700380 m_ptr = otherPtr;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800381 return *this;
382}
383
384template<typename T>
385sp<T>& sp<T>::operator = (T* other)
386{
387 if (other) other->incStrong(this);
388 if (m_ptr) m_ptr->decStrong(this);
389 m_ptr = other;
390 return *this;
391}
392
393template<typename T> template<typename U>
394sp<T>& sp<T>::operator = (const sp<U>& other)
395{
Mathias Agopian51a6aef2010-06-24 21:49:02 -0700396 U* otherPtr(other.m_ptr);
397 if (otherPtr) otherPtr->incStrong(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800398 if (m_ptr) m_ptr->decStrong(this);
Mathias Agopian51a6aef2010-06-24 21:49:02 -0700399 m_ptr = otherPtr;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800400 return *this;
401}
402
403template<typename T> template<typename U>
404sp<T>& sp<T>::operator = (U* other)
405{
406 if (other) other->incStrong(this);
407 if (m_ptr) m_ptr->decStrong(this);
408 m_ptr = other;
409 return *this;
410}
411
412template<typename T>
413void sp<T>::force_set(T* other)
414{
415 other->forceIncStrong(this);
416 m_ptr = other;
417}
418
419template<typename T>
420void sp<T>::clear()
421{
422 if (m_ptr) {
423 m_ptr->decStrong(this);
424 m_ptr = 0;
425 }
426}
427
428template<typename T>
429sp<T>::sp(T* p, weakref_type* refs)
430 : m_ptr((p && refs->attemptIncStrong(this)) ? p : 0)
431{
432}
433
434template <typename T>
435inline TextOutput& operator<<(TextOutput& to, const sp<T>& val)
436{
437 to << "sp<>(" << val.get() << ")";
438 return to;
439}
440
441// ---------------------------------------------------------------------------
442
443template<typename T>
444wp<T>::wp(T* other)
445 : m_ptr(other)
446{
447 if (other) m_refs = other->createWeak(this);
448}
449
450template<typename T>
451wp<T>::wp(const wp<T>& other)
452 : m_ptr(other.m_ptr), m_refs(other.m_refs)
453{
454 if (m_ptr) m_refs->incWeak(this);
455}
456
457template<typename T>
458wp<T>::wp(const sp<T>& other)
459 : m_ptr(other.m_ptr)
460{
461 if (m_ptr) {
462 m_refs = m_ptr->createWeak(this);
463 }
464}
465
466template<typename T> template<typename U>
467wp<T>::wp(U* other)
468 : m_ptr(other)
469{
470 if (other) m_refs = other->createWeak(this);
471}
472
473template<typename T> template<typename U>
474wp<T>::wp(const wp<U>& other)
475 : m_ptr(other.m_ptr)
476{
477 if (m_ptr) {
478 m_refs = other.m_refs;
479 m_refs->incWeak(this);
480 }
481}
482
483template<typename T> template<typename U>
484wp<T>::wp(const sp<U>& other)
485 : m_ptr(other.m_ptr)
486{
487 if (m_ptr) {
488 m_refs = m_ptr->createWeak(this);
489 }
490}
491
492template<typename T>
493wp<T>::~wp()
494{
495 if (m_ptr) m_refs->decWeak(this);
496}
497
498template<typename T>
499wp<T>& wp<T>::operator = (T* other)
500{
501 weakref_type* newRefs =
502 other ? other->createWeak(this) : 0;
503 if (m_ptr) m_refs->decWeak(this);
504 m_ptr = other;
505 m_refs = newRefs;
506 return *this;
507}
508
509template<typename T>
510wp<T>& wp<T>::operator = (const wp<T>& other)
511{
Mathias Agopian51a6aef2010-06-24 21:49:02 -0700512 weakref_type* otherRefs(other.m_refs);
513 T* otherPtr(other.m_ptr);
514 if (otherPtr) otherRefs->incWeak(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800515 if (m_ptr) m_refs->decWeak(this);
Mathias Agopian51a6aef2010-06-24 21:49:02 -0700516 m_ptr = otherPtr;
517 m_refs = otherRefs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800518 return *this;
519}
520
521template<typename T>
522wp<T>& wp<T>::operator = (const sp<T>& other)
523{
524 weakref_type* newRefs =
525 other != NULL ? other->createWeak(this) : 0;
Mathias Agopian51a6aef2010-06-24 21:49:02 -0700526 T* otherPtr(other.m_ptr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800527 if (m_ptr) m_refs->decWeak(this);
Mathias Agopian51a6aef2010-06-24 21:49:02 -0700528 m_ptr = otherPtr;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800529 m_refs = newRefs;
530 return *this;
531}
532
533template<typename T> template<typename U>
534wp<T>& wp<T>::operator = (U* other)
535{
536 weakref_type* newRefs =
537 other ? other->createWeak(this) : 0;
538 if (m_ptr) m_refs->decWeak(this);
539 m_ptr = other;
540 m_refs = newRefs;
541 return *this;
542}
543
544template<typename T> template<typename U>
545wp<T>& wp<T>::operator = (const wp<U>& other)
546{
Mathias Agopian51a6aef2010-06-24 21:49:02 -0700547 weakref_type* otherRefs(other.m_refs);
548 U* otherPtr(other.m_ptr);
549 if (otherPtr) otherRefs->incWeak(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800550 if (m_ptr) m_refs->decWeak(this);
Mathias Agopian51a6aef2010-06-24 21:49:02 -0700551 m_ptr = otherPtr;
552 m_refs = otherRefs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800553 return *this;
554}
555
556template<typename T> template<typename U>
557wp<T>& wp<T>::operator = (const sp<U>& other)
558{
559 weakref_type* newRefs =
560 other != NULL ? other->createWeak(this) : 0;
Mathias Agopian51a6aef2010-06-24 21:49:02 -0700561 U* otherPtr(other.m_ptr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800562 if (m_ptr) m_refs->decWeak(this);
Mathias Agopian51a6aef2010-06-24 21:49:02 -0700563 m_ptr = otherPtr;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800564 m_refs = newRefs;
565 return *this;
566}
567
568template<typename T>
569void wp<T>::set_object_and_refs(T* other, weakref_type* refs)
570{
571 if (other) refs->incWeak(this);
572 if (m_ptr) m_refs->decWeak(this);
573 m_ptr = other;
574 m_refs = refs;
575}
576
577template<typename T>
578sp<T> wp<T>::promote() const
579{
580 return sp<T>(m_ptr, m_refs);
581}
582
583template<typename T>
584void wp<T>::clear()
585{
586 if (m_ptr) {
587 m_refs->decWeak(this);
588 m_ptr = 0;
589 }
590}
591
592template <typename T>
593inline TextOutput& operator<<(TextOutput& to, const wp<T>& val)
594{
595 to << "wp<>(" << val.unsafe_get() << ")";
596 return to;
597}
598
599}; // namespace android
600
601// ---------------------------------------------------------------------------
602
603#endif // ANDROID_REF_BASE_H