blob: cbda0fd80db638e394cb05074f801d2295672615 [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 }
159
160protected:
161 inline ~LightRefBase() { }
162
163private:
164 mutable volatile int32_t mCount;
165};
166
167// ---------------------------------------------------------------------------
168
169template <typename T>
170class sp
171{
172public:
173 typedef typename RefBase::weakref_type weakref_type;
174
175 inline sp() : m_ptr(0) { }
176
177 sp(T* other);
178 sp(const sp<T>& other);
179 template<typename U> sp(U* other);
180 template<typename U> sp(const sp<U>& other);
181
182 ~sp();
183
184 // Assignment
185
186 sp& operator = (T* other);
187 sp& operator = (const sp<T>& other);
188
189 template<typename U> sp& operator = (const sp<U>& other);
190 template<typename U> sp& operator = (U* other);
191
192 //! Special optimization for use by ProcessState (and nobody else).
193 void force_set(T* other);
194
195 // Reset
196
197 void clear();
198
199 // Accessors
200
201 inline T& operator* () const { return *m_ptr; }
202 inline T* operator-> () const { return m_ptr; }
203 inline T* get() const { return m_ptr; }
204
205 // Operators
206
207 COMPARE(==)
208 COMPARE(!=)
209 COMPARE(>)
210 COMPARE(<)
211 COMPARE(<=)
212 COMPARE(>=)
213
214private:
215 template<typename Y> friend class sp;
216 template<typename Y> friend class wp;
217
218 // Optimization for wp::promote().
219 sp(T* p, weakref_type* refs);
220
221 T* m_ptr;
222};
223
224template <typename T>
225TextOutput& operator<<(TextOutput& to, const sp<T>& val);
226
227// ---------------------------------------------------------------------------
228
229template <typename T>
230class wp
231{
232public:
233 typedef typename RefBase::weakref_type weakref_type;
234
235 inline wp() : m_ptr(0) { }
236
237 wp(T* other);
238 wp(const wp<T>& other);
239 wp(const sp<T>& other);
240 template<typename U> wp(U* other);
241 template<typename U> wp(const sp<U>& other);
242 template<typename U> wp(const wp<U>& other);
243
244 ~wp();
245
246 // Assignment
247
248 wp& operator = (T* other);
249 wp& operator = (const wp<T>& other);
250 wp& operator = (const sp<T>& other);
251
252 template<typename U> wp& operator = (U* other);
253 template<typename U> wp& operator = (const wp<U>& other);
254 template<typename U> wp& operator = (const sp<U>& other);
255
256 void set_object_and_refs(T* other, weakref_type* refs);
257
258 // promotion to sp
259
260 sp<T> promote() const;
261
262 // Reset
263
264 void clear();
265
266 // Accessors
267
268 inline weakref_type* get_refs() const { return m_refs; }
269
270 inline T* unsafe_get() const { return m_ptr; }
271
272 // Operators
273
274 COMPARE(==)
275 COMPARE(!=)
276 COMPARE(>)
277 COMPARE(<)
278 COMPARE(<=)
279 COMPARE(>=)
280
281private:
282 template<typename Y> friend class sp;
283 template<typename Y> friend class wp;
284
285 T* m_ptr;
286 weakref_type* m_refs;
287};
288
289template <typename T>
290TextOutput& operator<<(TextOutput& to, const wp<T>& val);
291
292#undef COMPARE
293
294// ---------------------------------------------------------------------------
295// No user serviceable parts below here.
296
297template<typename T>
298sp<T>::sp(T* other)
299 : m_ptr(other)
300{
301 if (other) other->incStrong(this);
302}
303
304template<typename T>
305sp<T>::sp(const sp<T>& other)
306 : m_ptr(other.m_ptr)
307{
308 if (m_ptr) m_ptr->incStrong(this);
309}
310
311template<typename T> template<typename U>
312sp<T>::sp(U* other) : m_ptr(other)
313{
314 if (other) other->incStrong(this);
315}
316
317template<typename T> template<typename U>
318sp<T>::sp(const sp<U>& other)
319 : m_ptr(other.m_ptr)
320{
321 if (m_ptr) m_ptr->incStrong(this);
322}
323
324template<typename T>
325sp<T>::~sp()
326{
327 if (m_ptr) m_ptr->decStrong(this);
328}
329
330template<typename T>
331sp<T>& sp<T>::operator = (const sp<T>& other) {
332 if (other.m_ptr) other.m_ptr->incStrong(this);
333 if (m_ptr) m_ptr->decStrong(this);
334 m_ptr = other.m_ptr;
335 return *this;
336}
337
338template<typename T>
339sp<T>& sp<T>::operator = (T* other)
340{
341 if (other) other->incStrong(this);
342 if (m_ptr) m_ptr->decStrong(this);
343 m_ptr = other;
344 return *this;
345}
346
347template<typename T> template<typename U>
348sp<T>& sp<T>::operator = (const sp<U>& other)
349{
350 if (other.m_ptr) other.m_ptr->incStrong(this);
351 if (m_ptr) m_ptr->decStrong(this);
352 m_ptr = other.m_ptr;
353 return *this;
354}
355
356template<typename T> template<typename U>
357sp<T>& sp<T>::operator = (U* other)
358{
359 if (other) other->incStrong(this);
360 if (m_ptr) m_ptr->decStrong(this);
361 m_ptr = other;
362 return *this;
363}
364
365template<typename T>
366void sp<T>::force_set(T* other)
367{
368 other->forceIncStrong(this);
369 m_ptr = other;
370}
371
372template<typename T>
373void sp<T>::clear()
374{
375 if (m_ptr) {
376 m_ptr->decStrong(this);
377 m_ptr = 0;
378 }
379}
380
381template<typename T>
382sp<T>::sp(T* p, weakref_type* refs)
383 : m_ptr((p && refs->attemptIncStrong(this)) ? p : 0)
384{
385}
386
387template <typename T>
388inline TextOutput& operator<<(TextOutput& to, const sp<T>& val)
389{
390 to << "sp<>(" << val.get() << ")";
391 return to;
392}
393
394// ---------------------------------------------------------------------------
395
396template<typename T>
397wp<T>::wp(T* other)
398 : m_ptr(other)
399{
400 if (other) m_refs = other->createWeak(this);
401}
402
403template<typename T>
404wp<T>::wp(const wp<T>& other)
405 : m_ptr(other.m_ptr), m_refs(other.m_refs)
406{
407 if (m_ptr) m_refs->incWeak(this);
408}
409
410template<typename T>
411wp<T>::wp(const sp<T>& other)
412 : m_ptr(other.m_ptr)
413{
414 if (m_ptr) {
415 m_refs = m_ptr->createWeak(this);
416 }
417}
418
419template<typename T> template<typename U>
420wp<T>::wp(U* other)
421 : m_ptr(other)
422{
423 if (other) m_refs = other->createWeak(this);
424}
425
426template<typename T> template<typename U>
427wp<T>::wp(const wp<U>& other)
428 : m_ptr(other.m_ptr)
429{
430 if (m_ptr) {
431 m_refs = other.m_refs;
432 m_refs->incWeak(this);
433 }
434}
435
436template<typename T> template<typename U>
437wp<T>::wp(const sp<U>& other)
438 : m_ptr(other.m_ptr)
439{
440 if (m_ptr) {
441 m_refs = m_ptr->createWeak(this);
442 }
443}
444
445template<typename T>
446wp<T>::~wp()
447{
448 if (m_ptr) m_refs->decWeak(this);
449}
450
451template<typename T>
452wp<T>& wp<T>::operator = (T* other)
453{
454 weakref_type* newRefs =
455 other ? other->createWeak(this) : 0;
456 if (m_ptr) m_refs->decWeak(this);
457 m_ptr = other;
458 m_refs = newRefs;
459 return *this;
460}
461
462template<typename T>
463wp<T>& wp<T>::operator = (const wp<T>& other)
464{
465 if (other.m_ptr) other.m_refs->incWeak(this);
466 if (m_ptr) m_refs->decWeak(this);
467 m_ptr = other.m_ptr;
468 m_refs = other.m_refs;
469 return *this;
470}
471
472template<typename T>
473wp<T>& wp<T>::operator = (const sp<T>& other)
474{
475 weakref_type* newRefs =
476 other != NULL ? other->createWeak(this) : 0;
477 if (m_ptr) m_refs->decWeak(this);
478 m_ptr = other.get();
479 m_refs = newRefs;
480 return *this;
481}
482
483template<typename T> template<typename U>
484wp<T>& wp<T>::operator = (U* other)
485{
486 weakref_type* newRefs =
487 other ? other->createWeak(this) : 0;
488 if (m_ptr) m_refs->decWeak(this);
489 m_ptr = other;
490 m_refs = newRefs;
491 return *this;
492}
493
494template<typename T> template<typename U>
495wp<T>& wp<T>::operator = (const wp<U>& other)
496{
497 if (other.m_ptr) other.m_refs->incWeak(this);
498 if (m_ptr) m_refs->decWeak(this);
499 m_ptr = other.m_ptr;
500 m_refs = other.m_refs;
501 return *this;
502}
503
504template<typename T> template<typename U>
505wp<T>& wp<T>::operator = (const sp<U>& other)
506{
507 weakref_type* newRefs =
508 other != NULL ? other->createWeak(this) : 0;
509 if (m_ptr) m_refs->decWeak(this);
510 m_ptr = other.get();
511 m_refs = newRefs;
512 return *this;
513}
514
515template<typename T>
516void wp<T>::set_object_and_refs(T* other, weakref_type* refs)
517{
518 if (other) refs->incWeak(this);
519 if (m_ptr) m_refs->decWeak(this);
520 m_ptr = other;
521 m_refs = refs;
522}
523
524template<typename T>
525sp<T> wp<T>::promote() const
526{
527 return sp<T>(m_ptr, m_refs);
528}
529
530template<typename T>
531void wp<T>::clear()
532{
533 if (m_ptr) {
534 m_refs->decWeak(this);
535 m_ptr = 0;
536 }
537}
538
539template <typename T>
540inline TextOutput& operator<<(TextOutput& to, const wp<T>& val)
541{
542 to << "wp<>(" << val.unsafe_get() << ")";
543 return to;
544}
545
546}; // namespace android
547
548// ---------------------------------------------------------------------------
549
550#endif // ANDROID_REF_BASE_H