|  | /* | 
|  | * Copyright (C) 2005 The Android Open Source Project | 
|  | * | 
|  | * Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | * you may not use this file except in compliance with the License. | 
|  | * You may obtain a copy of the License at | 
|  | * | 
|  | *      http://www.apache.org/licenses/LICENSE-2.0 | 
|  | * | 
|  | * Unless required by applicable law or agreed to in writing, software | 
|  | * distributed under the License is distributed on an "AS IS" BASIS, | 
|  | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | * See the License for the specific language governing permissions and | 
|  | * limitations under the License. | 
|  | */ | 
|  |  | 
|  | #ifndef ANDROID_REF_BASE_H | 
|  | #define ANDROID_REF_BASE_H | 
|  |  | 
|  | #include <cutils/atomic.h> | 
|  |  | 
|  | #include <stdint.h> | 
|  | #include <sys/types.h> | 
|  | #include <stdlib.h> | 
|  | #include <string.h> | 
|  |  | 
|  | #include <utils/StrongPointer.h> | 
|  |  | 
|  | // --------------------------------------------------------------------------- | 
|  | namespace android { | 
|  |  | 
|  | class TextOutput; | 
|  | TextOutput& printWeakPointer(TextOutput& to, const void* val); | 
|  |  | 
|  | // --------------------------------------------------------------------------- | 
|  |  | 
|  | #define COMPARE_WEAK(_op_)                                      \ | 
|  | inline bool operator _op_ (const sp<T>& o) const {              \ | 
|  | return m_ptr _op_ o.m_ptr;                                  \ | 
|  | }                                                               \ | 
|  | inline bool operator _op_ (const T* o) const {                  \ | 
|  | return m_ptr _op_ o;                                        \ | 
|  | }                                                               \ | 
|  | template<typename U>                                            \ | 
|  | inline bool operator _op_ (const sp<U>& o) const {              \ | 
|  | return m_ptr _op_ o.m_ptr;                                  \ | 
|  | }                                                               \ | 
|  | template<typename U>                                            \ | 
|  | inline bool operator _op_ (const U* o) const {                  \ | 
|  | return m_ptr _op_ o;                                        \ | 
|  | } | 
|  |  | 
|  | // --------------------------------------------------------------------------- | 
|  |  | 
|  | class ReferenceMover; | 
|  | class ReferenceConverterBase { | 
|  | public: | 
|  | virtual size_t getReferenceTypeSize() const = 0; | 
|  | virtual void* getReferenceBase(void const*) const = 0; | 
|  | inline virtual ~ReferenceConverterBase() { } | 
|  | }; | 
|  |  | 
|  | // --------------------------------------------------------------------------- | 
|  |  | 
|  | class RefBase | 
|  | { | 
|  | public: | 
|  | void            incStrong(const void* id) const; | 
|  | void            decStrong(const void* id) const; | 
|  |  | 
|  | void            forceIncStrong(const void* id) const; | 
|  |  | 
|  | //! DEBUGGING ONLY: Get current strong ref count. | 
|  | int32_t         getStrongCount() const; | 
|  |  | 
|  | class weakref_type | 
|  | { | 
|  | public: | 
|  | RefBase*            refBase() const; | 
|  |  | 
|  | void                incWeak(const void* id); | 
|  | void                decWeak(const void* id); | 
|  |  | 
|  | bool                attemptIncStrong(const void* id); | 
|  |  | 
|  | //! This is only safe if you have set OBJECT_LIFETIME_FOREVER. | 
|  | bool                attemptIncWeak(const void* id); | 
|  |  | 
|  | //! DEBUGGING ONLY: Get current weak ref count. | 
|  | int32_t             getWeakCount() const; | 
|  |  | 
|  | //! DEBUGGING ONLY: Print references held on object. | 
|  | void                printRefs() const; | 
|  |  | 
|  | //! DEBUGGING ONLY: Enable tracking for this object. | 
|  | // enable -- enable/disable tracking | 
|  | // retain -- when tracking is enable, if true, then we save a stack trace | 
|  | //           for each reference and dereference; when retain == false, we | 
|  | //           match up references and dereferences and keep only the | 
|  | //           outstanding ones. | 
|  |  | 
|  | void                trackMe(bool enable, bool retain); | 
|  | }; | 
|  |  | 
|  | weakref_type*   createWeak(const void* id) const; | 
|  |  | 
|  | weakref_type*   getWeakRefs() const; | 
|  |  | 
|  | //! DEBUGGING ONLY: Print references held on object. | 
|  | inline  void            printRefs() const { getWeakRefs()->printRefs(); } | 
|  |  | 
|  | //! DEBUGGING ONLY: Enable tracking of object. | 
|  | inline  void            trackMe(bool enable, bool retain) | 
|  | { | 
|  | getWeakRefs()->trackMe(enable, retain); | 
|  | } | 
|  |  | 
|  | typedef RefBase basetype; | 
|  |  | 
|  | protected: | 
|  | RefBase(); | 
|  | virtual                 ~RefBase(); | 
|  |  | 
|  | //! Flags for extendObjectLifetime() | 
|  | enum { | 
|  | OBJECT_LIFETIME_WEAK    = 0x0001, | 
|  | OBJECT_LIFETIME_FOREVER = 0x0003 | 
|  | }; | 
|  |  | 
|  | void            extendObjectLifetime(int32_t mode); | 
|  |  | 
|  | //! Flags for onIncStrongAttempted() | 
|  | enum { | 
|  | FIRST_INC_STRONG = 0x0001 | 
|  | }; | 
|  |  | 
|  | virtual void            onFirstRef(); | 
|  | virtual void            onLastStrongRef(const void* id); | 
|  | virtual bool            onIncStrongAttempted(uint32_t flags, const void* id); | 
|  | virtual void            onLastWeakRef(const void* id); | 
|  |  | 
|  | private: | 
|  | friend class ReferenceMover; | 
|  | static void moveReferences(void* d, void const* s, size_t n, | 
|  | const ReferenceConverterBase& caster); | 
|  |  | 
|  | private: | 
|  | friend class weakref_type; | 
|  | class weakref_impl; | 
|  |  | 
|  | RefBase(const RefBase& o); | 
|  | RefBase&        operator=(const RefBase& o); | 
|  |  | 
|  | weakref_impl* const mRefs; | 
|  | }; | 
|  |  | 
|  | // --------------------------------------------------------------------------- | 
|  |  | 
|  | template <class T> | 
|  | class LightRefBase | 
|  | { | 
|  | public: | 
|  | inline LightRefBase() : mCount(0) { } | 
|  | inline void incStrong(const void* id) const { | 
|  | android_atomic_inc(&mCount); | 
|  | } | 
|  | inline void decStrong(const void* id) const { | 
|  | if (android_atomic_dec(&mCount) == 1) { | 
|  | delete static_cast<const T*>(this); | 
|  | } | 
|  | } | 
|  | //! DEBUGGING ONLY: Get current strong ref count. | 
|  | inline int32_t getStrongCount() const { | 
|  | return mCount; | 
|  | } | 
|  |  | 
|  | typedef LightRefBase<T> basetype; | 
|  |  | 
|  | protected: | 
|  | inline ~LightRefBase() { } | 
|  |  | 
|  | private: | 
|  | friend class ReferenceMover; | 
|  | inline static void moveReferences(void* d, void const* s, size_t n, | 
|  | const ReferenceConverterBase& caster) { } | 
|  |  | 
|  | private: | 
|  | mutable volatile int32_t mCount; | 
|  | }; | 
|  |  | 
|  | // --------------------------------------------------------------------------- | 
|  |  | 
|  | template <typename T> | 
|  | class wp | 
|  | { | 
|  | public: | 
|  | typedef typename RefBase::weakref_type weakref_type; | 
|  |  | 
|  | inline wp() : m_ptr(0) { } | 
|  |  | 
|  | wp(T* other); | 
|  | wp(const wp<T>& other); | 
|  | wp(const sp<T>& other); | 
|  | template<typename U> wp(U* other); | 
|  | template<typename U> wp(const sp<U>& other); | 
|  | template<typename U> wp(const wp<U>& other); | 
|  |  | 
|  | ~wp(); | 
|  |  | 
|  | // Assignment | 
|  |  | 
|  | wp& operator = (T* other); | 
|  | wp& operator = (const wp<T>& other); | 
|  | wp& operator = (const sp<T>& other); | 
|  |  | 
|  | template<typename U> wp& operator = (U* other); | 
|  | template<typename U> wp& operator = (const wp<U>& other); | 
|  | template<typename U> wp& operator = (const sp<U>& other); | 
|  |  | 
|  | void set_object_and_refs(T* other, weakref_type* refs); | 
|  |  | 
|  | // promotion to sp | 
|  |  | 
|  | sp<T> promote() const; | 
|  |  | 
|  | // Reset | 
|  |  | 
|  | void clear(); | 
|  |  | 
|  | // Accessors | 
|  |  | 
|  | inline  weakref_type* get_refs() const { return m_refs; } | 
|  |  | 
|  | inline  T* unsafe_get() const { return m_ptr; } | 
|  |  | 
|  | // Operators | 
|  |  | 
|  | COMPARE_WEAK(==) | 
|  | COMPARE_WEAK(!=) | 
|  | COMPARE_WEAK(>) | 
|  | COMPARE_WEAK(<) | 
|  | COMPARE_WEAK(<=) | 
|  | COMPARE_WEAK(>=) | 
|  |  | 
|  | inline bool operator == (const wp<T>& o) const { | 
|  | return (m_ptr == o.m_ptr) && (m_refs == o.m_refs); | 
|  | } | 
|  | template<typename U> | 
|  | inline bool operator == (const wp<U>& o) const { | 
|  | return m_ptr == o.m_ptr; | 
|  | } | 
|  |  | 
|  | inline bool operator > (const wp<T>& o) const { | 
|  | return (m_ptr == o.m_ptr) ? (m_refs > o.m_refs) : (m_ptr > o.m_ptr); | 
|  | } | 
|  | template<typename U> | 
|  | inline bool operator > (const wp<U>& o) const { | 
|  | return (m_ptr == o.m_ptr) ? (m_refs > o.m_refs) : (m_ptr > o.m_ptr); | 
|  | } | 
|  |  | 
|  | inline bool operator < (const wp<T>& o) const { | 
|  | return (m_ptr == o.m_ptr) ? (m_refs < o.m_refs) : (m_ptr < o.m_ptr); | 
|  | } | 
|  | template<typename U> | 
|  | inline bool operator < (const wp<U>& o) const { | 
|  | return (m_ptr == o.m_ptr) ? (m_refs < o.m_refs) : (m_ptr < o.m_ptr); | 
|  | } | 
|  | inline bool operator != (const wp<T>& o) const { return m_refs != o.m_refs; } | 
|  | template<typename U> inline bool operator != (const wp<U>& o) const { return !operator == (o); } | 
|  | inline bool operator <= (const wp<T>& o) const { return !operator > (o); } | 
|  | template<typename U> inline bool operator <= (const wp<U>& o) const { return !operator > (o); } | 
|  | inline bool operator >= (const wp<T>& o) const { return !operator < (o); } | 
|  | template<typename U> inline bool operator >= (const wp<U>& o) const { return !operator < (o); } | 
|  |  | 
|  | private: | 
|  | template<typename Y> friend class sp; | 
|  | template<typename Y> friend class wp; | 
|  |  | 
|  | T*              m_ptr; | 
|  | weakref_type*   m_refs; | 
|  | }; | 
|  |  | 
|  | template <typename T> | 
|  | TextOutput& operator<<(TextOutput& to, const wp<T>& val); | 
|  |  | 
|  | #undef COMPARE_WEAK | 
|  |  | 
|  | // --------------------------------------------------------------------------- | 
|  | // No user serviceable parts below here. | 
|  |  | 
|  | template<typename T> | 
|  | wp<T>::wp(T* other) | 
|  | : m_ptr(other) | 
|  | { | 
|  | if (other) m_refs = other->createWeak(this); | 
|  | } | 
|  |  | 
|  | template<typename T> | 
|  | wp<T>::wp(const wp<T>& other) | 
|  | : m_ptr(other.m_ptr), m_refs(other.m_refs) | 
|  | { | 
|  | if (m_ptr) m_refs->incWeak(this); | 
|  | } | 
|  |  | 
|  | template<typename T> | 
|  | wp<T>::wp(const sp<T>& other) | 
|  | : m_ptr(other.m_ptr) | 
|  | { | 
|  | if (m_ptr) { | 
|  | m_refs = m_ptr->createWeak(this); | 
|  | } | 
|  | } | 
|  |  | 
|  | template<typename T> template<typename U> | 
|  | wp<T>::wp(U* other) | 
|  | : m_ptr(other) | 
|  | { | 
|  | if (other) m_refs = other->createWeak(this); | 
|  | } | 
|  |  | 
|  | template<typename T> template<typename U> | 
|  | wp<T>::wp(const wp<U>& other) | 
|  | : m_ptr(other.m_ptr) | 
|  | { | 
|  | if (m_ptr) { | 
|  | m_refs = other.m_refs; | 
|  | m_refs->incWeak(this); | 
|  | } | 
|  | } | 
|  |  | 
|  | template<typename T> template<typename U> | 
|  | wp<T>::wp(const sp<U>& other) | 
|  | : m_ptr(other.m_ptr) | 
|  | { | 
|  | if (m_ptr) { | 
|  | m_refs = m_ptr->createWeak(this); | 
|  | } | 
|  | } | 
|  |  | 
|  | template<typename T> | 
|  | wp<T>::~wp() | 
|  | { | 
|  | if (m_ptr) m_refs->decWeak(this); | 
|  | } | 
|  |  | 
|  | template<typename T> | 
|  | wp<T>& wp<T>::operator = (T* other) | 
|  | { | 
|  | weakref_type* newRefs = | 
|  | other ? other->createWeak(this) : 0; | 
|  | if (m_ptr) m_refs->decWeak(this); | 
|  | m_ptr = other; | 
|  | m_refs = newRefs; | 
|  | return *this; | 
|  | } | 
|  |  | 
|  | template<typename T> | 
|  | wp<T>& wp<T>::operator = (const wp<T>& other) | 
|  | { | 
|  | weakref_type* otherRefs(other.m_refs); | 
|  | T* otherPtr(other.m_ptr); | 
|  | if (otherPtr) otherRefs->incWeak(this); | 
|  | if (m_ptr) m_refs->decWeak(this); | 
|  | m_ptr = otherPtr; | 
|  | m_refs = otherRefs; | 
|  | return *this; | 
|  | } | 
|  |  | 
|  | template<typename T> | 
|  | wp<T>& wp<T>::operator = (const sp<T>& other) | 
|  | { | 
|  | weakref_type* newRefs = | 
|  | other != NULL ? other->createWeak(this) : 0; | 
|  | T* otherPtr(other.m_ptr); | 
|  | if (m_ptr) m_refs->decWeak(this); | 
|  | m_ptr = otherPtr; | 
|  | m_refs = newRefs; | 
|  | return *this; | 
|  | } | 
|  |  | 
|  | template<typename T> template<typename U> | 
|  | wp<T>& wp<T>::operator = (U* other) | 
|  | { | 
|  | weakref_type* newRefs = | 
|  | other ? other->createWeak(this) : 0; | 
|  | if (m_ptr) m_refs->decWeak(this); | 
|  | m_ptr = other; | 
|  | m_refs = newRefs; | 
|  | return *this; | 
|  | } | 
|  |  | 
|  | template<typename T> template<typename U> | 
|  | wp<T>& wp<T>::operator = (const wp<U>& other) | 
|  | { | 
|  | weakref_type* otherRefs(other.m_refs); | 
|  | U* otherPtr(other.m_ptr); | 
|  | if (otherPtr) otherRefs->incWeak(this); | 
|  | if (m_ptr) m_refs->decWeak(this); | 
|  | m_ptr = otherPtr; | 
|  | m_refs = otherRefs; | 
|  | return *this; | 
|  | } | 
|  |  | 
|  | template<typename T> template<typename U> | 
|  | wp<T>& wp<T>::operator = (const sp<U>& other) | 
|  | { | 
|  | weakref_type* newRefs = | 
|  | other != NULL ? other->createWeak(this) : 0; | 
|  | U* otherPtr(other.m_ptr); | 
|  | if (m_ptr) m_refs->decWeak(this); | 
|  | m_ptr = otherPtr; | 
|  | m_refs = newRefs; | 
|  | return *this; | 
|  | } | 
|  |  | 
|  | template<typename T> | 
|  | void wp<T>::set_object_and_refs(T* other, weakref_type* refs) | 
|  | { | 
|  | if (other) refs->incWeak(this); | 
|  | if (m_ptr) m_refs->decWeak(this); | 
|  | m_ptr = other; | 
|  | m_refs = refs; | 
|  | } | 
|  |  | 
|  | template<typename T> | 
|  | sp<T> wp<T>::promote() const | 
|  | { | 
|  | sp<T> result; | 
|  | if (m_ptr && m_refs->attemptIncStrong(&result)) { | 
|  | result.set_pointer(m_ptr); | 
|  | } | 
|  | return result; | 
|  | } | 
|  |  | 
|  | template<typename T> | 
|  | void wp<T>::clear() | 
|  | { | 
|  | if (m_ptr) { | 
|  | m_refs->decWeak(this); | 
|  | m_ptr = 0; | 
|  | } | 
|  | } | 
|  |  | 
|  | template <typename T> | 
|  | inline TextOutput& operator<<(TextOutput& to, const wp<T>& val) | 
|  | { | 
|  | return printWeakPointer(to, val.unsafe_get()); | 
|  | } | 
|  |  | 
|  | // --------------------------------------------------------------------------- | 
|  |  | 
|  | // this class just serves as a namespace so TYPE::moveReferences can stay | 
|  | // private. | 
|  |  | 
|  | class ReferenceMover { | 
|  | // StrongReferenceCast and WeakReferenceCast do the impedance matching | 
|  | // between the generic (void*) implementation in Refbase and the strongly typed | 
|  | // template specializations below. | 
|  |  | 
|  | template <typename TYPE> | 
|  | struct StrongReferenceCast : public ReferenceConverterBase { | 
|  | virtual size_t getReferenceTypeSize() const { return sizeof( sp<TYPE> ); } | 
|  | virtual void* getReferenceBase(void const* p) const { | 
|  | sp<TYPE> const* sptr(reinterpret_cast<sp<TYPE> const*>(p)); | 
|  | return static_cast<typename TYPE::basetype *>(sptr->get()); | 
|  | } | 
|  | }; | 
|  |  | 
|  | template <typename TYPE> | 
|  | struct WeakReferenceCast : public ReferenceConverterBase { | 
|  | virtual size_t getReferenceTypeSize() const { return sizeof( wp<TYPE> ); } | 
|  | virtual void* getReferenceBase(void const* p) const { | 
|  | wp<TYPE> const* sptr(reinterpret_cast<wp<TYPE> const*>(p)); | 
|  | return static_cast<typename TYPE::basetype *>(sptr->unsafe_get()); | 
|  | } | 
|  | }; | 
|  |  | 
|  | public: | 
|  | template<typename TYPE> static inline | 
|  | void move_references(sp<TYPE>* d, sp<TYPE> const* s, size_t n) { | 
|  | memmove(d, s, n*sizeof(sp<TYPE>)); | 
|  | StrongReferenceCast<TYPE> caster; | 
|  | TYPE::moveReferences(d, s, n, caster); | 
|  | } | 
|  | template<typename TYPE> static inline | 
|  | void move_references(wp<TYPE>* d, wp<TYPE> const* s, size_t n) { | 
|  | memmove(d, s, n*sizeof(wp<TYPE>)); | 
|  | WeakReferenceCast<TYPE> caster; | 
|  | TYPE::moveReferences(d, s, n, caster); | 
|  | } | 
|  | }; | 
|  |  | 
|  | // specialization for moving sp<> and wp<> types. | 
|  | // these are used by the [Sorted|Keyed]Vector<> implementations | 
|  | // sp<> and wp<> need to be handled specially, because they do not | 
|  | // have trivial copy operation in the general case (see RefBase.cpp | 
|  | // when DEBUG ops are enabled), but can be implemented very | 
|  | // efficiently in most cases. | 
|  |  | 
|  | template<typename TYPE> inline | 
|  | void move_forward_type(sp<TYPE>* d, sp<TYPE> const* s, size_t n) { | 
|  | ReferenceMover::move_references(d, s, n); | 
|  | } | 
|  |  | 
|  | template<typename TYPE> inline | 
|  | void move_backward_type(sp<TYPE>* d, sp<TYPE> const* s, size_t n) { | 
|  | ReferenceMover::move_references(d, s, n); | 
|  | } | 
|  |  | 
|  | template<typename TYPE> inline | 
|  | void move_forward_type(wp<TYPE>* d, wp<TYPE> const* s, size_t n) { | 
|  | ReferenceMover::move_references(d, s, n); | 
|  | } | 
|  |  | 
|  | template<typename TYPE> inline | 
|  | void move_backward_type(wp<TYPE>* d, wp<TYPE> const* s, size_t n) { | 
|  | ReferenceMover::move_references(d, s, n); | 
|  | } | 
|  |  | 
|  |  | 
|  | }; // namespace android | 
|  |  | 
|  | // --------------------------------------------------------------------------- | 
|  |  | 
|  | #endif // ANDROID_REF_BASE_H |