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