blob: ca170827f1b294a37bdd51a904f76b5129b5da49 [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
Mathias Agopianddc31c32011-06-12 18:05:53 -0700119 // used to override the RefBase destruction.
120 class Destroyer {
121 friend class RefBase;
Mathias Agopian7a87ec72011-06-14 11:50:22 -0700122 friend class weakref_type;
Mathias Agopianddc31c32011-06-12 18:05:53 -0700123 public:
124 virtual ~Destroyer();
125 private:
126 virtual void destroy(RefBase const* base) = 0;
127 };
128
129 // Make sure to never acquire a strong reference from this function. The
130 // same restrictions than for destructors apply.
131 void setDestroyer(Destroyer* destroyer);
132
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800133protected:
134 RefBase();
135 virtual ~RefBase();
Mathias Agopian20aeb1c2011-05-19 18:03:31 -0700136
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800137 //! Flags for extendObjectLifetime()
138 enum {
139 OBJECT_LIFETIME_WEAK = 0x0001,
140 OBJECT_LIFETIME_FOREVER = 0x0003
141 };
142
143 void extendObjectLifetime(int32_t mode);
144
145 //! Flags for onIncStrongAttempted()
146 enum {
147 FIRST_INC_STRONG = 0x0001
148 };
149
150 virtual void onFirstRef();
151 virtual void onLastStrongRef(const void* id);
152 virtual bool onIncStrongAttempted(uint32_t flags, const void* id);
153 virtual void onLastWeakRef(const void* id);
154
155private:
Mathias Agopianf14a1042011-02-16 20:23:43 -0800156 friend class ReferenceMover;
157 static void moveReferences(void* d, void const* s, size_t n,
158 const ReferenceConverterBase& caster);
159
160private:
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800161 friend class weakref_type;
162 class weakref_impl;
163
164 RefBase(const RefBase& o);
165 RefBase& operator=(const RefBase& o);
166
167 weakref_impl* const mRefs;
168};
169
170// ---------------------------------------------------------------------------
171
172template <class T>
173class LightRefBase
174{
175public:
176 inline LightRefBase() : mCount(0) { }
177 inline void incStrong(const void* id) const {
178 android_atomic_inc(&mCount);
179 }
180 inline void decStrong(const void* id) const {
181 if (android_atomic_dec(&mCount) == 1) {
182 delete static_cast<const T*>(this);
183 }
184 }
Mathias Agopian0926f502009-05-04 14:17:04 -0700185 //! DEBUGGING ONLY: Get current strong ref count.
186 inline int32_t getStrongCount() const {
187 return mCount;
188 }
Mathias Agopianf14a1042011-02-16 20:23:43 -0800189
190 typedef LightRefBase<T> basetype;
191
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800192protected:
193 inline ~LightRefBase() { }
Mathias Agopianf14a1042011-02-16 20:23:43 -0800194
195private:
196 friend class ReferenceMover;
197 inline static void moveReferences(void* d, void const* s, size_t n,
198 const ReferenceConverterBase& caster) { }
199
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800200private:
201 mutable volatile int32_t mCount;
202};
203
204// ---------------------------------------------------------------------------
205
206template <typename T>
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800207class wp
208{
209public:
210 typedef typename RefBase::weakref_type weakref_type;
211
212 inline wp() : m_ptr(0) { }
213
214 wp(T* other);
215 wp(const wp<T>& other);
216 wp(const sp<T>& other);
217 template<typename U> wp(U* other);
218 template<typename U> wp(const sp<U>& other);
219 template<typename U> wp(const wp<U>& other);
220
221 ~wp();
222
223 // Assignment
224
225 wp& operator = (T* other);
226 wp& operator = (const wp<T>& other);
227 wp& operator = (const sp<T>& other);
228
229 template<typename U> wp& operator = (U* other);
230 template<typename U> wp& operator = (const wp<U>& other);
231 template<typename U> wp& operator = (const sp<U>& other);
232
233 void set_object_and_refs(T* other, weakref_type* refs);
234
235 // promotion to sp
236
237 sp<T> promote() const;
238
239 // Reset
240
241 void clear();
242
243 // Accessors
244
245 inline weakref_type* get_refs() const { return m_refs; }
246
247 inline T* unsafe_get() const { return m_ptr; }
248
249 // Operators
Mathias Agopian7802bbd2011-02-09 18:38:55 -0800250
251 COMPARE_WEAK(==)
252 COMPARE_WEAK(!=)
253 COMPARE_WEAK(>)
254 COMPARE_WEAK(<)
255 COMPARE_WEAK(<=)
256 COMPARE_WEAK(>=)
257
258 inline bool operator == (const wp<T>& o) const {
259 return (m_ptr == o.m_ptr) && (m_refs == o.m_refs);
260 }
261 template<typename U>
262 inline bool operator == (const wp<U>& o) const {
263 return m_ptr == o.m_ptr;
264 }
265
266 inline bool operator > (const wp<T>& o) const {
267 return (m_ptr == o.m_ptr) ? (m_refs > o.m_refs) : (m_ptr > o.m_ptr);
268 }
269 template<typename U>
270 inline bool operator > (const wp<U>& o) const {
271 return (m_ptr == o.m_ptr) ? (m_refs > o.m_refs) : (m_ptr > o.m_ptr);
272 }
273
274 inline bool operator < (const wp<T>& o) const {
275 return (m_ptr == o.m_ptr) ? (m_refs < o.m_refs) : (m_ptr < o.m_ptr);
276 }
277 template<typename U>
278 inline bool operator < (const wp<U>& o) const {
279 return (m_ptr == o.m_ptr) ? (m_refs < o.m_refs) : (m_ptr < o.m_ptr);
280 }
281 inline bool operator != (const wp<T>& o) const { return m_refs != o.m_refs; }
282 template<typename U> inline bool operator != (const wp<U>& o) const { return !operator == (o); }
283 inline bool operator <= (const wp<T>& o) const { return !operator > (o); }
284 template<typename U> inline bool operator <= (const wp<U>& o) const { return !operator > (o); }
285 inline bool operator >= (const wp<T>& o) const { return !operator < (o); }
286 template<typename U> inline bool operator >= (const wp<U>& o) const { return !operator < (o); }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800287
288private:
289 template<typename Y> friend class sp;
290 template<typename Y> friend class wp;
291
292 T* m_ptr;
293 weakref_type* m_refs;
294};
295
296template <typename T>
297TextOutput& operator<<(TextOutput& to, const wp<T>& val);
298
Mathias Agopian7802bbd2011-02-09 18:38:55 -0800299#undef COMPARE_WEAK
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800300
301// ---------------------------------------------------------------------------
302// No user serviceable parts below here.
303
304template<typename T>
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800305wp<T>::wp(T* other)
306 : m_ptr(other)
307{
308 if (other) m_refs = other->createWeak(this);
309}
310
311template<typename T>
312wp<T>::wp(const wp<T>& other)
313 : m_ptr(other.m_ptr), m_refs(other.m_refs)
314{
315 if (m_ptr) m_refs->incWeak(this);
316}
317
318template<typename T>
319wp<T>::wp(const sp<T>& other)
320 : m_ptr(other.m_ptr)
321{
322 if (m_ptr) {
323 m_refs = m_ptr->createWeak(this);
324 }
325}
326
327template<typename T> template<typename U>
328wp<T>::wp(U* other)
329 : m_ptr(other)
330{
331 if (other) m_refs = other->createWeak(this);
332}
333
334template<typename T> template<typename U>
335wp<T>::wp(const wp<U>& other)
336 : m_ptr(other.m_ptr)
337{
338 if (m_ptr) {
339 m_refs = other.m_refs;
340 m_refs->incWeak(this);
341 }
342}
343
344template<typename T> template<typename U>
345wp<T>::wp(const sp<U>& other)
346 : m_ptr(other.m_ptr)
347{
348 if (m_ptr) {
349 m_refs = m_ptr->createWeak(this);
350 }
351}
352
353template<typename T>
354wp<T>::~wp()
355{
356 if (m_ptr) m_refs->decWeak(this);
357}
358
359template<typename T>
360wp<T>& wp<T>::operator = (T* other)
361{
362 weakref_type* newRefs =
363 other ? other->createWeak(this) : 0;
364 if (m_ptr) m_refs->decWeak(this);
365 m_ptr = other;
366 m_refs = newRefs;
367 return *this;
368}
369
370template<typename T>
371wp<T>& wp<T>::operator = (const wp<T>& other)
372{
Mathias Agopian8c3c51b2010-06-24 21:49:02 -0700373 weakref_type* otherRefs(other.m_refs);
374 T* otherPtr(other.m_ptr);
375 if (otherPtr) otherRefs->incWeak(this);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800376 if (m_ptr) m_refs->decWeak(this);
Mathias Agopian8c3c51b2010-06-24 21:49:02 -0700377 m_ptr = otherPtr;
378 m_refs = otherRefs;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800379 return *this;
380}
381
382template<typename T>
383wp<T>& wp<T>::operator = (const sp<T>& other)
384{
385 weakref_type* newRefs =
386 other != NULL ? other->createWeak(this) : 0;
Mathias Agopian8c3c51b2010-06-24 21:49:02 -0700387 T* otherPtr(other.m_ptr);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800388 if (m_ptr) m_refs->decWeak(this);
Mathias Agopian8c3c51b2010-06-24 21:49:02 -0700389 m_ptr = otherPtr;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800390 m_refs = newRefs;
391 return *this;
392}
393
394template<typename T> template<typename U>
395wp<T>& wp<T>::operator = (U* other)
396{
397 weakref_type* newRefs =
398 other ? other->createWeak(this) : 0;
399 if (m_ptr) m_refs->decWeak(this);
400 m_ptr = other;
401 m_refs = newRefs;
402 return *this;
403}
404
405template<typename T> template<typename U>
406wp<T>& wp<T>::operator = (const wp<U>& other)
407{
Mathias Agopian8c3c51b2010-06-24 21:49:02 -0700408 weakref_type* otherRefs(other.m_refs);
409 U* otherPtr(other.m_ptr);
410 if (otherPtr) otherRefs->incWeak(this);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800411 if (m_ptr) m_refs->decWeak(this);
Mathias Agopian8c3c51b2010-06-24 21:49:02 -0700412 m_ptr = otherPtr;
413 m_refs = otherRefs;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800414 return *this;
415}
416
417template<typename T> template<typename U>
418wp<T>& wp<T>::operator = (const sp<U>& other)
419{
420 weakref_type* newRefs =
421 other != NULL ? other->createWeak(this) : 0;
Mathias Agopian8c3c51b2010-06-24 21:49:02 -0700422 U* otherPtr(other.m_ptr);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800423 if (m_ptr) m_refs->decWeak(this);
Mathias Agopian8c3c51b2010-06-24 21:49:02 -0700424 m_ptr = otherPtr;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800425 m_refs = newRefs;
426 return *this;
427}
428
429template<typename T>
430void wp<T>::set_object_and_refs(T* other, weakref_type* refs)
431{
432 if (other) refs->incWeak(this);
433 if (m_ptr) m_refs->decWeak(this);
434 m_ptr = other;
435 m_refs = refs;
436}
437
438template<typename T>
439sp<T> wp<T>::promote() const
440{
Mathias Agopiand0050042011-02-24 18:12:34 -0800441 sp<T> result;
442 if (m_ptr && m_refs->attemptIncStrong(&result)) {
443 result.set_pointer(m_ptr);
444 }
445 return result;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800446}
447
448template<typename T>
449void wp<T>::clear()
450{
451 if (m_ptr) {
452 m_refs->decWeak(this);
453 m_ptr = 0;
454 }
455}
456
457template <typename T>
458inline TextOutput& operator<<(TextOutput& to, const wp<T>& val)
459{
Mathias Agopiana08ef492011-02-16 15:23:08 -0800460 return printWeakPointer(to, val.unsafe_get());
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800461}
462
Mathias Agopianf14a1042011-02-16 20:23:43 -0800463// ---------------------------------------------------------------------------
464
465// this class just serves as a namespace so TYPE::moveReferences can stay
466// private.
467
468class ReferenceMover {
469 // StrongReferenceCast and WeakReferenceCast do the impedance matching
470 // between the generic (void*) implementation in Refbase and the strongly typed
471 // template specializations below.
472
473 template <typename TYPE>
474 struct StrongReferenceCast : public ReferenceConverterBase {
475 virtual size_t getReferenceTypeSize() const { return sizeof( sp<TYPE> ); }
476 virtual void* getReferenceBase(void const* p) const {
477 sp<TYPE> const* sptr(reinterpret_cast<sp<TYPE> const*>(p));
478 return static_cast<typename TYPE::basetype *>(sptr->get());
479 }
480 };
481
482 template <typename TYPE>
483 struct WeakReferenceCast : public ReferenceConverterBase {
484 virtual size_t getReferenceTypeSize() const { return sizeof( wp<TYPE> ); }
485 virtual void* getReferenceBase(void const* p) const {
486 wp<TYPE> const* sptr(reinterpret_cast<wp<TYPE> const*>(p));
487 return static_cast<typename TYPE::basetype *>(sptr->unsafe_get());
488 }
489 };
490
491public:
492 template<typename TYPE> static inline
493 void move_references(sp<TYPE>* d, sp<TYPE> const* s, size_t n) {
494 memmove(d, s, n*sizeof(sp<TYPE>));
495 StrongReferenceCast<TYPE> caster;
496 TYPE::moveReferences(d, s, n, caster);
497 }
498 template<typename TYPE> static inline
499 void move_references(wp<TYPE>* d, wp<TYPE> const* s, size_t n) {
500 memmove(d, s, n*sizeof(wp<TYPE>));
501 WeakReferenceCast<TYPE> caster;
502 TYPE::moveReferences(d, s, n, caster);
503 }
504};
505
506// specialization for moving sp<> and wp<> types.
507// these are used by the [Sorted|Keyed]Vector<> implementations
508// sp<> and wp<> need to be handled specially, because they do not
509// have trivial copy operation in the general case (see RefBase.cpp
510// when DEBUG ops are enabled), but can be implemented very
511// efficiently in most cases.
512
513template<typename TYPE> inline
514void move_forward_type(sp<TYPE>* d, sp<TYPE> const* s, size_t n) {
515 ReferenceMover::move_references(d, s, n);
516}
517
518template<typename TYPE> inline
519void move_backward_type(sp<TYPE>* d, sp<TYPE> const* s, size_t n) {
520 ReferenceMover::move_references(d, s, n);
521}
522
523template<typename TYPE> inline
524void move_forward_type(wp<TYPE>* d, wp<TYPE> const* s, size_t n) {
525 ReferenceMover::move_references(d, s, n);
526}
527
528template<typename TYPE> inline
529void move_backward_type(wp<TYPE>* d, wp<TYPE> const* s, size_t n) {
530 ReferenceMover::move_references(d, s, n);
531}
532
533
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800534}; // namespace android
535
536// ---------------------------------------------------------------------------
537
538#endif // ANDROID_REF_BASE_H