Loading include/utils/RefBase.h +101 −176 Original line number Diff line number Diff line Loading @@ -22,16 +22,16 @@ #include <stdint.h> #include <sys/types.h> #include <stdlib.h> #include <string.h> #include <utils/StrongPointer.h> // --------------------------------------------------------------------------- namespace android { class TextOutput; TextOutput& printStrongPointer(TextOutput& to, const void* val); TextOutput& printWeakPointer(TextOutput& to, const void* val); template<typename T> class wp; // --------------------------------------------------------------------------- #define COMPARE_WEAK(_op_) \ Loading @@ -50,15 +50,15 @@ inline bool operator _op_ (const U* o) const { \ return m_ptr _op_ o; \ } #define COMPARE(_op_) \ COMPARE_WEAK(_op_) \ inline bool operator _op_ (const wp<T>& o) const { \ return m_ptr _op_ o.m_ptr; \ } \ template<typename U> \ inline bool operator _op_ (const wp<U>& o) const { \ return m_ptr _op_ o.m_ptr; \ } // --------------------------------------------------------------------------- class ReferenceMover; class ReferenceConverterBase { public: virtual size_t getReferenceTypeSize() const = 0; virtual void* getReferenceBase(void const*) const = 0; inline virtual ~ReferenceConverterBase() { } }; // --------------------------------------------------------------------------- Loading Loading @@ -115,6 +115,8 @@ public: getWeakRefs()->trackMe(enable, retain); } typedef RefBase basetype; protected: RefBase(); virtual ~RefBase(); Loading @@ -137,6 +139,11 @@ protected: 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; Loading Loading @@ -167,73 +174,20 @@ public: return mCount; } typedef LightRefBase<T> basetype; protected: inline ~LightRefBase() { } private: mutable volatile int32_t mCount; }; // --------------------------------------------------------------------------- template <typename T> class sp { public: typedef typename RefBase::weakref_type weakref_type; inline sp() : m_ptr(0) { } sp(T* other); sp(const sp<T>& other); template<typename U> sp(U* other); template<typename U> sp(const sp<U>& other); ~sp(); // Assignment sp& operator = (T* other); sp& operator = (const sp<T>& other); template<typename U> sp& operator = (const sp<U>& other); template<typename U> sp& operator = (U* other); //! Special optimization for use by ProcessState (and nobody else). void force_set(T* other); // Reset void clear(); // Accessors inline T& operator* () const { return *m_ptr; } inline T* operator-> () const { return m_ptr; } inline T* get() const { return m_ptr; } // Operators COMPARE(==) COMPARE(!=) COMPARE(>) COMPARE(<) COMPARE(<=) COMPARE(>=) friend class ReferenceMover; inline static void moveReferences(void* d, void const* s, size_t n, const ReferenceConverterBase& caster) { } private: template<typename Y> friend class sp; template<typename Y> friend class wp; // Optimization for wp::promote(). sp(T* p, weakref_type* refs); T* m_ptr; mutable volatile int32_t mCount; }; template <typename T> TextOutput& operator<<(TextOutput& to, const sp<T>& val); // --------------------------------------------------------------------------- template <typename T> Loading Loading @@ -329,112 +283,11 @@ private: template <typename T> TextOutput& operator<<(TextOutput& to, const wp<T>& val); #undef COMPARE #undef COMPARE_WEAK // --------------------------------------------------------------------------- // No user serviceable parts below here. template<typename T> sp<T>::sp(T* other) : m_ptr(other) { if (other) other->incStrong(this); } template<typename T> sp<T>::sp(const sp<T>& other) : m_ptr(other.m_ptr) { if (m_ptr) m_ptr->incStrong(this); } template<typename T> template<typename U> sp<T>::sp(U* other) : m_ptr(other) { if (other) other->incStrong(this); } template<typename T> template<typename U> sp<T>::sp(const sp<U>& other) : m_ptr(other.m_ptr) { if (m_ptr) m_ptr->incStrong(this); } template<typename T> sp<T>::~sp() { if (m_ptr) m_ptr->decStrong(this); } template<typename T> sp<T>& sp<T>::operator = (const sp<T>& other) { T* otherPtr(other.m_ptr); if (otherPtr) otherPtr->incStrong(this); if (m_ptr) m_ptr->decStrong(this); m_ptr = otherPtr; return *this; } template<typename T> sp<T>& sp<T>::operator = (T* other) { if (other) other->incStrong(this); if (m_ptr) m_ptr->decStrong(this); m_ptr = other; return *this; } template<typename T> template<typename U> sp<T>& sp<T>::operator = (const sp<U>& other) { U* otherPtr(other.m_ptr); if (otherPtr) otherPtr->incStrong(this); if (m_ptr) m_ptr->decStrong(this); m_ptr = otherPtr; return *this; } template<typename T> template<typename U> sp<T>& sp<T>::operator = (U* other) { if (other) other->incStrong(this); if (m_ptr) m_ptr->decStrong(this); m_ptr = other; return *this; } template<typename T> void sp<T>::force_set(T* other) { other->forceIncStrong(this); m_ptr = other; } template<typename T> void sp<T>::clear() { if (m_ptr) { m_ptr->decStrong(this); m_ptr = 0; } } template<typename T> sp<T>::sp(T* p, weakref_type* refs) : m_ptr((p && refs->attemptIncStrong(this)) ? p : 0) { } template <typename T> inline TextOutput& operator<<(TextOutput& to, const sp<T>& val) { return printStrongPointer(to, val.get()); } // --------------------------------------------------------------------------- template<typename T> wp<T>::wp(T* other) : m_ptr(other) Loading Loading @@ -572,7 +425,8 @@ void wp<T>::set_object_and_refs(T* other, weakref_type* refs) template<typename T> sp<T> wp<T>::promote() const { return sp<T>(m_ptr, m_refs); T* p = (m_ptr && m_refs->attemptIncStrong(this)) ? m_ptr : 0; return sp<T>(p, true); } template<typename T> Loading @@ -590,6 +444,77 @@ 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 // --------------------------------------------------------------------------- Loading include/utils/StrongPointer.h 0 → 100644 +224 −0 Original line number Diff line number Diff line /* * 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_STRONG_POINTER_H #define ANDROID_STRONG_POINTER_H #include <cutils/atomic.h> #include <stdint.h> #include <sys/types.h> #include <stdlib.h> // --------------------------------------------------------------------------- namespace android { class TextOutput; TextOutput& printStrongPointer(TextOutput& to, const void* val); template<typename T> class wp; // --------------------------------------------------------------------------- #define COMPARE(_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; \ } \ inline bool operator _op_ (const wp<T>& o) const { \ return m_ptr _op_ o.m_ptr; \ } \ template<typename U> \ inline bool operator _op_ (const wp<U>& o) const { \ return m_ptr _op_ o.m_ptr; \ } // --------------------------------------------------------------------------- template <typename T> class sp { public: inline sp() : m_ptr(0) { } sp(T* other); sp(const sp<T>& other); template<typename U> sp(U* other); template<typename U> sp(const sp<U>& other); ~sp(); // Assignment sp& operator = (T* other); sp& operator = (const sp<T>& other); template<typename U> sp& operator = (const sp<U>& other); template<typename U> sp& operator = (U* other); //! Special optimization for use by ProcessState (and nobody else). void force_set(T* other); // Reset void clear(); // Accessors inline T& operator* () const { return *m_ptr; } inline T* operator-> () const { return m_ptr; } inline T* get() const { return m_ptr; } // Operators COMPARE(==) COMPARE(!=) COMPARE(>) COMPARE(<) COMPARE(<=) COMPARE(>=) private: template<typename Y> friend class sp; template<typename Y> friend class wp; // Optimization for wp::promote(). sp(T* p, bool); T* m_ptr; }; #undef COMPARE template <typename T> TextOutput& operator<<(TextOutput& to, const sp<T>& val); // --------------------------------------------------------------------------- // No user serviceable parts below here. template<typename T> sp<T>::sp(T* other) : m_ptr(other) { if (other) other->incStrong(this); } template<typename T> sp<T>::sp(const sp<T>& other) : m_ptr(other.m_ptr) { if (m_ptr) m_ptr->incStrong(this); } template<typename T> template<typename U> sp<T>::sp(U* other) : m_ptr(other) { if (other) other->incStrong(this); } template<typename T> template<typename U> sp<T>::sp(const sp<U>& other) : m_ptr(other.m_ptr) { if (m_ptr) m_ptr->incStrong(this); } template<typename T> sp<T>::~sp() { if (m_ptr) m_ptr->decStrong(this); } template<typename T> sp<T>& sp<T>::operator = (const sp<T>& other) { T* otherPtr(other.m_ptr); if (otherPtr) otherPtr->incStrong(this); if (m_ptr) m_ptr->decStrong(this); m_ptr = otherPtr; return *this; } template<typename T> sp<T>& sp<T>::operator = (T* other) { if (other) other->incStrong(this); if (m_ptr) m_ptr->decStrong(this); m_ptr = other; return *this; } template<typename T> template<typename U> sp<T>& sp<T>::operator = (const sp<U>& other) { U* otherPtr(other.m_ptr); if (otherPtr) otherPtr->incStrong(this); if (m_ptr) m_ptr->decStrong(this); m_ptr = otherPtr; return *this; } template<typename T> template<typename U> sp<T>& sp<T>::operator = (U* other) { if (other) other->incStrong(this); if (m_ptr) m_ptr->decStrong(this); m_ptr = other; return *this; } template<typename T> void sp<T>::force_set(T* other) { other->forceIncStrong(this); m_ptr = other; } template<typename T> void sp<T>::clear() { if (m_ptr) { m_ptr->decStrong(this); m_ptr = 0; } } template<typename T> sp<T>::sp(T* p, bool) : m_ptr(p) { } template <typename T> inline TextOutput& operator<<(TextOutput& to, const sp<T>& val) { return printStrongPointer(to, val.get()); } }; // namespace android // --------------------------------------------------------------------------- #endif // ANDROID_STRONG_POINTER_H include/utils/TypeHelpers.h +0 −13 Original line number Diff line number Diff line Loading @@ -37,18 +37,6 @@ template <typename T> struct trait_trivial_move { enum { value = false }; }; template <typename T> struct trait_pointer { enum { value = false }; }; template <typename T> struct trait_pointer<T*> { enum { value = true }; }; // sp<> can be trivially moved template <typename T> class sp; template <typename T> struct trait_trivial_move< sp<T> >{ enum { value = true }; }; // wp<> can be trivially moved template <typename T> class wp; template <typename T> struct trait_trivial_move< wp<T> >{ enum { value = true }; }; template <typename TYPE> struct traits { enum { Loading Loading @@ -217,7 +205,6 @@ void move_backward_type(TYPE* d, const TYPE* s, size_t n = 1) { } } // --------------------------------------------------------------------------- /* Loading libs/utils/RefBase.cpp +101 −70 Original line number Diff line number Diff line Loading @@ -20,7 +20,6 @@ #include <utils/Atomic.h> #include <utils/CallStack.h> #include <utils/KeyedVector.h> #include <utils/Log.h> #include <utils/threads.h> #include <utils/TextOutput.h> Loading @@ -35,6 +34,7 @@ // compile with refcounting debugging enabled #define DEBUG_REFS 0 #define DEBUG_REFS_FATAL_SANITY_CHECKS 0 #define DEBUG_REFS_ENABLED_BY_DEFAULT 1 #define DEBUG_REFS_CALLSTACK_ENABLED 1 Loading Loading @@ -70,8 +70,10 @@ public: void addStrongRef(const void* /*id*/) { } void removeStrongRef(const void* /*id*/) { } void renameStrongRefId(const void* /*old_id*/, const void* /*new_id*/) { } void addWeakRef(const void* /*id*/) { } void removeWeakRef(const void* /*id*/) { } void renameWeakRefId(const void* /*old_id*/, const void* /*new_id*/) { } void printRefs() const { } void trackMe(bool, bool) { } Loading @@ -87,40 +89,74 @@ public: , mTrackEnabled(!!DEBUG_REFS_ENABLED_BY_DEFAULT) , mRetain(false) { //LOGI("NEW weakref_impl %p for RefBase %p", this, base); } ~weakref_impl() { LOG_ALWAYS_FATAL_IF(!mRetain && mStrongRefs != NULL, "Strong references remain!"); LOG_ALWAYS_FATAL_IF(!mRetain && mWeakRefs != NULL, "Weak references remain!"); bool dumpStack = false; if (!mRetain && mStrongRefs != NULL) { dumpStack = true; #if DEBUG_REFS_FATAL_SANITY_CHECKS LOG_ALWAYS_FATAL("Strong references remain!"); #else LOGE("Strong references remain!"); #endif } void addStrongRef(const void* id) { if (!mRetain && mWeakRefs != NULL) { dumpStack = true; #if DEBUG_REFS_FATAL_SANITY_CHECKS LOG_ALWAYS_FATAL("Weak references remain!"); #else LOGE("Weak references remain!"); #endif } if (dumpStack) { CallStack stack; stack.update(); stack.dump(); } } void addStrongRef(const void* id) { //LOGD_IF(mTrackEnabled, // "addStrongRef: RefBase=%p, id=%p", mBase, id); addRef(&mStrongRefs, id, mStrong); } void removeStrongRef(const void* id) { if (!mRetain) void removeStrongRef(const void* id) { //LOGD_IF(mTrackEnabled, // "removeStrongRef: RefBase=%p, id=%p", mBase, id); if (!mRetain) { removeRef(&mStrongRefs, id); else } else { addRef(&mStrongRefs, id, -mStrong); } } void addWeakRef(const void* id) { void renameStrongRefId(const void* old_id, const void* new_id) { //LOGD_IF(mTrackEnabled, // "renameStrongRefId: RefBase=%p, oid=%p, nid=%p", // mBase, old_id, new_id); renameRefsId(mStrongRefs, old_id, new_id); } void addWeakRef(const void* id) { addRef(&mWeakRefs, id, mWeak); } void removeWeakRef(const void* id) { if (!mRetain) void removeWeakRef(const void* id) { if (!mRetain) { removeRef(&mWeakRefs, id); else } else { addRef(&mWeakRefs, id, -mWeak); } } void renameWeakRefId(const void* old_id, const void* new_id) { renameRefsId(mWeakRefs, old_id, new_id); } void trackMe(bool track, bool retain) { Loading @@ -133,8 +169,7 @@ public: String8 text; { AutoMutex _l(const_cast<weakref_impl*>(this)->mMutex); Mutex::Autolock _l(const_cast<weakref_impl*>(this)->mMutex); char buf[128]; sprintf(buf, "Strong references on RefBase %p (weakref_type %p):\n", mBase, this); text.append(buf); Loading Loading @@ -173,6 +208,7 @@ private: { if (mTrackEnabled) { AutoMutex _l(mMutex); ref_entry* ref = new ref_entry; // Reference count at the time of the snapshot, but before the // update. Positive value means we increment, negative--we Loading @@ -182,7 +218,6 @@ private: #if DEBUG_REFS_CALLSTACK_ENABLED ref->stack.update(2); #endif ref->next = *refs; *refs = ref; } Loading @@ -200,13 +235,37 @@ private: delete ref; return; } refs = &ref->next; ref = *refs; } LOG_ALWAYS_FATAL("RefBase: removing id %p on RefBase %p (weakref_type %p) that doesn't exist!", #if DEBUG_REFS_FATAL_SANITY_CHECKS LOG_ALWAYS_FATAL("RefBase: removing id %p on RefBase %p" "(weakref_type %p) that doesn't exist!", id, mBase, this); #endif LOGE("RefBase: removing id %p on RefBase %p" "(weakref_type %p) that doesn't exist!", id, mBase, this); CallStack stack; stack.update(); stack.dump(); } } void renameRefsId(ref_entry* r, const void* old_id, const void* new_id) { if (mTrackEnabled) { AutoMutex _l(mMutex); ref_entry* ref = r; while (ref != NULL) { if (ref->id == old_id) { ref->id = new_id; } ref = ref->next; } } } Loading Loading @@ -236,44 +295,6 @@ private: // on removeref that match the address ones. bool mRetain; #if 0 void addRef(KeyedVector<const void*, int32_t>* refs, const void* id) { AutoMutex _l(mMutex); ssize_t i = refs->indexOfKey(id); if (i >= 0) { ++(refs->editValueAt(i)); } else { i = refs->add(id, 1); } } void removeRef(KeyedVector<const void*, int32_t>* refs, const void* id) { AutoMutex _l(mMutex); ssize_t i = refs->indexOfKey(id); LOG_ALWAYS_FATAL_IF(i < 0, "RefBase: removing id %p that doesn't exist!", id); if (i >= 0) { int32_t val = --(refs->editValueAt(i)); if (val == 0) { refs->removeItemsAt(i); } } } void printRefs(const KeyedVector<const void*, int32_t>& refs) { const size_t N=refs.size(); for (size_t i=0; i<N; i++) { printf("\tID %p: %d remain\n", refs.keyAt(i), refs.valueAt(i)); } } mutable Mutex mMutex; KeyedVector<const void*, int32_t> mStrongRefs; KeyedVector<const void*, int32_t> mWeakRefs; #endif #endif }; Loading @@ -282,7 +303,6 @@ private: void RefBase::incStrong(const void* id) const { weakref_impl* const refs = mRefs; refs->addWeakRef(id); refs->incWeak(id); refs->addStrongRef(id); Loading Loading @@ -314,14 +334,12 @@ void RefBase::decStrong(const void* id) const delete this; } } refs->removeWeakRef(id); refs->decWeak(id); } void RefBase::forceIncStrong(const void* id) const { weakref_impl* const refs = mRefs; refs->addWeakRef(id); refs->incWeak(id); refs->addStrongRef(id); Loading Loading @@ -433,7 +451,6 @@ bool RefBase::weakref_type::attemptIncStrong(const void* id) } } impl->addWeakRef(id); impl->addStrongRef(id); #if PRINT_REFS Loading Loading @@ -498,14 +515,11 @@ RefBase::weakref_type* RefBase::getWeakRefs() const RefBase::RefBase() : mRefs(new weakref_impl(this)) { // LOGV("Creating refs %p with RefBase %p\n", mRefs, this); } RefBase::~RefBase() { // LOGV("Destroying RefBase %p (refs %p)\n", this, mRefs); if (mRefs->mWeak == 0) { // LOGV("Freeing refs %p of old RefBase %p\n", mRefs, this); delete mRefs; } } Loading Loading @@ -534,6 +548,23 @@ void RefBase::onLastWeakRef(const void* /*id*/) // --------------------------------------------------------------------------- void RefBase::moveReferences(void* dst, void const* src, size_t n, const ReferenceConverterBase& caster) { #if DEBUG_REFS const size_t itemSize = caster.getReferenceTypeSize(); for (size_t i=0 ; i<n ; i++) { void* d = reinterpret_cast<void *>(intptr_t(dst) + i*itemSize); void const* s = reinterpret_cast<void const*>(intptr_t(src) + i*itemSize); RefBase* ref(reinterpret_cast<RefBase*>(caster.getReferenceBase(d))); ref->mRefs->renameStrongRefId(s, d); ref->mRefs->renameWeakRefId(s, d); } #endif } // --------------------------------------------------------------------------- TextOutput& printStrongPointer(TextOutput& to, const void* val) { to << "sp<>(" << val << ")"; Loading Loading
include/utils/RefBase.h +101 −176 Original line number Diff line number Diff line Loading @@ -22,16 +22,16 @@ #include <stdint.h> #include <sys/types.h> #include <stdlib.h> #include <string.h> #include <utils/StrongPointer.h> // --------------------------------------------------------------------------- namespace android { class TextOutput; TextOutput& printStrongPointer(TextOutput& to, const void* val); TextOutput& printWeakPointer(TextOutput& to, const void* val); template<typename T> class wp; // --------------------------------------------------------------------------- #define COMPARE_WEAK(_op_) \ Loading @@ -50,15 +50,15 @@ inline bool operator _op_ (const U* o) const { \ return m_ptr _op_ o; \ } #define COMPARE(_op_) \ COMPARE_WEAK(_op_) \ inline bool operator _op_ (const wp<T>& o) const { \ return m_ptr _op_ o.m_ptr; \ } \ template<typename U> \ inline bool operator _op_ (const wp<U>& o) const { \ return m_ptr _op_ o.m_ptr; \ } // --------------------------------------------------------------------------- class ReferenceMover; class ReferenceConverterBase { public: virtual size_t getReferenceTypeSize() const = 0; virtual void* getReferenceBase(void const*) const = 0; inline virtual ~ReferenceConverterBase() { } }; // --------------------------------------------------------------------------- Loading Loading @@ -115,6 +115,8 @@ public: getWeakRefs()->trackMe(enable, retain); } typedef RefBase basetype; protected: RefBase(); virtual ~RefBase(); Loading @@ -137,6 +139,11 @@ protected: 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; Loading Loading @@ -167,73 +174,20 @@ public: return mCount; } typedef LightRefBase<T> basetype; protected: inline ~LightRefBase() { } private: mutable volatile int32_t mCount; }; // --------------------------------------------------------------------------- template <typename T> class sp { public: typedef typename RefBase::weakref_type weakref_type; inline sp() : m_ptr(0) { } sp(T* other); sp(const sp<T>& other); template<typename U> sp(U* other); template<typename U> sp(const sp<U>& other); ~sp(); // Assignment sp& operator = (T* other); sp& operator = (const sp<T>& other); template<typename U> sp& operator = (const sp<U>& other); template<typename U> sp& operator = (U* other); //! Special optimization for use by ProcessState (and nobody else). void force_set(T* other); // Reset void clear(); // Accessors inline T& operator* () const { return *m_ptr; } inline T* operator-> () const { return m_ptr; } inline T* get() const { return m_ptr; } // Operators COMPARE(==) COMPARE(!=) COMPARE(>) COMPARE(<) COMPARE(<=) COMPARE(>=) friend class ReferenceMover; inline static void moveReferences(void* d, void const* s, size_t n, const ReferenceConverterBase& caster) { } private: template<typename Y> friend class sp; template<typename Y> friend class wp; // Optimization for wp::promote(). sp(T* p, weakref_type* refs); T* m_ptr; mutable volatile int32_t mCount; }; template <typename T> TextOutput& operator<<(TextOutput& to, const sp<T>& val); // --------------------------------------------------------------------------- template <typename T> Loading Loading @@ -329,112 +283,11 @@ private: template <typename T> TextOutput& operator<<(TextOutput& to, const wp<T>& val); #undef COMPARE #undef COMPARE_WEAK // --------------------------------------------------------------------------- // No user serviceable parts below here. template<typename T> sp<T>::sp(T* other) : m_ptr(other) { if (other) other->incStrong(this); } template<typename T> sp<T>::sp(const sp<T>& other) : m_ptr(other.m_ptr) { if (m_ptr) m_ptr->incStrong(this); } template<typename T> template<typename U> sp<T>::sp(U* other) : m_ptr(other) { if (other) other->incStrong(this); } template<typename T> template<typename U> sp<T>::sp(const sp<U>& other) : m_ptr(other.m_ptr) { if (m_ptr) m_ptr->incStrong(this); } template<typename T> sp<T>::~sp() { if (m_ptr) m_ptr->decStrong(this); } template<typename T> sp<T>& sp<T>::operator = (const sp<T>& other) { T* otherPtr(other.m_ptr); if (otherPtr) otherPtr->incStrong(this); if (m_ptr) m_ptr->decStrong(this); m_ptr = otherPtr; return *this; } template<typename T> sp<T>& sp<T>::operator = (T* other) { if (other) other->incStrong(this); if (m_ptr) m_ptr->decStrong(this); m_ptr = other; return *this; } template<typename T> template<typename U> sp<T>& sp<T>::operator = (const sp<U>& other) { U* otherPtr(other.m_ptr); if (otherPtr) otherPtr->incStrong(this); if (m_ptr) m_ptr->decStrong(this); m_ptr = otherPtr; return *this; } template<typename T> template<typename U> sp<T>& sp<T>::operator = (U* other) { if (other) other->incStrong(this); if (m_ptr) m_ptr->decStrong(this); m_ptr = other; return *this; } template<typename T> void sp<T>::force_set(T* other) { other->forceIncStrong(this); m_ptr = other; } template<typename T> void sp<T>::clear() { if (m_ptr) { m_ptr->decStrong(this); m_ptr = 0; } } template<typename T> sp<T>::sp(T* p, weakref_type* refs) : m_ptr((p && refs->attemptIncStrong(this)) ? p : 0) { } template <typename T> inline TextOutput& operator<<(TextOutput& to, const sp<T>& val) { return printStrongPointer(to, val.get()); } // --------------------------------------------------------------------------- template<typename T> wp<T>::wp(T* other) : m_ptr(other) Loading Loading @@ -572,7 +425,8 @@ void wp<T>::set_object_and_refs(T* other, weakref_type* refs) template<typename T> sp<T> wp<T>::promote() const { return sp<T>(m_ptr, m_refs); T* p = (m_ptr && m_refs->attemptIncStrong(this)) ? m_ptr : 0; return sp<T>(p, true); } template<typename T> Loading @@ -590,6 +444,77 @@ 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 // --------------------------------------------------------------------------- Loading
include/utils/StrongPointer.h 0 → 100644 +224 −0 Original line number Diff line number Diff line /* * 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_STRONG_POINTER_H #define ANDROID_STRONG_POINTER_H #include <cutils/atomic.h> #include <stdint.h> #include <sys/types.h> #include <stdlib.h> // --------------------------------------------------------------------------- namespace android { class TextOutput; TextOutput& printStrongPointer(TextOutput& to, const void* val); template<typename T> class wp; // --------------------------------------------------------------------------- #define COMPARE(_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; \ } \ inline bool operator _op_ (const wp<T>& o) const { \ return m_ptr _op_ o.m_ptr; \ } \ template<typename U> \ inline bool operator _op_ (const wp<U>& o) const { \ return m_ptr _op_ o.m_ptr; \ } // --------------------------------------------------------------------------- template <typename T> class sp { public: inline sp() : m_ptr(0) { } sp(T* other); sp(const sp<T>& other); template<typename U> sp(U* other); template<typename U> sp(const sp<U>& other); ~sp(); // Assignment sp& operator = (T* other); sp& operator = (const sp<T>& other); template<typename U> sp& operator = (const sp<U>& other); template<typename U> sp& operator = (U* other); //! Special optimization for use by ProcessState (and nobody else). void force_set(T* other); // Reset void clear(); // Accessors inline T& operator* () const { return *m_ptr; } inline T* operator-> () const { return m_ptr; } inline T* get() const { return m_ptr; } // Operators COMPARE(==) COMPARE(!=) COMPARE(>) COMPARE(<) COMPARE(<=) COMPARE(>=) private: template<typename Y> friend class sp; template<typename Y> friend class wp; // Optimization for wp::promote(). sp(T* p, bool); T* m_ptr; }; #undef COMPARE template <typename T> TextOutput& operator<<(TextOutput& to, const sp<T>& val); // --------------------------------------------------------------------------- // No user serviceable parts below here. template<typename T> sp<T>::sp(T* other) : m_ptr(other) { if (other) other->incStrong(this); } template<typename T> sp<T>::sp(const sp<T>& other) : m_ptr(other.m_ptr) { if (m_ptr) m_ptr->incStrong(this); } template<typename T> template<typename U> sp<T>::sp(U* other) : m_ptr(other) { if (other) other->incStrong(this); } template<typename T> template<typename U> sp<T>::sp(const sp<U>& other) : m_ptr(other.m_ptr) { if (m_ptr) m_ptr->incStrong(this); } template<typename T> sp<T>::~sp() { if (m_ptr) m_ptr->decStrong(this); } template<typename T> sp<T>& sp<T>::operator = (const sp<T>& other) { T* otherPtr(other.m_ptr); if (otherPtr) otherPtr->incStrong(this); if (m_ptr) m_ptr->decStrong(this); m_ptr = otherPtr; return *this; } template<typename T> sp<T>& sp<T>::operator = (T* other) { if (other) other->incStrong(this); if (m_ptr) m_ptr->decStrong(this); m_ptr = other; return *this; } template<typename T> template<typename U> sp<T>& sp<T>::operator = (const sp<U>& other) { U* otherPtr(other.m_ptr); if (otherPtr) otherPtr->incStrong(this); if (m_ptr) m_ptr->decStrong(this); m_ptr = otherPtr; return *this; } template<typename T> template<typename U> sp<T>& sp<T>::operator = (U* other) { if (other) other->incStrong(this); if (m_ptr) m_ptr->decStrong(this); m_ptr = other; return *this; } template<typename T> void sp<T>::force_set(T* other) { other->forceIncStrong(this); m_ptr = other; } template<typename T> void sp<T>::clear() { if (m_ptr) { m_ptr->decStrong(this); m_ptr = 0; } } template<typename T> sp<T>::sp(T* p, bool) : m_ptr(p) { } template <typename T> inline TextOutput& operator<<(TextOutput& to, const sp<T>& val) { return printStrongPointer(to, val.get()); } }; // namespace android // --------------------------------------------------------------------------- #endif // ANDROID_STRONG_POINTER_H
include/utils/TypeHelpers.h +0 −13 Original line number Diff line number Diff line Loading @@ -37,18 +37,6 @@ template <typename T> struct trait_trivial_move { enum { value = false }; }; template <typename T> struct trait_pointer { enum { value = false }; }; template <typename T> struct trait_pointer<T*> { enum { value = true }; }; // sp<> can be trivially moved template <typename T> class sp; template <typename T> struct trait_trivial_move< sp<T> >{ enum { value = true }; }; // wp<> can be trivially moved template <typename T> class wp; template <typename T> struct trait_trivial_move< wp<T> >{ enum { value = true }; }; template <typename TYPE> struct traits { enum { Loading Loading @@ -217,7 +205,6 @@ void move_backward_type(TYPE* d, const TYPE* s, size_t n = 1) { } } // --------------------------------------------------------------------------- /* Loading
libs/utils/RefBase.cpp +101 −70 Original line number Diff line number Diff line Loading @@ -20,7 +20,6 @@ #include <utils/Atomic.h> #include <utils/CallStack.h> #include <utils/KeyedVector.h> #include <utils/Log.h> #include <utils/threads.h> #include <utils/TextOutput.h> Loading @@ -35,6 +34,7 @@ // compile with refcounting debugging enabled #define DEBUG_REFS 0 #define DEBUG_REFS_FATAL_SANITY_CHECKS 0 #define DEBUG_REFS_ENABLED_BY_DEFAULT 1 #define DEBUG_REFS_CALLSTACK_ENABLED 1 Loading Loading @@ -70,8 +70,10 @@ public: void addStrongRef(const void* /*id*/) { } void removeStrongRef(const void* /*id*/) { } void renameStrongRefId(const void* /*old_id*/, const void* /*new_id*/) { } void addWeakRef(const void* /*id*/) { } void removeWeakRef(const void* /*id*/) { } void renameWeakRefId(const void* /*old_id*/, const void* /*new_id*/) { } void printRefs() const { } void trackMe(bool, bool) { } Loading @@ -87,40 +89,74 @@ public: , mTrackEnabled(!!DEBUG_REFS_ENABLED_BY_DEFAULT) , mRetain(false) { //LOGI("NEW weakref_impl %p for RefBase %p", this, base); } ~weakref_impl() { LOG_ALWAYS_FATAL_IF(!mRetain && mStrongRefs != NULL, "Strong references remain!"); LOG_ALWAYS_FATAL_IF(!mRetain && mWeakRefs != NULL, "Weak references remain!"); bool dumpStack = false; if (!mRetain && mStrongRefs != NULL) { dumpStack = true; #if DEBUG_REFS_FATAL_SANITY_CHECKS LOG_ALWAYS_FATAL("Strong references remain!"); #else LOGE("Strong references remain!"); #endif } void addStrongRef(const void* id) { if (!mRetain && mWeakRefs != NULL) { dumpStack = true; #if DEBUG_REFS_FATAL_SANITY_CHECKS LOG_ALWAYS_FATAL("Weak references remain!"); #else LOGE("Weak references remain!"); #endif } if (dumpStack) { CallStack stack; stack.update(); stack.dump(); } } void addStrongRef(const void* id) { //LOGD_IF(mTrackEnabled, // "addStrongRef: RefBase=%p, id=%p", mBase, id); addRef(&mStrongRefs, id, mStrong); } void removeStrongRef(const void* id) { if (!mRetain) void removeStrongRef(const void* id) { //LOGD_IF(mTrackEnabled, // "removeStrongRef: RefBase=%p, id=%p", mBase, id); if (!mRetain) { removeRef(&mStrongRefs, id); else } else { addRef(&mStrongRefs, id, -mStrong); } } void addWeakRef(const void* id) { void renameStrongRefId(const void* old_id, const void* new_id) { //LOGD_IF(mTrackEnabled, // "renameStrongRefId: RefBase=%p, oid=%p, nid=%p", // mBase, old_id, new_id); renameRefsId(mStrongRefs, old_id, new_id); } void addWeakRef(const void* id) { addRef(&mWeakRefs, id, mWeak); } void removeWeakRef(const void* id) { if (!mRetain) void removeWeakRef(const void* id) { if (!mRetain) { removeRef(&mWeakRefs, id); else } else { addRef(&mWeakRefs, id, -mWeak); } } void renameWeakRefId(const void* old_id, const void* new_id) { renameRefsId(mWeakRefs, old_id, new_id); } void trackMe(bool track, bool retain) { Loading @@ -133,8 +169,7 @@ public: String8 text; { AutoMutex _l(const_cast<weakref_impl*>(this)->mMutex); Mutex::Autolock _l(const_cast<weakref_impl*>(this)->mMutex); char buf[128]; sprintf(buf, "Strong references on RefBase %p (weakref_type %p):\n", mBase, this); text.append(buf); Loading Loading @@ -173,6 +208,7 @@ private: { if (mTrackEnabled) { AutoMutex _l(mMutex); ref_entry* ref = new ref_entry; // Reference count at the time of the snapshot, but before the // update. Positive value means we increment, negative--we Loading @@ -182,7 +218,6 @@ private: #if DEBUG_REFS_CALLSTACK_ENABLED ref->stack.update(2); #endif ref->next = *refs; *refs = ref; } Loading @@ -200,13 +235,37 @@ private: delete ref; return; } refs = &ref->next; ref = *refs; } LOG_ALWAYS_FATAL("RefBase: removing id %p on RefBase %p (weakref_type %p) that doesn't exist!", #if DEBUG_REFS_FATAL_SANITY_CHECKS LOG_ALWAYS_FATAL("RefBase: removing id %p on RefBase %p" "(weakref_type %p) that doesn't exist!", id, mBase, this); #endif LOGE("RefBase: removing id %p on RefBase %p" "(weakref_type %p) that doesn't exist!", id, mBase, this); CallStack stack; stack.update(); stack.dump(); } } void renameRefsId(ref_entry* r, const void* old_id, const void* new_id) { if (mTrackEnabled) { AutoMutex _l(mMutex); ref_entry* ref = r; while (ref != NULL) { if (ref->id == old_id) { ref->id = new_id; } ref = ref->next; } } } Loading Loading @@ -236,44 +295,6 @@ private: // on removeref that match the address ones. bool mRetain; #if 0 void addRef(KeyedVector<const void*, int32_t>* refs, const void* id) { AutoMutex _l(mMutex); ssize_t i = refs->indexOfKey(id); if (i >= 0) { ++(refs->editValueAt(i)); } else { i = refs->add(id, 1); } } void removeRef(KeyedVector<const void*, int32_t>* refs, const void* id) { AutoMutex _l(mMutex); ssize_t i = refs->indexOfKey(id); LOG_ALWAYS_FATAL_IF(i < 0, "RefBase: removing id %p that doesn't exist!", id); if (i >= 0) { int32_t val = --(refs->editValueAt(i)); if (val == 0) { refs->removeItemsAt(i); } } } void printRefs(const KeyedVector<const void*, int32_t>& refs) { const size_t N=refs.size(); for (size_t i=0; i<N; i++) { printf("\tID %p: %d remain\n", refs.keyAt(i), refs.valueAt(i)); } } mutable Mutex mMutex; KeyedVector<const void*, int32_t> mStrongRefs; KeyedVector<const void*, int32_t> mWeakRefs; #endif #endif }; Loading @@ -282,7 +303,6 @@ private: void RefBase::incStrong(const void* id) const { weakref_impl* const refs = mRefs; refs->addWeakRef(id); refs->incWeak(id); refs->addStrongRef(id); Loading Loading @@ -314,14 +334,12 @@ void RefBase::decStrong(const void* id) const delete this; } } refs->removeWeakRef(id); refs->decWeak(id); } void RefBase::forceIncStrong(const void* id) const { weakref_impl* const refs = mRefs; refs->addWeakRef(id); refs->incWeak(id); refs->addStrongRef(id); Loading Loading @@ -433,7 +451,6 @@ bool RefBase::weakref_type::attemptIncStrong(const void* id) } } impl->addWeakRef(id); impl->addStrongRef(id); #if PRINT_REFS Loading Loading @@ -498,14 +515,11 @@ RefBase::weakref_type* RefBase::getWeakRefs() const RefBase::RefBase() : mRefs(new weakref_impl(this)) { // LOGV("Creating refs %p with RefBase %p\n", mRefs, this); } RefBase::~RefBase() { // LOGV("Destroying RefBase %p (refs %p)\n", this, mRefs); if (mRefs->mWeak == 0) { // LOGV("Freeing refs %p of old RefBase %p\n", mRefs, this); delete mRefs; } } Loading Loading @@ -534,6 +548,23 @@ void RefBase::onLastWeakRef(const void* /*id*/) // --------------------------------------------------------------------------- void RefBase::moveReferences(void* dst, void const* src, size_t n, const ReferenceConverterBase& caster) { #if DEBUG_REFS const size_t itemSize = caster.getReferenceTypeSize(); for (size_t i=0 ; i<n ; i++) { void* d = reinterpret_cast<void *>(intptr_t(dst) + i*itemSize); void const* s = reinterpret_cast<void const*>(intptr_t(src) + i*itemSize); RefBase* ref(reinterpret_cast<RefBase*>(caster.getReferenceBase(d))); ref->mRefs->renameStrongRefId(s, d); ref->mRefs->renameWeakRefId(s, d); } #endif } // --------------------------------------------------------------------------- TextOutput& printStrongPointer(TextOutput& to, const void* val) { to << "sp<>(" << val << ")"; Loading