前言
最近解决稳定性问题,遇到sp问题,本文就简单梳理RefBase和sp、wp下。
RefBase
RefBase是Android中所有对象的始祖,类似于MFC中的CObject及Java中的Object对象。在Android中,RefBase结合sp和wp,实现了一套通过引用计数的方法来控制对象生命周期的机制。
sp的意思应该是strong pointer,而wp则是weak pointer的意思。Android推出这一套机制可能是模仿Java,因为Java世界中有所谓weak reference之类的东西。sp和wp的目的,就是为了帮助健忘的程序员回收new出来的内存。
// 类A继承自RefBase
class A : RefBase {
}
int main{
A *pa = new A();
{
sp<A> spA(pa);
wp<A> wpA(pa);
// 大括号结束后,析构wp和sp
}
return 0;
}
RefBase
system/core/include/utils/RefBase.h
system/core/libutils/RefBase.cpp
class RefBase
{
public:
void incStrong(const void* id) const;
void decStrong(const void* id) const;
void forceIncStrong(const void* id) const;
int32_t getStrongCount() const;
class weakref_type
{
public:
RefBase* refBase() const;
void incWeak(const void* id);
void decWeak(const void* id);
bool attemptIncStrong(const void* id);
};
weakref_type* createWeak(const void* id) const;
weakref_type* getWeakRefs() const;
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);
weakref_impl* const mRefs;
};
- 创建RefBase时同时创建影子对象weakref_impl,名为mRefs。
mRefs是引用计数管理的关键类,它是从RefBase的内部类weakref_type中派生出来的(继承)。
class RefBase::weakref_impl : public RefBase::weakref_type
{
public:
std::atomic<int32_t> mStrong;
std::atomic<int32_t> mWeak;
RefBase* const mBase;
std::atomic<int32_t> mFlags;
weakref_impl(RefBase* base)
: mStrong(INITIAL_STRONG_VALUE)
, mWeak(0)
, mBase(base) // 实际对象
, mFlags(0)
{
}
...
}
// 构造函数,会同时创建其内部类(影子对象)weakref_impl
RefBase::RefBase()
: mRefs(new weakref_impl(this))
{
}
// 强引用+1
void RefBase::incStrong(const void* id) const
{
weakref_impl* const refs = mRefs;
refs->incWeak(id);
refs->addStrongRef(id);
const int32_t c = refs->mStrong.fetch_add(1, std::memory_order_relaxed);
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;
}
int32_t old = refs->mStrong.fetch_sub(INITIAL_STRONG_VALUE,
std::memory_order_relaxed);
// A decStrong() must still happen after us.
ALOG_ASSERT(old > INITIAL_STRONG_VALUE, "0x%x too small", old);
refs->mBase->onFirstRef();
}
// 强引用-1
void RefBase::decStrong(const void* id) const
{
weakref_impl* const refs = mRefs;
refs->removeStrongRef(id);
const int32_t c = refs->mStrong.fetch_sub(1, std::memory_order_release);
#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) {
std::atomic_thread_fence(std::memory_order_acquire);
refs->mBase->onLastStrongRef(id);
int32_t flags = refs->mFlags.load(std::memory_order_relaxed);
if ((flags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_STRONG) {
delete this;
// Since mStrong had been incremented, the destructor did not
// delete refs.
}
}
// Note that even with only strong reference operations, the thread
// deallocating this may not be the same as the thread deallocating refs.
// That's OK: all accesses to this happen before its deletion here,
// and all accesses to refs happen before its deletion in the final decWeak.
// The destructor can safely access mRefs because either it's deleting
// mRefs itself, or it's running entirely before the final mWeak decrement.
refs->decWeak(id);
}
sp
frameworks/rs/cpp/util/StrongPointer.h
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;
};
template<typename T>
sp<T>::sp(T* other)
: m_ptr(other)
{
if (other) other->incStrong(this);
}
template<typename T>
sp<T>::~sp()
{
if (m_ptr) m_ptr->decStrong(this);
}
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;
};
template<typename T>
wp<T>::wp(T* other)
: m_ptr(other)
{
if (other) m_refs = other->createWeak(this);
}
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;
}
理解Refbase强弱引用
深入理解Android(卷l)