blob: e37b56f5bf93f3e14fce37aa06edbd66a6f381c2 [file] [log] [blame]
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001/*
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 <utils/TextOutput.h>
21
22#include <stdint.h>
23#include <sys/types.h>
24#include <stdlib.h>
25
26// ---------------------------------------------------------------------------
27namespace android {
28
29template<typename T> class wp;
30
31// ---------------------------------------------------------------------------
32
33#define COMPARE(_op_) \
34inline bool operator _op_ (const sp<T>& o) const { \
35 return m_ptr _op_ o.m_ptr; \
36} \
37inline bool operator _op_ (const wp<T>& o) const { \
38 return m_ptr _op_ o.m_ptr; \
39} \
40inline bool operator _op_ (const T* o) const { \
41 return m_ptr _op_ o; \
42} \
43template<typename U> \
44inline bool operator _op_ (const sp<U>& o) const { \
45 return m_ptr _op_ o.m_ptr; \
46} \
47template<typename U> \
48inline bool operator _op_ (const wp<U>& o) const { \
49 return m_ptr _op_ o.m_ptr; \
50} \
51template<typename U> \
52inline bool operator _op_ (const U* o) const { \
53 return m_ptr _op_ o; \
54}
55
56// ---------------------------------------------------------------------------
57
58class RefBase
59{
60public:
61 void incStrong(const void* id) const;
62 void decStrong(const void* id) const;
63
64 void forceIncStrong(const void* id) const;
65
66 //! DEBUGGING ONLY: Get current strong ref count.
67 int32_t getStrongCount() const;
68
69 class weakref_type
70 {
71 public:
72 RefBase* refBase() const;
73
74 void incWeak(const void* id);
75 void decWeak(const void* id);
76
77 bool attemptIncStrong(const void* id);
78
79 //! This is only safe if you have set OBJECT_LIFETIME_FOREVER.
80 bool attemptIncWeak(const void* id);
81
82 //! DEBUGGING ONLY: Get current weak ref count.
83 int32_t getWeakCount() const;
84
85 //! DEBUGGING ONLY: Print references held on object.
86 void printRefs() const;
87
88 //! DEBUGGING ONLY: Enable tracking for this object.
89 // enable -- enable/disable tracking
90 // retain -- when tracking is enable, if true, then we save a stack trace
91 // for each reference and dereference; when retain == false, we
92 // match up references and dereferences and keep only the
93 // outstanding ones.
94
95 void trackMe(bool enable, bool retain);
96 };
97
98 weakref_type* createWeak(const void* id) const;
99
100 weakref_type* getWeakRefs() const;
101
102 //! DEBUGGING ONLY: Print references held on object.
103 inline void printRefs() const { getWeakRefs()->printRefs(); }
104
105 //! DEBUGGING ONLY: Enable tracking of object.
106 inline void trackMe(bool enable, bool retain)
107 {
108 getWeakRefs()->trackMe(enable, retain);
109 }
110
111protected:
112 RefBase();
113 virtual ~RefBase();
114
115 //! Flags for extendObjectLifetime()
116 enum {
117 OBJECT_LIFETIME_WEAK = 0x0001,
118 OBJECT_LIFETIME_FOREVER = 0x0003
119 };
120
121 void extendObjectLifetime(int32_t mode);
122
123 //! Flags for onIncStrongAttempted()
124 enum {
125 FIRST_INC_STRONG = 0x0001
126 };
127
128 virtual void onFirstRef();
129 virtual void onLastStrongRef(const void* id);
130 virtual bool onIncStrongAttempted(uint32_t flags, const void* id);
131 virtual void onLastWeakRef(const void* id);
132
133private:
134 friend class weakref_type;
135 class weakref_impl;
136
137 RefBase(const RefBase& o);
138 RefBase& operator=(const RefBase& o);
139
140 weakref_impl* const mRefs;
141};
142
143// ---------------------------------------------------------------------------
144
145template <typename T>
146class sp
147{
148public:
149 typedef typename RefBase::weakref_type weakref_type;
150
151 inline sp() : m_ptr(0) { }
152
153 sp(T* other);
154 sp(const sp<T>& other);
155 template<typename U> sp(U* other);
156 template<typename U> sp(const sp<U>& other);
157
158 ~sp();
159
160 // Assignment
161
162 sp& operator = (T* other);
163 sp& operator = (const sp<T>& other);
164
165 template<typename U> sp& operator = (const sp<U>& other);
166 template<typename U> sp& operator = (U* other);
167
168 //! Special optimization for use by ProcessState (and nobody else).
169 void force_set(T* other);
170
171 // Reset
172
173 void clear();
174
175 // Accessors
176
177 inline T& operator* () const { return *m_ptr; }
178 inline T* operator-> () const { return m_ptr; }
179 inline T* get() const { return m_ptr; }
180
181 // Operators
182
183 COMPARE(==)
184 COMPARE(!=)
185 COMPARE(>)
186 COMPARE(<)
187 COMPARE(<=)
188 COMPARE(>=)
189
190private:
191 template<typename Y> friend class sp;
192 template<typename Y> friend class wp;
193
194 // Optimization for wp::promote().
195 sp(T* p, weakref_type* refs);
196
197 T* m_ptr;
198};
199
200template <typename T>
201TextOutput& operator<<(TextOutput& to, const sp<T>& val);
202
203// ---------------------------------------------------------------------------
204
205template <typename T>
206class wp
207{
208public:
209 typedef typename RefBase::weakref_type weakref_type;
210
211 inline wp() : m_ptr(0) { }
212
213 wp(T* other);
214 wp(const wp<T>& other);
215 wp(const sp<T>& other);
216 template<typename U> wp(U* other);
217 template<typename U> wp(const sp<U>& other);
218 template<typename U> wp(const wp<U>& other);
219
220 ~wp();
221
222 // Assignment
223
224 wp& operator = (T* other);
225 wp& operator = (const wp<T>& other);
226 wp& operator = (const sp<T>& other);
227
228 template<typename U> wp& operator = (U* other);
229 template<typename U> wp& operator = (const wp<U>& other);
230 template<typename U> wp& operator = (const sp<U>& other);
231
232 void set_object_and_refs(T* other, weakref_type* refs);
233
234 // promotion to sp
235
236 sp<T> promote() const;
237
238 // Reset
239
240 void clear();
241
242 // Accessors
243
244 inline weakref_type* get_refs() const { return m_refs; }
245
246 inline T* unsafe_get() const { return m_ptr; }
247
248 // Operators
249
250 COMPARE(==)
251 COMPARE(!=)
252 COMPARE(>)
253 COMPARE(<)
254 COMPARE(<=)
255 COMPARE(>=)
256
257private:
258 template<typename Y> friend class sp;
259 template<typename Y> friend class wp;
260
261 T* m_ptr;
262 weakref_type* m_refs;
263};
264
265template <typename T>
266TextOutput& operator<<(TextOutput& to, const wp<T>& val);
267
268#undef COMPARE
269
270// ---------------------------------------------------------------------------
271// No user serviceable parts below here.
272
273template<typename T>
274sp<T>::sp(T* other)
275 : m_ptr(other)
276{
277 if (other) other->incStrong(this);
278}
279
280template<typename T>
281sp<T>::sp(const sp<T>& other)
282 : m_ptr(other.m_ptr)
283{
284 if (m_ptr) m_ptr->incStrong(this);
285}
286
287template<typename T> template<typename U>
288sp<T>::sp(U* other) : m_ptr(other)
289{
290 if (other) other->incStrong(this);
291}
292
293template<typename T> template<typename U>
294sp<T>::sp(const sp<U>& other)
295 : m_ptr(other.m_ptr)
296{
297 if (m_ptr) m_ptr->incStrong(this);
298}
299
300template<typename T>
301sp<T>::~sp()
302{
303 if (m_ptr) m_ptr->decStrong(this);
304}
305
306template<typename T>
307sp<T>& sp<T>::operator = (const sp<T>& other) {
308 if (other.m_ptr) other.m_ptr->incStrong(this);
309 if (m_ptr) m_ptr->decStrong(this);
310 m_ptr = other.m_ptr;
311 return *this;
312}
313
314template<typename T>
315sp<T>& sp<T>::operator = (T* other)
316{
317 if (other) other->incStrong(this);
318 if (m_ptr) m_ptr->decStrong(this);
319 m_ptr = other;
320 return *this;
321}
322
323template<typename T> template<typename U>
324sp<T>& sp<T>::operator = (const sp<U>& other)
325{
326 if (other.m_ptr) other.m_ptr->incStrong(this);
327 if (m_ptr) m_ptr->decStrong(this);
328 m_ptr = other.m_ptr;
329 return *this;
330}
331
332template<typename T> template<typename U>
333sp<T>& sp<T>::operator = (U* other)
334{
335 if (other) other->incStrong(this);
336 if (m_ptr) m_ptr->decStrong(this);
337 m_ptr = other;
338 return *this;
339}
340
341template<typename T>
342void sp<T>::force_set(T* other)
343{
344 other->forceIncStrong(this);
345 m_ptr = other;
346}
347
348template<typename T>
349void sp<T>::clear()
350{
351 if (m_ptr) {
352 m_ptr->decStrong(this);
353 m_ptr = 0;
354 }
355}
356
357template<typename T>
358sp<T>::sp(T* p, weakref_type* refs)
359 : m_ptr((p && refs->attemptIncStrong(this)) ? p : 0)
360{
361}
362
363template <typename T>
364inline TextOutput& operator<<(TextOutput& to, const sp<T>& val)
365{
366 to << "sp<>(" << val.get() << ")";
367 return to;
368}
369
370// ---------------------------------------------------------------------------
371
372template<typename T>
373wp<T>::wp(T* other)
374 : m_ptr(other)
375{
376 if (other) m_refs = other->createWeak(this);
377}
378
379template<typename T>
380wp<T>::wp(const wp<T>& other)
381 : m_ptr(other.m_ptr), m_refs(other.m_refs)
382{
383 if (m_ptr) m_refs->incWeak(this);
384}
385
386template<typename T>
387wp<T>::wp(const sp<T>& other)
388 : m_ptr(other.m_ptr)
389{
390 if (m_ptr) {
391 m_refs = m_ptr->createWeak(this);
392 }
393}
394
395template<typename T> template<typename U>
396wp<T>::wp(U* other)
397 : m_ptr(other)
398{
399 if (other) m_refs = other->createWeak(this);
400}
401
402template<typename T> template<typename U>
403wp<T>::wp(const wp<U>& other)
404 : m_ptr(other.m_ptr)
405{
406 if (m_ptr) {
407 m_refs = other.m_refs;
408 m_refs->incWeak(this);
409 }
410}
411
412template<typename T> template<typename U>
413wp<T>::wp(const sp<U>& other)
414 : m_ptr(other.m_ptr)
415{
416 if (m_ptr) {
417 m_refs = m_ptr->createWeak(this);
418 }
419}
420
421template<typename T>
422wp<T>::~wp()
423{
424 if (m_ptr) m_refs->decWeak(this);
425}
426
427template<typename T>
428wp<T>& wp<T>::operator = (T* other)
429{
430 weakref_type* newRefs =
431 other ? other->createWeak(this) : 0;
432 if (m_ptr) m_refs->decWeak(this);
433 m_ptr = other;
434 m_refs = newRefs;
435 return *this;
436}
437
438template<typename T>
439wp<T>& wp<T>::operator = (const wp<T>& other)
440{
441 if (other.m_ptr) other.m_refs->incWeak(this);
442 if (m_ptr) m_refs->decWeak(this);
443 m_ptr = other.m_ptr;
444 m_refs = other.m_refs;
445 return *this;
446}
447
448template<typename T>
449wp<T>& wp<T>::operator = (const sp<T>& other)
450{
451 weakref_type* newRefs =
452 other != NULL ? other->createWeak(this) : 0;
453 if (m_ptr) m_refs->decWeak(this);
454 m_ptr = other.get();
455 m_refs = newRefs;
456 return *this;
457}
458
459template<typename T> template<typename U>
460wp<T>& wp<T>::operator = (U* other)
461{
462 weakref_type* newRefs =
463 other ? other->createWeak(this) : 0;
464 if (m_ptr) m_refs->decWeak(this);
465 m_ptr = other;
466 m_refs = newRefs;
467 return *this;
468}
469
470template<typename T> template<typename U>
471wp<T>& wp<T>::operator = (const wp<U>& other)
472{
473 if (other.m_ptr) other.m_refs->incWeak(this);
474 if (m_ptr) m_refs->decWeak(this);
475 m_ptr = other.m_ptr;
476 m_refs = other.m_refs;
477 return *this;
478}
479
480template<typename T> template<typename U>
481wp<T>& wp<T>::operator = (const sp<U>& other)
482{
483 weakref_type* newRefs =
484 other != NULL ? other->createWeak(this) : 0;
485 if (m_ptr) m_refs->decWeak(this);
486 m_ptr = other.get();
487 m_refs = newRefs;
488 return *this;
489}
490
491template<typename T>
492void wp<T>::set_object_and_refs(T* other, weakref_type* refs)
493{
494 if (other) refs->incWeak(this);
495 if (m_ptr) m_refs->decWeak(this);
496 m_ptr = other;
497 m_refs = refs;
498}
499
500template<typename T>
501sp<T> wp<T>::promote() const
502{
503 return sp<T>(m_ptr, m_refs);
504}
505
506template<typename T>
507void wp<T>::clear()
508{
509 if (m_ptr) {
510 m_refs->decWeak(this);
511 m_ptr = 0;
512 }
513}
514
515template <typename T>
516inline TextOutput& operator<<(TextOutput& to, const wp<T>& val)
517{
518 to << "wp<>(" << val.unsafe_get() << ")";
519 return to;
520}
521
522}; // namespace android
523
524// ---------------------------------------------------------------------------
525
526#endif // ANDROID_REF_BASE_H