Android指针管理:RefBase,SP,WP (二)
(1)在Android中,RefBase结合了sp和wp,实现了一套通过引用计数的方法来控制对象声明周期的方法。
RefBase的定义在/frameworks/base/include/utils/RefBase.h,实现在/frameworks/base/libs/utils/RefBase.cpp。
wp的定义在/frameworks/base/include/utils/RefBase.h,
sp的定义在/frameworks/base/include/utils/StrongPointer.h中。
(2)weakref_impl是weakref_type 的子类
android_atomic_dec(&mCount) == 1 mCount减1,但是返回的是mCount减1之前的值。如果返回1,表示这次减过之后引用计数就是0了,就把对象delete掉。
android_atomic_inc(&impl->mStrong) mCount加1,但是返回的是mCount加1之前的值。
android_atomic_add(-INITIAL_STRONG_VALUE, &impl->mStrong); 加一个数,在此加的是(-INITIAL_STRONG_VALUE)
android_atomic_cmpxchg(curCount, curCount+1, &impl->mStrong) 表示如果impl->mStrong的值为curCount,则把impl->mString的值改为curCount+1
(3)对象声明周期的控制
enum {
OBJECT_LIFETIME_STRONG = 0x0000,
OBJECT_LIFETIME_WEAK = 0x0001,
OBJECT_LIFETIME_MASK = 0x0001
};
void extendObjectLifetime(int32_t mode);
RefBase中,声明了一个枚举和extendObjectLifetime函数,来控制对象的生命周期。
void RefBase::extendObjectLifetime(int32_t mode)
{
android_atomic_or(mode, &mRefs->mFlags); // 用mode给weakref_impl的mFlags赋值 mFlags只在这一个地方赋值
}
(4)
incStrong中, 将强引用数与弱引用数同时 +1
decStrong中,将强引用数与弱引用数同时 -1
incWeak中,只有弱引用数 +1
decWeak中,只有弱引用数 -1
(5)
weakref_impl.mFlag == OBJECT_LIFETIME_STRONG时:
强引用计数来控制对象的生命周期,弱引用对象控制weakref_impl的生命周期。
强引用为0,对象被delete;弱引用为0时,weakref_impl被delete。
记住:使用wp时,要有sp生成,否则可能会引起segment fault。
weakref_impl.mFlag == OBJECT_LIFETIME_WEAK时:
由弱引用来控制对象和weakref_impl的生命周期。
强引用为0无作用,弱引用为0时,对象和weakref_impl被同时delete。
(6)
void RefBase::incStrong(const void* id) const
{
weakref_impl* const refs = mRefs;
refs->incWeak(id); refs->addStrongRef(id);
//refs->mStrong的值+1,但是返回的c是+1之前的值
const int32_t c = android_atomic_inc(&refs->mStrong);
ALOG_ASSERT(c > 0, "incStrong() called on %p after last strong ref", refs);
#if PRINT_REFS
ALOGD("incStrong of %p from %p: cnt=%d\n", this, id, c);
#endif
if (c != INITIAL_STRONG_VALUE) { //+1之前不是INITAL_STRONG_VALUE,返回
return;
} //refs->mStrong= INITIAL_STRONG_VALUE + 1 - INITIAL_STRONG_VALUE = 1 最终为1
android_atomic_add(-INITIAL_STRONG_VALUE, &refs->mStrong);
refs->mBase->onFirstRef();
}
第一次创建强引用会回调RefBase的onFirstRef()方法,这个方法很重要,派生类可以重载次方法,做一些初始化操作。在audio system中,很多类重载此方法!!!
RefBase.h 源文件
#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>
#include <utils/TypeHelpers.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 ReferenceRenamer {
protected:
// destructor is purposedly not virtual so we avoid code overhead from
// subclasses; we have to make it protected to guarantee that it
// cannot be called from this base class (and to make strict compilers
// happy).
~ReferenceRenamer() { }
public:
virtual void operator()(size_t i) const = 0;
}; // --------------------------------------------------------------------------- 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); // acquires a strong reference if there is already one.
bool attemptIncStrong(const void* id); // acquires a weak reference if there is already one.
// This is not always safe. see ProcessState.cpp and BpBinder.cpp
// for proper use.
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_STRONG = 0x0000,
OBJECT_LIFETIME_WEAK = 0x0001,
OBJECT_LIFETIME_MASK = 0x0001
}; 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 weakref_type;
class weakref_impl; RefBase(const RefBase& o);
RefBase& operator=(const RefBase& o); private:
friend class ReferenceMover; static void renameRefs(size_t n, const ReferenceRenamer& renamer); static void renameRefId(weakref_type* ref,
const void* old_id, const void* new_id); static void renameRefId(RefBase* ref,
const void* old_id, const void* new_id); weakref_impl* const mRefs;
}; // --------------------------------------------------------------------------- template <class T>
class LightRefBase
{
public:
inline LightRefBase() : mCount(0) { }
inline void incStrong(__attribute__((unused)) const void* id) const {
android_atomic_inc(&mCount);
}
inline void decStrong(__attribute__((unused)) 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 renameRefs(size_t n, const ReferenceRenamer& renamer) { }
inline static void renameRefId(T* ref,
const void* old_id, const void* new_id) { } 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 {
public:
// it would be nice if we could make sure no extra code is generated
// for sp<TYPE> or wp<TYPE> when TYPE is a descendant of RefBase:
// Using a sp<RefBase> override doesn't work; it's a bit like we wanted
// a template<typename TYPE inherits RefBase> template... template<typename TYPE> static inline
void move_references(sp<TYPE>* d, sp<TYPE> const* s, size_t n) { class Renamer : public ReferenceRenamer {
sp<TYPE>* d;
sp<TYPE> const* s;
virtual void operator()(size_t i) const {
// The id are known to be the sp<>'s this pointer
TYPE::renameRefId(d[i].get(), &s[i], &d[i]);
}
public:
Renamer(sp<TYPE>* d, sp<TYPE> const* s) : s(s), d(d) { }
}; memmove(d, s, n*sizeof(sp<TYPE>));
TYPE::renameRefs(n, Renamer(d, s));
} template<typename TYPE> static inline
void move_references(wp<TYPE>* d, wp<TYPE> const* s, size_t n) { class Renamer : public ReferenceRenamer {
wp<TYPE>* d;
wp<TYPE> const* s;
virtual void operator()(size_t i) const {
// The id are known to be the wp<>'s this pointer
TYPE::renameRefId(d[i].get_refs(), &s[i], &d[i]);
}
public:
Renamer(wp<TYPE>* d, wp<TYPE> const* s) : s(s), d(d) { }
}; memmove(d, s, n*sizeof(wp<TYPE>));
TYPE::renameRefs(n, Renamer(d, s));
}
}; // 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
去掉Debug和其他信息,简化之后的RefBase.h:
类RefBase:
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; weakref_type* createWeak(const void* id) const; weakref_type* getWeakRefs() const; typedef RefBase basetype; protected:
RefBase();
virtual ~RefBase(); //! Flags for extendObjectLifetime()
enum {
OBJECT_LIFETIME_STRONG = 0x0000,
OBJECT_LIFETIME_WEAK = 0x0001,
OBJECT_LIFETIME_MASK = 0x0001
}; 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 weakref_type;
class weakref_impl; RefBase(const RefBase& o);
RefBase& operator=(const RefBase& o); };
类LightRefBase:
template <class T>
class LightRefBase
{
public:
inline LightRefBase() : mCount(0) { }
inline void incStrong(__attribute__((unused)) const void* id) const {
android_atomic_inc(&mCount);
}
inline void decStrong(__attribute__((unused)) 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 renameRefs(size_t n, const ReferenceRenamer& renamer) { }
inline static void renameRefId(T* ref,
const void* old_id, const void* new_id) { } private:
mutable volatile int32_t mCount;
};
类wp:
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;
};
类wp函数实现:
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;
}
}
RefBase.cpp 源文件
简化之后的RefBase.cpp:
继承自weakref_type的类weakref_impl:
class RefBase::weakref_impl : public RefBase::weakref_type
{
public:
volatile int32_t mStrong;
volatile int32_t mWeak;
RefBase* const mBase;
volatile int32_t mFlags; weakref_impl(RefBase* base)
: mStrong(INITIAL_STRONG_VALUE)
, mWeak(0)
, mBase(base)
, mFlags(0)
{
} 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) { } };
RefBase类的函数实现:
#define INITIAL_STRONG_VALUE (1<<28) void RefBase::incStrong(const void* id) const
{
weakref_impl* const refs = mRefs;
refs->incWeak(id); refs->addStrongRef(id);
const int32_t c = android_atomic_inc(&refs->mStrong);
ALOG_ASSERT(c > 0, "incStrong() called on %p after last strong ref", refs);
#if PRINT_REFS
ALOGD("incStrong of %p from %p: cnt=%d\n", this, id, c);
#endif
if (c != INITIAL_STRONG_VALUE) {
return;
} android_atomic_add(-INITIAL_STRONG_VALUE, &refs->mStrong);
refs->mBase->onFirstRef();
} void RefBase::decStrong(const void* id) const
{
weakref_impl* const refs = mRefs;
refs->removeStrongRef(id);
const int32_t c = android_atomic_dec(&refs->mStrong);
#if PRINT_REFS
ALOGD("decStrong of %p from %p: cnt=%d\n", this, id, c);
#endif
ALOG_ASSERT(c >= 1, "decStrong() called on %p too many times", refs);
if (c == 1) {
refs->mBase->onLastStrongRef(id);
if ((refs->mFlags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_STRONG) {
delete this;
}
}
refs->decWeak(id);
} void RefBase::forceIncStrong(const void* id) const
{
weakref_impl* const refs = mRefs;
refs->incWeak(id); refs->addStrongRef(id);
const int32_t c = android_atomic_inc(&refs->mStrong);
ALOG_ASSERT(c >= 0, "forceIncStrong called on %p after ref count underflow",
refs);
#if PRINT_REFS
ALOGD("forceIncStrong of %p from %p: cnt=%d\n", this, id, c);
#endif switch (c) {
case INITIAL_STRONG_VALUE:
android_atomic_add(-INITIAL_STRONG_VALUE, &refs->mStrong);
// fall through...
case 0:
refs->mBase->onFirstRef();
}
} int32_t RefBase::getStrongCount() const
{
return mRefs->mStrong;
} RefBase::weakref_type* RefBase::createWeak(const void* id) const
{
mRefs->incWeak(id);
return mRefs;
} RefBase::weakref_type* RefBase::getWeakRefs() const
{
return mRefs;
} RefBase::RefBase()
: mRefs(new weakref_impl(this))
{
} RefBase::~RefBase()
{
if (mRefs->mStrong == INITIAL_STRONG_VALUE) {
// we never acquired a strong (and/or weak) reference on this object.
delete mRefs;
} else {
// life-time of this object is extended to WEAK or FOREVER, in
// which case weakref_impl doesn't out-live the object and we
// can free it now.
if ((mRefs->mFlags & OBJECT_LIFETIME_MASK) != OBJECT_LIFETIME_STRONG) {
// It's possible that the weak count is not 0 if the object
// re-acquired a weak reference in its destructor
if (mRefs->mWeak == 0) {
delete mRefs;
}
}
}
// for debugging purposes, clear this.
const_cast<weakref_impl*&>(mRefs) = NULL;
} void RefBase::extendObjectLifetime(int32_t mode)
{
android_atomic_or(mode, &mRefs->mFlags);
} void RefBase::onFirstRef()
{
} void RefBase::onLastStrongRef(const void* /*id*/)
{
} bool RefBase::onIncStrongAttempted(uint32_t flags, const void* id)
{
return (flags&FIRST_INC_STRONG) ? true : false;
} void RefBase::onLastWeakRef(const void* /*id*/)
{
}
RefBase::weakref_type 类的函数实现:
RefBase* RefBase::weakref_type::refBase() const
{
return static_cast<const weakref_impl*>(this)->mBase;
} void RefBase::weakref_type::incWeak(const void* id)
{
weakref_impl* const impl = static_cast<weakref_impl*>(this);
impl->addWeakRef(id);
const int32_t c = android_atomic_inc(&impl->mWeak);
ALOG_ASSERT(c >= 0, "incWeak called on %p after last weak ref", this);
} void RefBase::weakref_type::decWeak(const void* id)
{
weakref_impl* const impl = static_cast<weakref_impl*>(this);
impl->removeWeakRef(id);
const int32_t c = android_atomic_dec(&impl->mWeak);
ALOG_ASSERT(c >= 1, "decWeak called on %p too many times", this);
if (c != 1) return; if ((impl->mFlags&OBJECT_LIFETIME_WEAK) == OBJECT_LIFETIME_STRONG) {
// This is the regular lifetime case. The object is destroyed
// when the last strong reference goes away. Since weakref_impl
// outlive the object, it is not destroyed in the dtor, and
// we'll have to do it here.
if (impl->mStrong == INITIAL_STRONG_VALUE) {
// Special case: we never had a strong reference, so we need to
// destroy the object now.
delete impl->mBase;
} else {
// ALOGV("Freeing refs %p of old RefBase %p\n", this, impl->mBase);
delete impl;
}
} else {
// less common case: lifetime is OBJECT_LIFETIME_{WEAK|FOREVER}
impl->mBase->onLastWeakRef(id);
if ((impl->mFlags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_WEAK) {
// this is the OBJECT_LIFETIME_WEAK case. The last weak-reference
// is gone, we can destroy the object.
delete impl->mBase;
}
}
} bool RefBase::weakref_type::attemptIncStrong(const void* id)
{
incWeak(id); weakref_impl* const impl = static_cast<weakref_impl*>(this);
int32_t curCount = impl->mStrong; ALOG_ASSERT(curCount >= 0,
"attemptIncStrong called on %p after underflow", this); while (curCount > 0 && curCount != INITIAL_STRONG_VALUE) {
// we're in the easy/common case of promoting a weak-reference
// from an existing strong reference.
if (android_atomic_cmpxchg(curCount, curCount+1, &impl->mStrong) == 0) {
break;
}
// the strong count has changed on us, we need to re-assert our
// situation.
curCount = impl->mStrong;
} if (curCount <= 0 || curCount == INITIAL_STRONG_VALUE) {
// we're now in the harder case of either:
// - there never was a strong reference on us
// - or, all strong references have been released
if ((impl->mFlags&OBJECT_LIFETIME_WEAK) == OBJECT_LIFETIME_STRONG) {
// this object has a "normal" life-time, i.e.: it gets destroyed
// when the last strong reference goes away
if (curCount <= 0) {
// the last strong-reference got released, the object cannot
// be revived.
decWeak(id);
return false;
} // here, curCount == INITIAL_STRONG_VALUE, which means
// there never was a strong-reference, so we can try to
// promote this object; we need to do that atomically.
while (curCount > 0) {
if (android_atomic_cmpxchg(curCount, curCount + 1,
&impl->mStrong) == 0) {
break;
}
// the strong count has changed on us, we need to re-assert our
// situation (e.g.: another thread has inc/decStrong'ed us)
curCount = impl->mStrong;
} if (curCount <= 0) {
// promote() failed, some other thread destroyed us in the
// meantime (i.e.: strong count reached zero).
decWeak(id);
return false;
}
} else {
// this object has an "extended" life-time, i.e.: it can be
// revived from a weak-reference only.
// Ask the object's implementation if it agrees to be revived
if (!impl->mBase->onIncStrongAttempted(FIRST_INC_STRONG, id)) {
// it didn't so give-up.
decWeak(id);
return false;
}
// grab a strong-reference, which is always safe due to the
// extended life-time.
curCount = android_atomic_inc(&impl->mStrong);
} // If the strong reference count has already been incremented by
// someone else, the implementor of onIncStrongAttempted() is holding
// an unneeded reference. So call onLastStrongRef() here to remove it.
// (No, this is not pretty.) Note that we MUST NOT do this if we
// are in fact acquiring the first reference.
if (curCount > 0 && curCount < INITIAL_STRONG_VALUE) {
impl->mBase->onLastStrongRef(id);
}
} impl->addStrongRef(id); #if PRINT_REFS
ALOGD("attemptIncStrong of %p from %p: cnt=%d\n", this, id, curCount);
#endif // now we need to fix-up the count if it was INITIAL_STRONG_VALUE
// this must be done safely, i.e.: handle the case where several threads
// were here in attemptIncStrong().
curCount = impl->mStrong;
while (curCount >= INITIAL_STRONG_VALUE) {
ALOG_ASSERT(curCount > INITIAL_STRONG_VALUE,
"attemptIncStrong in %p underflowed to INITIAL_STRONG_VALUE",
this);
if (android_atomic_cmpxchg(curCount, curCount-INITIAL_STRONG_VALUE,
&impl->mStrong) == 0) {
break;
}
// the strong-count changed on us, we need to re-assert the situation,
// for e.g.: it's possible the fix-up happened in another thread.
curCount = impl->mStrong;
} return true;
} bool RefBase::weakref_type::attemptIncWeak(const void* id)
{
weakref_impl* const impl = static_cast<weakref_impl*>(this); int32_t curCount = impl->mWeak;
ALOG_ASSERT(curCount >= 0, "attemptIncWeak called on %p after underflow",
this);
while (curCount > 0) {
if (android_atomic_cmpxchg(curCount, curCount+1, &impl->mWeak) == 0) {
break;
}
curCount = impl->mWeak;
} if (curCount > 0) {
impl->addWeakRef(id);
} return curCount > 0;
} int32_t RefBase::weakref_type::getWeakCount() const
{
return static_cast<const weakref_impl*>(this)->mWeak;
} void RefBase::weakref_type::printRefs() const
{
static_cast<const weakref_impl*>(this)->printRefs();
} void RefBase::weakref_type::trackMe(bool enable, bool retain)
{
static_cast<weakref_impl*>(this)->trackMe(enable, retain);
}
sp类声明 (StrongPointer.h)
/*
* 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 { 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;
void set_pointer(T* ptr);
T* m_ptr;
}; #undef COMPARE // ---------------------------------------------------------------------------
// 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)
((T*) 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) {
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> template<typename U>
sp<T>& sp<T>::operator =(U* other) {
if (other)
((T*) 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>
void sp<T>::set_pointer(T* ptr) {
m_ptr = ptr;
} }; // namespace android // --------------------------------------------------------------------------- #endif // ANDROID_STRONG_POINTER_H
Android指针管理:RefBase,SP,WP (二)的更多相关文章
- Android指针管理:RefBase,SP,WP
Android中通过引用计数来实现智能指针,并且实现有强指针与弱指针.由对象本身来提供引用计数器,但是对象不会去维护引用计数器的值,而是由智能指针来管理. 要达到所有对象都可用引用计数器实现智能指针管 ...
- 玩转Hook——Android权限管理功能探讨(二)
距离我上一篇研究ptrace的随笔http://www.cnblogs.com/zealotrouge/p/3544147.html已经过去半年了,最近不忙的时候抽空继续研究了下.同样,参考了Prad ...
- Android智能指针sp wp详解
研究Android的时候,经常会遇到sp.wp的东西,网上一搜,原来是android封装了c++中对象回收机制.说明:1. 如果一个类想使用智能指针,那么必须满足下面两个条件: a. 该类是虚基 ...
- Android智能指针SP WP使用方法介绍
Android手机操作系统既然是开源的操作系统.那么在具体的文件夹中就会存放着各种相关功能的开源代码.我们在使用的时候可以根据这些源代码进行相应的修改就能轻松的完成我们所需的功能.在这里大家就一起来看 ...
- Android线程管理(二)——ActivityThread
线程通信.ActivityThread及Thread类是理解Android线程管理的关键. 线程,作为CPU调度资源的基本单位,在Android等针对嵌入式设备的操作系统中,有着非常重要和基础的作用. ...
- Android包管理机制(二)PackageInstaller安装APK
前言 在本系列上一篇文章Android包管理机制(一)PackageInstaller的初始化中我们学习了PackageInstaller是如何初始化的,这一篇文章我们接着学习PackageInsta ...
- sc7731 Android 5.1 Camera 学习之二 framework 到 HAL接口整理
前面已经分析过,Client端发起远程调用,而实际完成处理任务的,是Server端的 CameraClient 实例.远程client 和 server是两个不同的进程,它们使用binder作为通信工 ...
- Android窗口管理服务WindowManagerService计算窗口Z轴位置的过程分析
文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/8570428 通过前面几篇文章的学习,我们知道了 ...
- Android窗口管理服务WindowManagerService对壁纸窗口(Wallpaper Window)的管理分析
文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/8550820 Android系统中,壁纸窗口和输 ...
随机推荐
- python中模块的引用
一. 模块的定义 定义 python模块(Module),是一个python文件,以.py结尾,包含了python对象定义和python语句.模块让你能够有逻辑地组织你的python代码段,把相关的代 ...
- 分布式_理论_05_ 一致性算法 Paxos
一.前言 二.参考资料 1.分布式理论(五)—— 一致性算法 Paxos 2.分布式理论(五) - 一致性算法Paxos
- hdoj-1106-排序(stringstream)
题目链接 /* Name: Copyright: Author: Date: 2018/5/2 20:56:53 Description: */ #include <iostream> # ...
- k-means算法的优缺点以及改进
大家接触的第一个聚类方法,十有八九都是K-means聚类啦.该算法十分容易理解,也很容易实现.其实几乎所有的机器学习和数据挖掘算法都有其优点和缺点.那么K-means的缺点是什么呢? 总结为下: (1 ...
- C#异步编程(三)内核模式线程同步
其实,在开发过程中,无论是用户模式的同步构造还是内核模式,都应该尽量避免.因为线程同步都会造成阻塞,这就影响了我们的并发量,也影响整个应用的效率.不过有些情况,我们不得不进行线程同步. 内核模式 wi ...
- LeetCode Relative Ranks
原题链接在这里:https://leetcode.com/problems/relative-ranks/#/description 题目: Given scores of N athletes, f ...
- JSplitPane的简单实现
import java.awt.Color; import javax.swing.ImageIcon; import javax.swing.JFrame; import javax.swing.J ...
- shell split函数的使用
#!/bin/awk -f BEGIN{FS=","} {split($1,name," "); for (i in name) print name[i] }
- redis设置为null问题
查看源码后发现,redis没有删除方法,本想给他设置为null,但是redis报错,所有仔细想了一下,发现redis提供了一个时间限制方法,所有可以让redis的时间限制为1s,就想当于删除redis ...
- 编译cef 2526
fetch --nohooks chromium cd /path/to/chromium/src# git checkout -b 51.0.2704.103 refs/tags/51.0.2704 ...