blob: e88cb29b7f9941b1c12828e7b2b4b5fd34f0a47c [file] [log] [blame]
The Android Open Source Projectedbf3b62009-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 Projectedbf3b62009-03-03 19:31:44 -080021
22#include <stdint.h>
23#include <sys/types.h>
24#include <stdlib.h>
Mathias Agopianf14a1042011-02-16 20:23:43 -080025#include <string.h>
26
27#include <utils/StrongPointer.h>
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080028
29// ---------------------------------------------------------------------------
30namespace android {
31
Mathias Agopiana08ef492011-02-16 15:23:08 -080032class TextOutput;
Mathias Agopiana08ef492011-02-16 15:23:08 -080033TextOutput& printWeakPointer(TextOutput& to, const void* val);
34
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080035// ---------------------------------------------------------------------------
36
Mathias Agopian7802bbd2011-02-09 18:38:55 -080037#define COMPARE_WEAK(_op_) \
The Android Open Source Projectedbf3b62009-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 Projectedbf3b62009-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 Agopian7802bbd2011-02-09 18:38:55 -080049inline bool operator _op_ (const U* o) const { \
50 return m_ptr _op_ o; \
51}
52
Mathias Agopianf14a1042011-02-16 20:23:43 -080053// ---------------------------------------------------------------------------
54
55class ReferenceMover;
56class ReferenceConverterBase {
57public:
58 virtual size_t getReferenceTypeSize() const = 0;
59 virtual void* getReferenceBase(void const*) const = 0;
60 inline virtual ~ReferenceConverterBase() { }
61};
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080062
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
Mathias Agopianf14a1042011-02-16 20:23:43 -0800118 typedef RefBase basetype;
119
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800120protected:
121 RefBase();
122 virtual ~RefBase();
Mathias Agopianf3d939c2011-06-06 09:55:15 -0700123
124 // called when the last reference goes away. this is responsible for
125 // calling the destructor. The default implementation just does
126 // "delete this;".
127 // Make sure to never acquire a strong reference from this function. The
128 // same restrictions than for destructors apply.
129 virtual void destroy() const;
130
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800131 //! Flags for extendObjectLifetime()
132 enum {
133 OBJECT_LIFETIME_WEAK = 0x0001,
134 OBJECT_LIFETIME_FOREVER = 0x0003
135 };
136
137 void extendObjectLifetime(int32_t mode);
138
139 //! Flags for onIncStrongAttempted()
140 enum {
141 FIRST_INC_STRONG = 0x0001
142 };
143
144 virtual void onFirstRef();
145 virtual void onLastStrongRef(const void* id);
146 virtual bool onIncStrongAttempted(uint32_t flags, const void* id);
147 virtual void onLastWeakRef(const void* id);
148
149private:
Mathias Agopianf14a1042011-02-16 20:23:43 -0800150 friend class ReferenceMover;
151 static void moveReferences(void* d, void const* s, size_t n,
152 const ReferenceConverterBase& caster);
153
154private:
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800155 friend class weakref_type;
156 class weakref_impl;
157
158 RefBase(const RefBase& o);
159 RefBase& operator=(const RefBase& o);
160
161 weakref_impl* const mRefs;
162};
163
164// ---------------------------------------------------------------------------
165
166template <class T>
167class LightRefBase
168{
169public:
170 inline LightRefBase() : mCount(0) { }
171 inline void incStrong(const void* id) const {
172 android_atomic_inc(&mCount);
173 }
174 inline void decStrong(const void* id) const {
175 if (android_atomic_dec(&mCount) == 1) {
176 delete static_cast<const T*>(this);
177 }
178 }
Mathias Agopian0926f502009-05-04 14:17:04 -0700179 //! DEBUGGING ONLY: Get current strong ref count.
180 inline int32_t getStrongCount() const {
181 return mCount;
182 }
Mathias Agopianf14a1042011-02-16 20:23:43 -0800183
184 typedef LightRefBase<T> basetype;
185
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800186protected:
187 inline ~LightRefBase() { }
Mathias Agopianf14a1042011-02-16 20:23:43 -0800188
189private:
190 friend class ReferenceMover;
191 inline static void moveReferences(void* d, void const* s, size_t n,
192 const ReferenceConverterBase& caster) { }
193
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800194private:
195 mutable volatile int32_t mCount;
196};
197
198// ---------------------------------------------------------------------------
199
200template <typename T>
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800201class wp
202{
203public:
204 typedef typename RefBase::weakref_type weakref_type;
205
206 inline wp() : m_ptr(0) { }
207
208 wp(T* other);
209 wp(const wp<T>& other);
210 wp(const sp<T>& other);
211 template<typename U> wp(U* other);
212 template<typename U> wp(const sp<U>& other);
213 template<typename U> wp(const wp<U>& other);
214
215 ~wp();
216
217 // Assignment
218
219 wp& operator = (T* other);
220 wp& operator = (const wp<T>& other);
221 wp& operator = (const sp<T>& other);
222
223 template<typename U> wp& operator = (U* other);
224 template<typename U> wp& operator = (const wp<U>& other);
225 template<typename U> wp& operator = (const sp<U>& other);
226
227 void set_object_and_refs(T* other, weakref_type* refs);
228
229 // promotion to sp
230
231 sp<T> promote() const;
232
233 // Reset
234
235 void clear();
236
237 // Accessors
238
239 inline weakref_type* get_refs() const { return m_refs; }
240
241 inline T* unsafe_get() const { return m_ptr; }
242
243 // Operators
Mathias Agopian7802bbd2011-02-09 18:38:55 -0800244
245 COMPARE_WEAK(==)
246 COMPARE_WEAK(!=)
247 COMPARE_WEAK(>)
248 COMPARE_WEAK(<)
249 COMPARE_WEAK(<=)
250 COMPARE_WEAK(>=)
251
252 inline bool operator == (const wp<T>& o) const {
253 return (m_ptr == o.m_ptr) && (m_refs == o.m_refs);
254 }
255 template<typename U>
256 inline bool operator == (const wp<U>& o) const {
257 return m_ptr == o.m_ptr;
258 }
259
260 inline bool operator > (const wp<T>& o) const {
261 return (m_ptr == o.m_ptr) ? (m_refs > o.m_refs) : (m_ptr > o.m_ptr);
262 }
263 template<typename U>
264 inline bool operator > (const wp<U>& o) const {
265 return (m_ptr == o.m_ptr) ? (m_refs > o.m_refs) : (m_ptr > o.m_ptr);
266 }
267
268 inline bool operator < (const wp<T>& o) const {
269 return (m_ptr == o.m_ptr) ? (m_refs < o.m_refs) : (m_ptr < o.m_ptr);
270 }
271 template<typename U>
272 inline bool operator < (const wp<U>& o) const {
273 return (m_ptr == o.m_ptr) ? (m_refs < o.m_refs) : (m_ptr < o.m_ptr);
274 }
275 inline bool operator != (const wp<T>& o) const { return m_refs != o.m_refs; }
276 template<typename U> inline bool operator != (const wp<U>& o) const { return !operator == (o); }
277 inline bool operator <= (const wp<T>& o) const { return !operator > (o); }
278 template<typename U> inline bool operator <= (const wp<U>& o) const { return !operator > (o); }
279 inline bool operator >= (const wp<T>& o) const { return !operator < (o); }
280 template<typename U> inline bool operator >= (const wp<U>& o) const { return !operator < (o); }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800281
282private:
283 template<typename Y> friend class sp;
284 template<typename Y> friend class wp;
285
286 T* m_ptr;
287 weakref_type* m_refs;
288};
289
290template <typename T>
291TextOutput& operator<<(TextOutput& to, const wp<T>& val);
292
Mathias Agopian7802bbd2011-02-09 18:38:55 -0800293#undef COMPARE_WEAK
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800294
295// ---------------------------------------------------------------------------
296// No user serviceable parts below here.
297
298template<typename T>
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800299wp<T>::wp(T* other)
300 : m_ptr(other)
301{
302 if (other) m_refs = other->createWeak(this);
303}
304
305template<typename T>
306wp<T>::wp(const wp<T>& other)
307 : m_ptr(other.m_ptr), m_refs(other.m_refs)
308{
309 if (m_ptr) m_refs->incWeak(this);
310}
311
312template<typename T>
313wp<T>::wp(const sp<T>& other)
314 : m_ptr(other.m_ptr)
315{
316 if (m_ptr) {
317 m_refs = m_ptr->createWeak(this);
318 }
319}
320
321template<typename T> template<typename U>
322wp<T>::wp(U* other)
323 : m_ptr(other)
324{
325 if (other) m_refs = other->createWeak(this);
326}
327
328template<typename T> template<typename U>
329wp<T>::wp(const wp<U>& other)
330 : m_ptr(other.m_ptr)
331{
332 if (m_ptr) {
333 m_refs = other.m_refs;
334 m_refs->incWeak(this);
335 }
336}
337
338template<typename T> template<typename U>
339wp<T>::wp(const sp<U>& other)
340 : m_ptr(other.m_ptr)
341{
342 if (m_ptr) {
343 m_refs = m_ptr->createWeak(this);
344 }
345}
346
347template<typename T>
348wp<T>::~wp()
349{
350 if (m_ptr) m_refs->decWeak(this);
351}
352
353template<typename T>
354wp<T>& wp<T>::operator = (T* other)
355{
356 weakref_type* newRefs =
357 other ? other->createWeak(this) : 0;
358 if (m_ptr) m_refs->decWeak(this);
359 m_ptr = other;
360 m_refs = newRefs;
361 return *this;
362}
363
364template<typename T>
365wp<T>& wp<T>::operator = (const wp<T>& other)
366{
Mathias Agopian8c3c51b2010-06-24 21:49:02 -0700367 weakref_type* otherRefs(other.m_refs);
368 T* otherPtr(other.m_ptr);
369 if (otherPtr) otherRefs->incWeak(this);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800370 if (m_ptr) m_refs->decWeak(this);
Mathias Agopian8c3c51b2010-06-24 21:49:02 -0700371 m_ptr = otherPtr;
372 m_refs = otherRefs;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800373 return *this;
374}
375
376template<typename T>
377wp<T>& wp<T>::operator = (const sp<T>& other)
378{
379 weakref_type* newRefs =
380 other != NULL ? other->createWeak(this) : 0;
Mathias Agopian8c3c51b2010-06-24 21:49:02 -0700381 T* otherPtr(other.m_ptr);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800382 if (m_ptr) m_refs->decWeak(this);
Mathias Agopian8c3c51b2010-06-24 21:49:02 -0700383 m_ptr = otherPtr;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800384 m_refs = newRefs;
385 return *this;
386}
387
388template<typename T> template<typename U>
389wp<T>& wp<T>::operator = (U* other)
390{
391 weakref_type* newRefs =
392 other ? other->createWeak(this) : 0;
393 if (m_ptr) m_refs->decWeak(this);
394 m_ptr = other;
395 m_refs = newRefs;
396 return *this;
397}
398
399template<typename T> template<typename U>
400wp<T>& wp<T>::operator = (const wp<U>& other)
401{
Mathias Agopian8c3c51b2010-06-24 21:49:02 -0700402 weakref_type* otherRefs(other.m_refs);
403 U* otherPtr(other.m_ptr);
404 if (otherPtr) otherRefs->incWeak(this);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800405 if (m_ptr) m_refs->decWeak(this);
Mathias Agopian8c3c51b2010-06-24 21:49:02 -0700406 m_ptr = otherPtr;
407 m_refs = otherRefs;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800408 return *this;
409}
410
411template<typename T> template<typename U>
412wp<T>& wp<T>::operator = (const sp<U>& other)
413{
414 weakref_type* newRefs =
415 other != NULL ? other->createWeak(this) : 0;
Mathias Agopian8c3c51b2010-06-24 21:49:02 -0700416 U* otherPtr(other.m_ptr);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800417 if (m_ptr) m_refs->decWeak(this);
Mathias Agopian8c3c51b2010-06-24 21:49:02 -0700418 m_ptr = otherPtr;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800419 m_refs = newRefs;
420 return *this;
421}
422
423template<typename T>
424void wp<T>::set_object_and_refs(T* other, weakref_type* refs)
425{
426 if (other) refs->incWeak(this);
427 if (m_ptr) m_refs->decWeak(this);
428 m_ptr = other;
429 m_refs = refs;
430}
431
432template<typename T>
433sp<T> wp<T>::promote() const
434{
Mathias Agopiand0050042011-02-24 18:12:34 -0800435 sp<T> result;
436 if (m_ptr && m_refs->attemptIncStrong(&result)) {
437 result.set_pointer(m_ptr);
438 }
439 return result;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800440}
441
442template<typename T>
443void wp<T>::clear()
444{
445 if (m_ptr) {
446 m_refs->decWeak(this);
447 m_ptr = 0;
448 }
449}
450
451template <typename T>
452inline TextOutput& operator<<(TextOutput& to, const wp<T>& val)
453{
Mathias Agopiana08ef492011-02-16 15:23:08 -0800454 return printWeakPointer(to, val.unsafe_get());
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800455}
456
Mathias Agopianf14a1042011-02-16 20:23:43 -0800457// ---------------------------------------------------------------------------
458
459// this class just serves as a namespace so TYPE::moveReferences can stay
460// private.
461
462class ReferenceMover {
463 // StrongReferenceCast and WeakReferenceCast do the impedance matching
464 // between the generic (void*) implementation in Refbase and the strongly typed
465 // template specializations below.
466
467 template <typename TYPE>
468 struct StrongReferenceCast : public ReferenceConverterBase {
469 virtual size_t getReferenceTypeSize() const { return sizeof( sp<TYPE> ); }
470 virtual void* getReferenceBase(void const* p) const {
471 sp<TYPE> const* sptr(reinterpret_cast<sp<TYPE> const*>(p));
472 return static_cast<typename TYPE::basetype *>(sptr->get());
473 }
474 };
475
476 template <typename TYPE>
477 struct WeakReferenceCast : public ReferenceConverterBase {
478 virtual size_t getReferenceTypeSize() const { return sizeof( wp<TYPE> ); }
479 virtual void* getReferenceBase(void const* p) const {
480 wp<TYPE> const* sptr(reinterpret_cast<wp<TYPE> const*>(p));
481 return static_cast<typename TYPE::basetype *>(sptr->unsafe_get());
482 }
483 };
484
485public:
486 template<typename TYPE> static inline
487 void move_references(sp<TYPE>* d, sp<TYPE> const* s, size_t n) {
488 memmove(d, s, n*sizeof(sp<TYPE>));
489 StrongReferenceCast<TYPE> caster;
490 TYPE::moveReferences(d, s, n, caster);
491 }
492 template<typename TYPE> static inline
493 void move_references(wp<TYPE>* d, wp<TYPE> const* s, size_t n) {
494 memmove(d, s, n*sizeof(wp<TYPE>));
495 WeakReferenceCast<TYPE> caster;
496 TYPE::moveReferences(d, s, n, caster);
497 }
498};
499
500// specialization for moving sp<> and wp<> types.
501// these are used by the [Sorted|Keyed]Vector<> implementations
502// sp<> and wp<> need to be handled specially, because they do not
503// have trivial copy operation in the general case (see RefBase.cpp
504// when DEBUG ops are enabled), but can be implemented very
505// efficiently in most cases.
506
507template<typename TYPE> inline
508void move_forward_type(sp<TYPE>* d, sp<TYPE> const* s, size_t n) {
509 ReferenceMover::move_references(d, s, n);
510}
511
512template<typename TYPE> inline
513void move_backward_type(sp<TYPE>* d, sp<TYPE> const* s, size_t n) {
514 ReferenceMover::move_references(d, s, n);
515}
516
517template<typename TYPE> inline
518void move_forward_type(wp<TYPE>* d, wp<TYPE> const* s, size_t n) {
519 ReferenceMover::move_references(d, s, n);
520}
521
522template<typename TYPE> inline
523void move_backward_type(wp<TYPE>* d, wp<TYPE> const* s, size_t n) {
524 ReferenceMover::move_references(d, s, n);
525}
526
527
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800528}; // namespace android
529
530// ---------------------------------------------------------------------------
531
532#endif // ANDROID_REF_BASE_H