blob: 412622596c85b2a58c794d0f12a9d585b29dbef6 [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// ---------------------------------------------------------------------------
Mathias Agopianf14a1042011-02-16 20:23:43 -080054class ReferenceMover;
55class ReferenceConverterBase {
56public:
57 virtual size_t getReferenceTypeSize() const = 0;
58 virtual void* getReferenceBase(void const*) const = 0;
59 inline virtual ~ReferenceConverterBase() { }
60};
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080061
62// ---------------------------------------------------------------------------
63
64class RefBase
65{
66public:
67 void incStrong(const void* id) const;
68 void decStrong(const void* id) const;
69
70 void forceIncStrong(const void* id) const;
71
72 //! DEBUGGING ONLY: Get current strong ref count.
73 int32_t getStrongCount() const;
74
75 class weakref_type
76 {
77 public:
78 RefBase* refBase() const;
79
80 void incWeak(const void* id);
81 void decWeak(const void* id);
82
83 bool attemptIncStrong(const void* id);
84
85 //! This is only safe if you have set OBJECT_LIFETIME_FOREVER.
86 bool attemptIncWeak(const void* id);
87
88 //! DEBUGGING ONLY: Get current weak ref count.
89 int32_t getWeakCount() const;
90
91 //! DEBUGGING ONLY: Print references held on object.
92 void printRefs() const;
93
94 //! DEBUGGING ONLY: Enable tracking for this object.
95 // enable -- enable/disable tracking
96 // retain -- when tracking is enable, if true, then we save a stack trace
97 // for each reference and dereference; when retain == false, we
98 // match up references and dereferences and keep only the
99 // outstanding ones.
100
101 void trackMe(bool enable, bool retain);
102 };
103
104 weakref_type* createWeak(const void* id) const;
105
106 weakref_type* getWeakRefs() const;
107
108 //! DEBUGGING ONLY: Print references held on object.
109 inline void printRefs() const { getWeakRefs()->printRefs(); }
110
111 //! DEBUGGING ONLY: Enable tracking of object.
112 inline void trackMe(bool enable, bool retain)
113 {
114 getWeakRefs()->trackMe(enable, retain);
115 }
116
Mathias Agopianf14a1042011-02-16 20:23:43 -0800117 typedef RefBase basetype;
118
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800119protected:
120 RefBase();
121 virtual ~RefBase();
Mathias Agopian20aeb1c2011-05-19 18:03:31 -0700122
123 // called when the last reference goes away. this is responsible for
124 // calling the destructor. The default implementation just does
125 // "delete this;".
126 // Make sure to never acquire a strong reference from this function. The
127 // same restrictions than for destructors apply.
128 virtual void destroy() const;
129
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800130 //! Flags for extendObjectLifetime()
131 enum {
132 OBJECT_LIFETIME_WEAK = 0x0001,
133 OBJECT_LIFETIME_FOREVER = 0x0003
134 };
135
136 void extendObjectLifetime(int32_t mode);
137
138 //! Flags for onIncStrongAttempted()
139 enum {
140 FIRST_INC_STRONG = 0x0001
141 };
142
143 virtual void onFirstRef();
144 virtual void onLastStrongRef(const void* id);
145 virtual bool onIncStrongAttempted(uint32_t flags, const void* id);
146 virtual void onLastWeakRef(const void* id);
147
148private:
Mathias Agopianf14a1042011-02-16 20:23:43 -0800149 friend class ReferenceMover;
150 static void moveReferences(void* d, void const* s, size_t n,
151 const ReferenceConverterBase& caster);
152
153private:
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800154 friend class weakref_type;
155 class weakref_impl;
156
157 RefBase(const RefBase& o);
158 RefBase& operator=(const RefBase& o);
159
160 weakref_impl* const mRefs;
161};
162
163// ---------------------------------------------------------------------------
164
165template <class T>
166class LightRefBase
167{
168public:
169 inline LightRefBase() : mCount(0) { }
170 inline void incStrong(const void* id) const {
171 android_atomic_inc(&mCount);
172 }
173 inline void decStrong(const void* id) const {
174 if (android_atomic_dec(&mCount) == 1) {
175 delete static_cast<const T*>(this);
176 }
177 }
Mathias Agopian0926f502009-05-04 14:17:04 -0700178 //! DEBUGGING ONLY: Get current strong ref count.
179 inline int32_t getStrongCount() const {
180 return mCount;
181 }
Mathias Agopianf14a1042011-02-16 20:23:43 -0800182
183 typedef LightRefBase<T> basetype;
184
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800185protected:
186 inline ~LightRefBase() { }
Mathias Agopianf14a1042011-02-16 20:23:43 -0800187
188private:
189 friend class ReferenceMover;
190 inline static void moveReferences(void* d, void const* s, size_t n,
191 const ReferenceConverterBase& caster) { }
192
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800193private:
194 mutable volatile int32_t mCount;
195};
196
197// ---------------------------------------------------------------------------
198
199template <typename T>
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800200class wp
201{
202public:
203 typedef typename RefBase::weakref_type weakref_type;
204
205 inline wp() : m_ptr(0) { }
206
207 wp(T* other);
208 wp(const wp<T>& other);
209 wp(const sp<T>& other);
210 template<typename U> wp(U* other);
211 template<typename U> wp(const sp<U>& other);
212 template<typename U> wp(const wp<U>& other);
213
214 ~wp();
215
216 // Assignment
217
218 wp& operator = (T* other);
219 wp& operator = (const wp<T>& other);
220 wp& operator = (const sp<T>& other);
221
222 template<typename U> wp& operator = (U* other);
223 template<typename U> wp& operator = (const wp<U>& other);
224 template<typename U> wp& operator = (const sp<U>& other);
225
226 void set_object_and_refs(T* other, weakref_type* refs);
227
228 // promotion to sp
229
230 sp<T> promote() const;
231
232 // Reset
233
234 void clear();
235
236 // Accessors
237
238 inline weakref_type* get_refs() const { return m_refs; }
239
240 inline T* unsafe_get() const { return m_ptr; }
241
242 // Operators
Mathias Agopian7802bbd2011-02-09 18:38:55 -0800243
244 COMPARE_WEAK(==)
245 COMPARE_WEAK(!=)
246 COMPARE_WEAK(>)
247 COMPARE_WEAK(<)
248 COMPARE_WEAK(<=)
249 COMPARE_WEAK(>=)
250
251 inline bool operator == (const wp<T>& o) const {
252 return (m_ptr == o.m_ptr) && (m_refs == o.m_refs);
253 }
254 template<typename U>
255 inline bool operator == (const wp<U>& o) const {
256 return m_ptr == o.m_ptr;
257 }
258
259 inline bool operator > (const wp<T>& o) const {
260 return (m_ptr == o.m_ptr) ? (m_refs > o.m_refs) : (m_ptr > o.m_ptr);
261 }
262 template<typename U>
263 inline bool operator > (const wp<U>& o) const {
264 return (m_ptr == o.m_ptr) ? (m_refs > o.m_refs) : (m_ptr > o.m_ptr);
265 }
266
267 inline bool operator < (const wp<T>& o) const {
268 return (m_ptr == o.m_ptr) ? (m_refs < o.m_refs) : (m_ptr < o.m_ptr);
269 }
270 template<typename U>
271 inline bool operator < (const wp<U>& o) const {
272 return (m_ptr == o.m_ptr) ? (m_refs < o.m_refs) : (m_ptr < o.m_ptr);
273 }
274 inline bool operator != (const wp<T>& o) const { return m_refs != o.m_refs; }
275 template<typename U> inline bool operator != (const wp<U>& o) const { return !operator == (o); }
276 inline bool operator <= (const wp<T>& o) const { return !operator > (o); }
277 template<typename U> inline bool operator <= (const wp<U>& o) const { return !operator > (o); }
278 inline bool operator >= (const wp<T>& o) const { return !operator < (o); }
279 template<typename U> inline bool operator >= (const wp<U>& o) const { return !operator < (o); }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800280
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
Mathias Agopian7802bbd2011-02-09 18:38:55 -0800292#undef COMPARE_WEAK
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800293
294// ---------------------------------------------------------------------------
295// No user serviceable parts below here.
296
297template<typename T>
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800298wp<T>::wp(T* other)
299 : m_ptr(other)
300{
301 if (other) m_refs = other->createWeak(this);
302}
303
304template<typename T>
305wp<T>::wp(const wp<T>& other)
306 : m_ptr(other.m_ptr), m_refs(other.m_refs)
307{
308 if (m_ptr) m_refs->incWeak(this);
309}
310
311template<typename T>
312wp<T>::wp(const sp<T>& other)
313 : m_ptr(other.m_ptr)
314{
315 if (m_ptr) {
316 m_refs = m_ptr->createWeak(this);
317 }
318}
319
320template<typename T> template<typename U>
321wp<T>::wp(U* other)
322 : m_ptr(other)
323{
324 if (other) m_refs = other->createWeak(this);
325}
326
327template<typename T> template<typename U>
328wp<T>::wp(const wp<U>& other)
329 : m_ptr(other.m_ptr)
330{
331 if (m_ptr) {
332 m_refs = other.m_refs;
333 m_refs->incWeak(this);
334 }
335}
336
337template<typename T> template<typename U>
338wp<T>::wp(const sp<U>& other)
339 : m_ptr(other.m_ptr)
340{
341 if (m_ptr) {
342 m_refs = m_ptr->createWeak(this);
343 }
344}
345
346template<typename T>
347wp<T>::~wp()
348{
349 if (m_ptr) m_refs->decWeak(this);
350}
351
352template<typename T>
353wp<T>& wp<T>::operator = (T* other)
354{
355 weakref_type* newRefs =
356 other ? other->createWeak(this) : 0;
357 if (m_ptr) m_refs->decWeak(this);
358 m_ptr = other;
359 m_refs = newRefs;
360 return *this;
361}
362
363template<typename T>
364wp<T>& wp<T>::operator = (const wp<T>& other)
365{
Mathias Agopian8c3c51b2010-06-24 21:49:02 -0700366 weakref_type* otherRefs(other.m_refs);
367 T* otherPtr(other.m_ptr);
368 if (otherPtr) otherRefs->incWeak(this);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800369 if (m_ptr) m_refs->decWeak(this);
Mathias Agopian8c3c51b2010-06-24 21:49:02 -0700370 m_ptr = otherPtr;
371 m_refs = otherRefs;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800372 return *this;
373}
374
375template<typename T>
376wp<T>& wp<T>::operator = (const sp<T>& other)
377{
378 weakref_type* newRefs =
379 other != NULL ? other->createWeak(this) : 0;
Mathias Agopian8c3c51b2010-06-24 21:49:02 -0700380 T* otherPtr(other.m_ptr);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800381 if (m_ptr) m_refs->decWeak(this);
Mathias Agopian8c3c51b2010-06-24 21:49:02 -0700382 m_ptr = otherPtr;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800383 m_refs = newRefs;
384 return *this;
385}
386
387template<typename T> template<typename U>
388wp<T>& wp<T>::operator = (U* other)
389{
390 weakref_type* newRefs =
391 other ? other->createWeak(this) : 0;
392 if (m_ptr) m_refs->decWeak(this);
393 m_ptr = other;
394 m_refs = newRefs;
395 return *this;
396}
397
398template<typename T> template<typename U>
399wp<T>& wp<T>::operator = (const wp<U>& other)
400{
Mathias Agopian8c3c51b2010-06-24 21:49:02 -0700401 weakref_type* otherRefs(other.m_refs);
402 U* otherPtr(other.m_ptr);
403 if (otherPtr) otherRefs->incWeak(this);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800404 if (m_ptr) m_refs->decWeak(this);
Mathias Agopian8c3c51b2010-06-24 21:49:02 -0700405 m_ptr = otherPtr;
406 m_refs = otherRefs;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800407 return *this;
408}
409
410template<typename T> template<typename U>
411wp<T>& wp<T>::operator = (const sp<U>& other)
412{
413 weakref_type* newRefs =
414 other != NULL ? other->createWeak(this) : 0;
Mathias Agopian8c3c51b2010-06-24 21:49:02 -0700415 U* otherPtr(other.m_ptr);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800416 if (m_ptr) m_refs->decWeak(this);
Mathias Agopian8c3c51b2010-06-24 21:49:02 -0700417 m_ptr = otherPtr;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800418 m_refs = newRefs;
419 return *this;
420}
421
422template<typename T>
423void wp<T>::set_object_and_refs(T* other, weakref_type* refs)
424{
425 if (other) refs->incWeak(this);
426 if (m_ptr) m_refs->decWeak(this);
427 m_ptr = other;
428 m_refs = refs;
429}
430
431template<typename T>
432sp<T> wp<T>::promote() const
433{
Mathias Agopiand0050042011-02-24 18:12:34 -0800434 sp<T> result;
435 if (m_ptr && m_refs->attemptIncStrong(&result)) {
436 result.set_pointer(m_ptr);
437 }
438 return result;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800439}
440
441template<typename T>
442void wp<T>::clear()
443{
444 if (m_ptr) {
445 m_refs->decWeak(this);
446 m_ptr = 0;
447 }
448}
449
450template <typename T>
451inline TextOutput& operator<<(TextOutput& to, const wp<T>& val)
452{
Mathias Agopiana08ef492011-02-16 15:23:08 -0800453 return printWeakPointer(to, val.unsafe_get());
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800454}
455
Mathias Agopianf14a1042011-02-16 20:23:43 -0800456// ---------------------------------------------------------------------------
457
458// this class just serves as a namespace so TYPE::moveReferences can stay
459// private.
460
461class ReferenceMover {
462 // StrongReferenceCast and WeakReferenceCast do the impedance matching
463 // between the generic (void*) implementation in Refbase and the strongly typed
464 // template specializations below.
465
466 template <typename TYPE>
467 struct StrongReferenceCast : public ReferenceConverterBase {
468 virtual size_t getReferenceTypeSize() const { return sizeof( sp<TYPE> ); }
469 virtual void* getReferenceBase(void const* p) const {
470 sp<TYPE> const* sptr(reinterpret_cast<sp<TYPE> const*>(p));
471 return static_cast<typename TYPE::basetype *>(sptr->get());
472 }
473 };
474
475 template <typename TYPE>
476 struct WeakReferenceCast : public ReferenceConverterBase {
477 virtual size_t getReferenceTypeSize() const { return sizeof( wp<TYPE> ); }
478 virtual void* getReferenceBase(void const* p) const {
479 wp<TYPE> const* sptr(reinterpret_cast<wp<TYPE> const*>(p));
480 return static_cast<typename TYPE::basetype *>(sptr->unsafe_get());
481 }
482 };
483
484public:
485 template<typename TYPE> static inline
486 void move_references(sp<TYPE>* d, sp<TYPE> const* s, size_t n) {
487 memmove(d, s, n*sizeof(sp<TYPE>));
488 StrongReferenceCast<TYPE> caster;
489 TYPE::moveReferences(d, s, n, caster);
490 }
491 template<typename TYPE> static inline
492 void move_references(wp<TYPE>* d, wp<TYPE> const* s, size_t n) {
493 memmove(d, s, n*sizeof(wp<TYPE>));
494 WeakReferenceCast<TYPE> caster;
495 TYPE::moveReferences(d, s, n, caster);
496 }
497};
498
499// specialization for moving sp<> and wp<> types.
500// these are used by the [Sorted|Keyed]Vector<> implementations
501// sp<> and wp<> need to be handled specially, because they do not
502// have trivial copy operation in the general case (see RefBase.cpp
503// when DEBUG ops are enabled), but can be implemented very
504// efficiently in most cases.
505
506template<typename TYPE> inline
507void move_forward_type(sp<TYPE>* d, sp<TYPE> const* s, size_t n) {
508 ReferenceMover::move_references(d, s, n);
509}
510
511template<typename TYPE> inline
512void move_backward_type(sp<TYPE>* d, sp<TYPE> const* s, size_t n) {
513 ReferenceMover::move_references(d, s, n);
514}
515
516template<typename TYPE> inline
517void move_forward_type(wp<TYPE>* d, wp<TYPE> const* s, size_t n) {
518 ReferenceMover::move_references(d, s, n);
519}
520
521template<typename TYPE> inline
522void move_backward_type(wp<TYPE>* d, wp<TYPE> const* s, size_t n) {
523 ReferenceMover::move_references(d, s, n);
524}
525
526
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800527}; // namespace android
528
529// ---------------------------------------------------------------------------
530
531#endif // ANDROID_REF_BASE_H