diff options
author | Mathias Agopian <mathias@google.com> | 2011-02-16 20:23:43 -0800 |
---|---|---|
committer | Alex Ray <aray@google.com> | 2013-07-30 13:56:56 -0700 |
commit | b26ea8b30f11cf0ad11ac7983208514a1bfafb75 (patch) | |
tree | ce7599f183785ee8caccfa83b0a19283f500e761 /include/utils/RefBase.h | |
parent | 966a48f3e78e75c3a4f3a2f23b98e970f06bf983 (diff) | |
download | system_core-b26ea8b30f11cf0ad11ac7983208514a1bfafb75.zip system_core-b26ea8b30f11cf0ad11ac7983208514a1bfafb75.tar.gz system_core-b26ea8b30f11cf0ad11ac7983208514a1bfafb75.tar.bz2 |
Fix some issues with RefBase debugging.
First slipt sp<> out of RefBase into StrongPointer.h so it can be reused
more easily and to make it clear that it doesn't require RefBase.
Note: the rest of the change only affects the system when DEBUG_REFS is enabled.
The main problem we fix here is that the owner id associated with each
reference could get out of date when a sp<> or wp<> was moved, for
instance when they're used in a Vector< >.
We fix this issue by calling into RefBase::moveReferences from
a template specialization for sp<TYPE> and wp<TYPE> of the
type helpers. RefBase::moveReferences() has then a chance to
update the owner ids.
There is a little bit of trickery to implement this generically in
RefBase, where we need to use a templatized functor that can turn
a sp<TYPE>* casted to a void* into a RefBase*.
Introduced a new debug option DEBUG_REFS_FATAL_SANITY_CHECKS
currently set to 0 by default as there seem to be an issue
with sp<ANativeWindow> which trips the sanity checks.
Change-Id: I4825b21c8ec47d4a0ef35d760760ae0c9cdfbd7f
Diffstat (limited to 'include/utils/RefBase.h')
-rw-r--r-- | include/utils/RefBase.h | 277 |
1 files changed, 101 insertions, 176 deletions
diff --git a/include/utils/RefBase.h b/include/utils/RefBase.h index f8d96cf..9b0e7d8 100644 --- a/include/utils/RefBase.h +++ b/include/utils/RefBase.h @@ -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_) \ @@ -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() { } +}; // --------------------------------------------------------------------------- @@ -115,6 +115,8 @@ public: getWeakRefs()->trackMe(enable, retain); } + typedef RefBase basetype; + protected: RefBase(); virtual ~RefBase(); @@ -138,6 +140,11 @@ protected: 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; @@ -166,74 +173,21 @@ public: inline int32_t getStrongCount() const { return mCount; } - -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 + typedef LightRefBase<T> basetype; - inline T& operator* () const { return *m_ptr; } - inline T* operator-> () const { return m_ptr; } - inline T* get() const { return m_ptr; } +protected: + inline ~LightRefBase() { } - // Operators - - COMPARE(==) - COMPARE(!=) - COMPARE(>) - COMPARE(<) - COMPARE(<=) - COMPARE(>=) - -private: - template<typename Y> friend class sp; - template<typename Y> friend class wp; +private: + friend class ReferenceMover; + inline static void moveReferences(void* d, void const* s, size_t n, + const ReferenceConverterBase& caster) { } - // Optimization for wp::promote(). - sp(T* p, weakref_type* refs); - - T* m_ptr; +private: + mutable volatile int32_t mCount; }; -template <typename T> -TextOutput& operator<<(TextOutput& to, const sp<T>& val); - // --------------------------------------------------------------------------- template <typename T> @@ -329,113 +283,12 @@ 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) { @@ -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> @@ -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 // --------------------------------------------------------------------------- |