- 智能指针
- LightRefBase
- RefBase
- StrongPointer
- WeakPointer
智能指针
这是自己实现的一个 SmartPointer.没有引入引用计数的概念.只是负责维护对象指针.
// SmartPointer.h
#ifndef SMART_POINTER_DEF_H
#define SMART_POINTER_DEF_H
template<typename T>
class SmartPointer
{
protected:
T *m_ptr;
public:
SmartPointer();
SmartPointer(const T *ptr);
~SmartPointer();
T* operator->();
T& operator*();
};
template<typename T>
SmartPointer<T>::SmartPointer()
{
m_ptr = NULL;
}
template<typename T>
SmartPointer<T>::SmartPointer(const T *ptr)
{
m_ptr = const_cast<T*>(ptr);
}
template<typename T>
SmartPointer<T>::~SmartPointer()
{
delete m_ptr;
}
template<typename T>
T* SmartPointer<T>::operator->()
{
return m_ptr;
}
template<typename T>
T& SmartPointer<T>::operator*()
{
return *m_ptr;
}
#endif // SMART_POINTER_DEF_H
// example.cpp
#include <cstdlib>
#include <iostream>
#include "SmartPointer.h"
using namespace std;
class Test {
public:
int i;
void print()
{
cout << i << endl;
}
};
int main(int argc, char **argv)
{
SmartPointer<int> pi = new int(5);
SmartPointer<Test> pt = new Test();
cout << *pi << endl;
*pi = 10;
cout << *pi << endl;
pt->i = 20;
pt->print();
return 0;
}
上述中 SmartPointer 明显缺点就是没有 引用计数. 如果我们想引入引用计数, 那么需要思考一个问题, 引用计数由谁维护?
-
引用计数由 智能指针 持有?
一个对象的引用计数只能有一个,但是每引用一次对象都要创建一个智能指针,那么就有好多个引用计数.明显的不合逻辑.
-
引用计数由 Object 自身持有
这是合理的.
接着的问题是如何维护 智能指针,引用计数,被引用对象 三者之间的关系.
下文依据 Android 源码来回答这个问题.
LightRefBase
template <class T>
class LightRefBase
{
public:
inline LightRefBase() : mCount(0) { }
inline void incStrong(__attribute__((unused)) const void* id) const { // 增加引用计数
mCount.fetch_add(1, std::memory_order_relaxed);
}
inline void decStrong(__attribute__((unused)) const void* id) const { // 减少引用计数
if (mCount.fetch_sub(1, std::memory_order_release) == 1) {
std::atomic_thread_fence(std::memory_order_acquire);
delete static_cast<const T*>(this); // 删除被引用对象
/*
* this 指针指向的是 LightRefBase 的 子类 对象.
*/
}
}
//! DEBUGGING ONLY: Get current strong ref count.
inline int32_t getStrongCount() const {
return mCount.load(std::memory_order_relaxed);
}
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 std::atomic<int32_t> mCount; // 引用计数 -> 原子变量
};
在 AndroidO 源码中,有一个 LightRefBase 的 Demo,修改修改,可以测试.
class SPFoo : public LightRefBase<SPFoo> {
public:
explicit SPFoo(bool* deleted_check) : mDeleted(deleted_check) {
*mDeleted = false;
}
~SPFoo() {
*mDeleted = true;
}
private:
bool* mDeleted;
};
int main(int argc, char **argv)
{
bool isDeleted;
sp<SPFoo> foo = new SPFoo(&isDeleted);
ALOGD("RefCnt = %d", foo->getStrongCount());
if (isDeleted) {
ALOGD("Already deleted...?");
}
sp<SPFoo> sp1(foo);
ALOGD("RefCnt = %d", foo->getStrongCount());
{
sp<SPFoo> sp2 = std::move(sp1);
/*
* std::move 并不会增加引用计数.
* 指向完后, sp1将变为 null.
*/
ALOGD("foo = %d, sp2 = %d",
foo->getStrongCount(), sp2->getStrongCount());
if (2 != foo->getStrongCount()) {
ALOGD("std::move failed, incremented refcnt");
}
if (nullptr != sp1.get()) {
ALOGE("std::move failed, sp1 is still valid");
}
if (nullptr == sp2.get()) {
ALOGE("sp2 is still valid");
}
sp1 = std::move(sp2);
ALOGD("RefCnt = %d", foo->getStrongCount());
}
if (isDeleted) {
ALOGD("deleted too early! still has a reference!");
}
{
:sp<SPFoo> sp2 = std::move(sp1);
ALOGD("RefCnt = %d", foo->getStrongCount());
}
if (!isDeleted) {
ALOGD("foo was leaded!");
}
return 0;
}
- sp 就是 Class StrongPointer.
- StrongPointer 知道什么时候增加,减少引用计数. 具体引用计数的维护交给了 LightRefBase.
RefBase
之前,我们先看下 StrongPointer.
StrongPointer
在 Android 中可以看到如下代码:
class A : public RefBase
{
...
}
{
sp<A> aa = new A();
}
就是说继承自 RefBase 也是使用 sp.
想说明的一个问题是, sp 可以适配 LightRefBase, 也可以适配 RefBase. sp 只是定义了什么时候增加引用计数,具体实现如何增加,由 LightRefBase 或 RefBase 管理.
下面来看 class sp 如何定义?
template<typename T> class wp;
// ---------------------------------------------------------------------------
// 操作符重载
// m_ptr 是实际分配的对象的地址,也就是 "new A()" 的地址.
#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); // NOLINT(implicit)
sp(const sp<T>& other);
sp(sp<T>&& other);
template<typename U> sp(U* other); // NOLINT(implicit)
template<typename U> sp(const sp<U>& other); // NOLINT(implicit)
template<typename U> sp(sp<U>&& other); // NOLINT(implicit)
~sp();
// Assignment
sp& operator = (T* other);
sp& operator = (const sp<T>& other);
sp& operator = (sp<T>&& other);
template<typename U> sp& operator = (const sp<U>& other);
template<typename U> sp& operator = (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;
};
// For code size reasons, we do not want this inlined or templated.
void sp_report_race();
#undef COMPARE
// ---------------------------------------------------------------------------
// No user serviceable parts below here.
template<typename T>
sp<T>::sp(T* other)
: m_ptr(other) {
if (other) {
other->incStrong(this); // other 指向 class A 的对象,A 可以继承自 RefBase,也可以继承自 LightRefBase
}
}
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>
sp<T>::sp(sp<T>&& other)
: m_ptr(other.m_ptr) {
other.m_ptr = nullptr; // 这里有意思, 引用的引用
}
template<typename T> template<typename U>
sp<T>::sp(U* other)
: m_ptr(other) {
if (other)
(static_cast<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> template<typename U>
sp<T>::sp(sp<U>&& other)
: m_ptr(other.m_ptr) {
other.m_ptr = nullptr;
}
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) {
// Force m_ptr to be read twice, to heuristically check for data races.
T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
T* otherPtr(other.m_ptr);
if (otherPtr) otherPtr->incStrong(this);
if (oldPtr) oldPtr->decStrong(this);
if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
m_ptr = otherPtr;
return *this;
}
template<typename T>
sp<T>& sp<T>::operator =(sp<T>&& other) {
T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
if (oldPtr) oldPtr->decStrong(this);
if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
m_ptr = other.m_ptr;
other.m_ptr = nullptr;
return *this;
}
template<typename T>
sp<T>& sp<T>::operator =(T* other) {
T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
if (other) other->incStrong(this);
if (oldPtr) oldPtr->decStrong(this);
if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
m_ptr = other;
return *this;
}
template<typename T> template<typename U>
sp<T>& sp<T>::operator =(const sp<U>& other) {
T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
T* otherPtr(other.m_ptr);
if (otherPtr) otherPtr->incStrong(this);
if (oldPtr) oldPtr->decStrong(this);
if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
m_ptr = otherPtr;
return *this;
}
template<typename T> template<typename U>
sp<T>& sp<T>::operator =(sp<U>&& other) {
T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
if (m_ptr) m_ptr->decStrong(this);
if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
m_ptr = other.m_ptr;
other.m_ptr = nullptr;
return *this;
}
template<typename T> template<typename U>
sp<T>& sp<T>::operator =(U* other) {
T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
if (other) (static_cast<T*>(other))->incStrong(this);
if (oldPtr) oldPtr->decStrong(this);
if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
m_ptr = other;
return *this;
}
template<typename T>
void sp<T>::force_set(T* other) {
other->forceIncStrong(this); // 什么是 forceInStrong?
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;
}
- StrongPointer 构造时 增加引用计数.
- StrongPointer 析构时 减少引用计数.
- StrongPointer 操作符 = 重载, 减少之前引用对象计数,增加新的引用对象计数.
ReBase 的定义
// RefBase.h
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
};
// Invoked after creation of initial strong pointer/reference.
virtual void onFirstRef();
// Invoked when either the last strong reference goes away, or we need to undo
// the effect of an unnecessary onIncStrongAttempted.
virtual void onLastStrongRef(const void* id);
// Only called in OBJECT_LIFETIME_WEAK case. Returns true if OK to promote to
// strong reference. May have side effects if it returns true.
// The first flags argument is always FIRST_INC_STRONG.
// TODO: Remove initial flag argument.
virtual bool onIncStrongAttempted(uint32_t flags, const void* id);
// Invoked in the OBJECT_LIFETIME_WEAK case when the last reference of either
// kind goes away. Unused.
// TODO: Remove.
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;
};
- 引用计数由 RefBase 的内部类 weakref_type 的子类 weakref_impl 维护.
- weakref_impl 是 weakref_type 的子类, weakref_type 只是提供接口,具体实现由 weakref_impl 完成.
-
RefBase 中 强引用 相关 API:
- incStorng
- decStrong
- forceIncStrong
- getStrongCount
-
RefBase 中 弱引用 相关 API:
- createWeak
- weakref_type->incWeak
- weakref_type->decWeak
RefBase 的构造
RefBase::RefBase()
: mRefs(new weakref_impl(this))
{
/*
* mRefs 很重要.
*/
}
weakref_impl
weakref_impl 不只是维护弱引用计数,也维护强引用计数.也就是说 sp 调用 RefBase 的 incStrong ,最后会调到 weakref_impl 的某个接口或者直接修改 weakref_impl 中 维护强引用计数的变量 mStrong.
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; // 描述对象的生命周期
/*
* mFlags 说明:
* mFlags 取值范围: OBJECT_LIFETIME_STRONG, OBJECT_LIFETIME_WEAK
* OBJECT_LIFETIME_STRONG: 表示对象的生命周期只受强引用计数影响.
* OBJECT_LIFETIME_WEAK: 表示对象寿命周期同事受强引用计数和弱引用计数的影响.
*/
/*
* weakref_impl 提供了 DEBUG 版本, DEBUG 版本用来调试 weakref_impl.
* 这里我都会进行详细分析.
*/
#if !DEBUG_REFS
/*
* weakref_impl 非调试 版本.
*/
explicit weakref_impl(RefBase* base)
: mStrong(INITIAL_STRONG_VALUE) // mStrong 初始值 为 : (1<<28)
, mWeak(0)
, mBase(base)
, mFlags(0) // mFlags 初始值为0 ,也就是 OBJECT_LIFETIME_STRONG. 默认对象只受引用计数影响.
{
}
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) { }
#else
weakref_impl(RefBase* base)
: mStrong(INITIAL_STRONG_VALUE)
, mWeak(0)
, mBase(base)
, mFlags(0)
, mStrongRefs(NULL)
, mWeakRefs(NULL)
, mTrackEnabled(!!DEBUG_REFS_ENABLED_BY_DEFAULT)
, mRetain(false)
{
}
/*
* mTrackEnabled : 如果 mTrackEnabled == false, addref 和 removeref 什么都不做.
* mRetain: 调用 addref 或 removeref 时 收集 stack traces, 而不是 删除 引用堆栈.
*/
~weakref_impl()
{
bool dumpStack = false;
if (!mRetain && mStrongRefs != NULL) {
/*
* 如果 mRetain == false, 在 析构 weakref_impl 时, mStrong 应该为 0, mStrongRefs 也该为 NULL; 如果不为0, 表示引用计数出错.
*/
dumpStack = true;
ALOGE("Strong references remain:");
/*
* 关于 ref_entry 下文详述.先跳到下文看 ref_entry 的详细描述.
*/
/*
* mStrongRefs 是 ref_entry * 类型, 而 ref_entry 是一个链表.
*/
ref_entry* refs = mStrongRefs;
/*
* 遍历 mStrongRefs 这个链表
*/
while (refs) {
char inc = refs->ref >= 0 ? '+' : '-'; // 如果 refs->ref > 0, 这 inc = '+'
ALOGD("\t%c ID %p (ref %d):", inc, refs->id, refs->ref); // 打印 debug log 信息.
#if DEBUG_REFS_CALLSTACK_ENABLED
refs->stack.log(LOG_TAG);
#endif
refs = refs->next;
}
}
/*
* 对 mWeakRefs 处理类似, mWeakRefs 也是一个 ref_entry 链表.
*/
if (!mRetain && mWeakRefs != NULL) {
dumpStack = true;
ALOGE("Weak references remain!");
ref_entry* refs = mWeakRefs;
while (refs) {
char inc = refs->ref >= 0 ? '+' : '-';
ALOGD("\t%c ID %p (ref %d):", inc, refs->id, refs->ref);
#if DEBUG_REFS_CALLSTACK_ENABLED
refs->stack.log(LOG_TAG);
#endif
refs = refs->next;
}
}
if (dumpStack) {
ALOGE("above errors at:");
CallStack stack(LOG_TAG);
}
}
/*
* 再次强调: id 是 sp 或 wp 的地址
*/
void addStrongRef(const void* id) {
//ALOGD_IF(mTrackEnabled,
// "addStrongRef: RefBase=%p, id=%p", mBase, id);
addRef(&mStrongRefs, id, mStrong.load(std::memory_order_relaxed));
/*
* addRef 将 id 和 mStrong 包装成 ref_entry , 添加到 mStrongRefs 这链表中.
*/
}
void removeStrongRef(const void* id) {
//ALOGD_IF(mTrackEnabled,
// "removeStrongRef: RefBase=%p, id=%p", mBase, id);
if (!mRetain) {
/*
* remoteRefs 删除 mStrongRefs 链表中 id 对应的 节点.
*/
removeRef(&mStrongRefs, id);
} else {
/*
* 这里很重要,如果 mRetain == true, 不是调用 removeRef 删除链表节点, 而是 增加一个 负数 节点.
* 想想这么做也是有理的.
*/
addRef(&mStrongRefs, id, -mStrong.load(std::memory_order_relaxed));
}
}
void renameStrongRefId(const void* old_id, const void* new_id) {
//ALOGD_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.load(std::memory_order_relaxed));
}
void removeWeakRef(const void* id) {
if (!mRetain) {
removeRef(&mWeakRefs, id);
} else {
addRef(&mWeakRefs, id, -mWeak.load(std::memory_order_relaxed));
}
}
void renameWeakRefId(const void* old_id, const void* new_id) {
renameRefsId(mWeakRefs, old_id, new_id);
}
void trackMe(bool track, bool retain)
{
mTrackEnabled = track;
mRetain = retain;
}
void printRefs() const
{
String8 text;
{
Mutex::Autolock _l(mMutex);
char buf[128];
snprintf(buf, sizeof(buf),
"Strong references on RefBase %p (weakref_type %p):\n",
mBase, this);
text.append(buf);
printRefsLocked(&text, mStrongRefs);
snprintf(buf, sizeof(buf),
"Weak references on RefBase %p (weakref_type %p):\n",
mBase, this);
text.append(buf);
printRefsLocked(&text, mWeakRefs);
}
{
char name[100];
snprintf(name, sizeof(name), DEBUG_REFS_CALLSTACK_PATH "/%p.stack",
this);
int rc = open(name, O_RDWR | O_CREAT | O_APPEND, 644);
if (rc >= 0) {
write(rc, text.string(), text.length());
close(rc);
ALOGD("STACK TRACE for %p saved in %s", this, name);
}
else ALOGE("FAILED TO PRINT STACK TRACE for %p in %s: %s", this,
name, strerror(errno));
}
}
private:
struct ref_entry
{
ref_entry* next; // 这是一个链表
const void* id; // id 是 sp 或 wp 的地址. id 很好追查.
#if DEBUG_REFS_CALLSTACK_ENABLED
CallStack stack; // CallStack
#endif
int32_t ref; // ref 是引用计数, 如果 ref_entry 描述的是 强引用计数,那么就是 mStrong 的值.
};
/*
* 这是 核心函数.非常清楚.就是构造节点,插入链表
*/
void addRef(ref_entry** refs, const void* id, int32_t mRef)
{
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
// decrement the reference count.
ref->ref = mRef;
ref->id = id;
#if DEBUG_REFS_CALLSTACK_ENABLED
ref->stack.update(2);
#endif
ref->next = *refs;
*refs = ref;
}
}
/*
* 遍历链表,找到 id 对应的节点,并且删除该节点.
*/
void removeRef(ref_entry** refs, const void* id)
{
if (mTrackEnabled) {
AutoMutex _l(mMutex);
ref_entry* const head = *refs;
ref_entry* ref = head;
while (ref != NULL) {
if (ref->id == id) {
*refs = ref->next;
delete ref;
return;
}
refs = &ref->next;
ref = *refs;
}
ALOGE("RefBase: removing id %p on RefBase %p"
"(weakref_type %p) that doesn't exist!",
id, mBase, this);
ref = head;
while (ref) {
char inc = ref->ref >= 0 ? '+' : '-';
ALOGD("\t%c ID %p (ref %d):", inc, ref->id, ref->ref);
ref = ref->next;
}
CallStack stack(LOG_TAG);
}
}
/*
* 将 old_id 对应的 链表节点 ref_entry 中的 id 元素替换成 new_id.
*/
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;
}
}
}
void printRefsLocked(String8* out, const ref_entry* refs) const
{
char buf[128];
while (refs) {
char inc = refs->ref >= 0 ? '+' : '-';
snprintf(buf, sizeof(buf), "\t%c ID %p (ref %d):\n",
inc, refs->id, refs->ref);
out->append(buf);
#if DEBUG_REFS_CALLSTACK_ENABLED
out->append(refs->stack.toString("\t\t"));
#else
out->append("\t\t(call stacks disabled)");
#endif
refs = refs->next;
}
}
mutable Mutex mMutex;
ref_entry* mStrongRefs;
ref_entry* mWeakRefs;
bool mTrackEnabled;
// Collect stack traces on addref and removeref, instead of deleting the stack references
// on removeref that match the address ones.
bool mRetain;
#endif
};
分析完 weakref_impl , 发现 在正式版本中, weakref_impl 只是负责定义 4 个变量, 且是 public 变量:mStrong, mWeak, mBase, mFlags.
在 调试版本中, weakref_impl 负责打印 debug message.
如何实现强引用计数?
增加强引用计数
void RefBase::incStrong(const void* id) const
{
weakref_impl* const refs = mRefs;
refs->incWeak(id);
refs->addStrongRef(id); // Debug 相关,已经分析过
const int32_t c = refs->mStrong.fetch_add(1, std::memory_order_relaxed); // 增加强引用计数
if (c != INITIAL_STRONG_VALUE) { // 如果不是第一次被强引用,直接返回
return;
}
// mStrong 的初始值: 0x10000000
// 第一次引用后 mStrong 的值是 0x10000000+1, old = 0x10000000+1
int32_t old = refs->mStrong.fetch_sub(INITIAL_STRONG_VALUE,
std::memory_order_relaxed);
/*
* 执行完后: mStrong == 1 ; 真是折腾啊!!
*/
// A decStrong() must still happen after us.
ALOG_ASSERT(old > INITIAL_STRONG_VALUE, "0x%x too small", old);
refs->mBase->onFirstRef(); // 这里是关键, 回调 onFirstRef()
}
incStrong 做了 3 件事:
- 增加弱引用计数
- 增加强引用计数
- 如果是第一次被强引用,调用 onFirstRef 来通知对象. onFirstRef 由 RefBase 子类重写.
incWeak
void RefBase::weakref_type::incWeak(const void* id)
{
weakref_impl* const impl = static_cast<weakref_impl*>(this); // this 指向 weakref_impl
impl->addWeakRef(id); // debug
const int32_t c __unused = impl->mWeak.fetch_add(1,
std::memory_order_relaxed); // mWeak + 1
ALOG_ASSERT(c >= 0, "incWeak called on %p after last weak ref", this);
}
减少强引用计数
void RefBase::decStrong(const void* id) const
{
weakref_impl* const refs = mRefs;
refs->removeStrongRef(id); // debug
const int32_t c = refs->mStrong.fetch_sub(1, std::memory_order_release); // mStrong - 1
#if PRINT_REFS
ALOGD("decStrong of %p from %p: cnt=%d\n", this, id, c);
#endif
LOG_ALWAYS_FATAL_IF(BAD_STRONG(c), "decStrong() called on %p too many times",
refs);
if (c == 1) { // 如果在当前是 最后一个 强引用, 那么就要考虑释放对象了
std::atomic_thread_fence(std::memory_order_acquire);
// 首先通过 onLastSrongRef 通知对象
refs->mBase->onLastStrongRef(id);
// 读取 mFlags 的值
int32_t flags = refs->mFlags.load(std::memory_order_relaxed);
if ((flags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_STRONG) {
// 此时,说明 OBJECT_LIFETIME_WEAK 没有设置.所以 对象的生命周期 只受 强引用计数的影响.
/*
* Object 的声明周期要想和 弱引用计数 相关,需要 设置 mFlags 为 OBJECT_LIFETIME_WEAK.
* 这是通过调用 RefBase::extendObjectLifetime 方法实现的.
* 在 ./framework 下,查找 extendObjectLifetimed 的调用, 只有 Binder 中有.
* 说明一般使用者,可以不去 Care 弱引用计数.
*/
// this 指向的就是对象.所以删除对象.
delete this;
// The destructor does not delete refs in this case.
}
}
// 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); // 不管如何, 还是要 decWeak 来减少弱引用计数的
}
~RefBase
RefBase::~RefBase()
{
int32_t flags = mRefs->mFlags.load(std::memory_order_relaxed);
// Life-time of this object is extended to WEAK, in
// which case weakref_impl doesn't out-live the object and we
// can free it now.
if ((flags & OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_WEAK) {
// It's possible that the weak count is not 0 if the object
// re-acquired a weak reference in its destructor
if (mRefs->mWeak.load(std::memory_order_relaxed) == 0) {
delete mRefs;
}
} else if (mRefs->mStrong.load(std::memory_order_relaxed)
== INITIAL_STRONG_VALUE) {
// We never acquired a strong reference on this object.
LOG_ALWAYS_FATAL_IF(mRefs->mWeak.load() != 0,
"RefBase: Explicit destruction with non-zero weak "
"reference count");
// TODO: Always report if we get here. Currently MediaMetadataRetriever
// C++ objects are inconsistently managed and sometimes get here.
// There may be other cases, but we believe they should all be fixed.
delete mRefs;
}
// For debugging purposes, clear mRefs. Ineffective against outstanding wp's.
const_cast<weakref_impl*&>(mRefs) = NULL;
/*
* 如果没有扩展 RefBase 的生命周期, 那么这个调用只执行最后一句话.
*/
}
decWeak
void RefBase::weakref_type::decWeak(const void* id)
{
weakref_impl* const impl = static_cast<weakref_impl*>(this);
impl->removeWeakRef(id);
const int32_t c = impl->mWeak.fetch_sub(1, std::memory_order_release);
LOG_ALWAYS_FATAL_IF(BAD_WEAK(c), "decWeak called on %p too many times",
this);
if (c != 1) return;
atomic_thread_fence(std::memory_order_acquire);
int32_t flags = impl->mFlags.load(std::memory_order_relaxed);
/*
* 对象 生命周期 只受 强引用计数 影响.
*/
if ((flags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_STRONG) {
// This is the regular lifetime case. The object is destroyed
// when the last strong reference goes away. Since weakref_impl
// outlives the object, it is not destroyed in the dtor, and
// we'll have to do it here.
if (impl->mStrong.load(std::memory_order_relaxed)
== INITIAL_STRONG_VALUE) {
// Decrementing a weak count to zero when object never had a strong
// reference. We assume it acquired a weak reference early, e.g.
// in the constructor, and will eventually be properly destroyed,
// usually via incrementing and decrementing the strong count.
// Thus we no longer do anything here. We log this case, since it
// seems to be extremely rare, and should not normally occur. We
// used to deallocate mBase here, so this may now indicate a leak.
ALOGW("RefBase: Object at %p lost last weak reference "
"before it had a strong reference", impl->mBase);
} else {
ALOGD("Freeing refs %p of old RefBase %p\n", this, impl->mBase);
delete impl;
/*
* 这里删除 weakref_impl.
*/
}
} else {
// This is the OBJECT_LIFETIME_WEAK case. The last weak-reference
// is gone, we can destroy the object.
/*
* 如果对象的生命周期受 弱引用计数 的影响.
* 1. 回调 onLastWeakRef
* 2. 删除 impl->mBase,也就是销毁对象.
*/
impl->mBase->onLastWeakRef(id);
delete impl->mBase;
}
}
如何实现弱引用计数?
非常重要的一点:
弱引用计数不直接操作它所引用的对象, 因为它所引用的对象可能不受引用计数控制,即它所引用的对象是一个无效的对象.
因此,如果需要操作一个弱指针所引用的对象,那么就需要将这个若指针升级为强指针, 这是通过成员函数 promote 来实现的.
如果升级成功,说明该若指针所引用的对象还没有被销毁,可以正常使用.
wp
#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; \
}
template <typename T>
class wp
{
public:
typedef typename RefBase::weakref_type weakref_type;
inline wp() : m_ptr(0) { }
wp(T* other); // NOLINT(implicit)
wp(const wp<T>& other);
explicit wp(const sp<T>& other);
template<typename U> wp(U* other); // NOLINT(implicit)
template<typename U> wp(const sp<U>& other); // NOLINT(implicit)
template<typename U> wp(const wp<U>& other); // NOLINT(implicit)
~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());
}
- createWeak
RefBase::weakref_type* RefBase::createWeak(const void* id) const
{
mRefs->incWeak(id);
return mRefs;
}
incWeak 已经分析过.
wp 是无法操作所引用对象的,因为 wp 没有重载 -> 和 * 操作符. wp 要想 操作对象,需要通过 promote 方法升级为强指针.
promote
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;
}
attemptIncStrong
attemptIncStrong 试图增加目标对象的强引用计数,但是可能会增加失败,因为目标对象可能已经被释放了,或者目标对象不允许强指针引用它.
bool RefBase::weakref_type::attemptIncStrong(const void* id)
{
incWeak(id); // 增加弱引用计数
weakref_impl* const impl = static_cast<weakref_impl*>(this);
int32_t curCount = impl->mStrong.load(std::memory_order_relaxed); // 获取当前的强引用计数
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.
/*
* 当预期的值与对象真正持有的值相等,那么它将返回成功并把所需的值写入内存。否则,预期值会被内存中实际的值覆盖更新,并返回失败。
* 关于 C++ automic 是个大学问,需要深入了解.
* 这里只需要明白,这是在将 引用计数 + 1
*/
if (impl->mStrong.compare_exchange_weak(curCount, curCount+1,
std::memory_order_relaxed)) {
break;
}
// the strong count has changed on us, we need to re-assert our
// situation. curCount was updated by compare_exchange_weak.
}
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
int32_t flags = impl->mFlags.load(std::memory_order_relaxed);
if ((flags&OBJECT_LIFETIME_MASK) == 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 (impl->mStrong.compare_exchange_weak(curCount, curCount+1,
std::memory_order_relaxed)) {
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 has been updated.
}
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 = impl->mStrong.fetch_add(1, std::memory_order_relaxed);
// 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
// curCount is the value of mStrong before we incremented it.
// 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 > INITIAL_STRONG_VALUE is OK, and can happen if we're doing
// this in the middle of another incStrong. The subtraction is handled
// by the thread that started with INITIAL_STRONG_VALUE.
if (curCount == INITIAL_STRONG_VALUE) {
impl->mStrong.fetch_sub(INITIAL_STRONG_VALUE,
std::memory_order_relaxed);
}
return true;
}
set_pointer
template<typename T>
void sp<T>::set_pointer(T* ptr) {
m_ptr = ptr;
}
循环引用
namespace andorid {
class Bigclass : public RefBase
{
public:
Bigclass(char *name){
strcpy(mName, name);
ALOGD("Construct: %s", mName);
}
~Bigclass(){
ALOGD("destruct: %s", mName);
}
void setStrongRefs(sp<Bigclass> b) {
spB = b;
}
private:
sp<Bigclass> spB;
char mName[64];
};
};
using name android;
void testStrongCrossRef()
{
sp<Bigclass> A = new Bigclass("testStrongClassA"); // A -> ref_cnt = 1
sp<Bigclass> B = new Bigclass("testStrongClassB"); // B -> ref_cnt = 1
A->setStrongRefs(B); // B->ref_cnt = 2, B->ref_cnt = 3, B->ref_cnt = 2
B->setStrongRefs(A); // A->ref_cng = 2, A->ref_cnt = 3, A->ref_cnt = 2
/*
* 说明: 实际参数到形似参数的传递也会 构造 sp, 增加 引用计数.但是在函数执行完后,会进行析构.
*/
/*
* A->ref_cnt = 1
* B->ref_cnt = 1
* 结果就是 ref_cnt != 0, 导致对象无法释放.
*/
}
int main()
{
ALOGD("Start testStrongClasses..");
testStrongCrossRef();
ALOGD("testStrongClasses Should be destructed!!");
return 0;
}
如何解决?
namespace andorid {
class Bigclass : public RefBase
{
public:
Bigclass(char *name){
strcpy(mName, name);
ALOGD("Construct: %s", mName);
}
~Bigclass(){
ALOGD("destruct: %s", mName);
}
void setStrongRefs(sp<Bigclass> b) {
spB = b;
}
void setWeakRefs(sp<Bigclass> b) {
wpB = b;
}
private:
wp<Bigclass> wpB;
sp<Bigclass> spB;
char mName[64];
};
};
using name android;
void testStrongCrossRef()
{
sp<Bigclass> A = new Bigclass("testStrongClassA"); // A -> ref_cnt = 1
sp<Bigclass> B = new Bigclass("testStrongClassB"); // B -> ref_cnt = 1
A->setWeakRefs(B); // B->ref_cnt = 2, B->ref_cnt = 1
B->setWeakRefs(A); // A->ref_cng = 2, A->ref_cnt = 1
/*
* 说明: 实际参数到形似参数的传递也会 构造 sp, 增加 引用计数.但是在函数执行完后,会进行析构.
*/
/*
* A->ref_cnt = 0
* B->ref_cnt = 0
*/
}
int main()
{
ALOGD("Start testStrongClasses..");
testStrongCrossRef();
ALOGD("testStrongClasses Should be destructed!!");
return 0;
}
Android中,最常用的肯定不是上面两种:
- 强强引用——互不相让,互相绑死,这是绝对禁止的。
- 弱弱引用——互不相干,各管生死。这个对于想要使用引用计数自动管理对象生命周期来说,没什么用处。
最常用的一般是强弱引用关系。强弱引用需要是有从属关系的,具体那个类是用sp引用,哪个是用wp引用,要看设计的逻辑了。
测试示例:
void testCrossRef(){
sp<Bigclass> A = new Bigclass("testNormalClassA");
sp<Bigclass> B = new Bigclass("testNormalClassB");
A->setStrongRefs(B);
B->setWeakRefs(A);
}
这种情况下,消除了循环引用,没有了内存泄露问题。 和上一个弱弱引用的例子比较,这里testNormalClassB的析构在testWeakClassA之后,testWeakClassB的生命周期是受testWeakClassA控制的,只有testWeakClassA析构,testWeakClassB才会析构。(上面的弱弱引用的测例,说明在无干预的情况下,应该是testWeakClassB先析构的)
对于强弱指针的使用,使用弱指针是需要特别注意,弱指针指向的对象,可能已经被销毁了,使用前需要通过promote()方法探测一下,详细信息可参考《深入理解Android》
循环引用问题2
namespace android {
class Bigclass : public RefBase
{
public:
Bigclass(char *name) {
strcpy(mName, name);
ALOGD("Construct: %s", mName);
}
~Bigclass() {
ALOGD("destruct: %s", mName);
}
void setStrongRefs(sp<Bigclass> b) {
spB = b;
}
void setWeakRefs(sp<Bigclass> b) {
ALOGD("--1---%s------", mName);
wpB = b;
sp<Bigclass> s = wpB.promote(); // 这里 promote 会将 弱引用转换为 强引用,会不会引起 retain cycle 呢?
if (s != NULL) {
s->printName();
}
ALOGD("--2---%s------", mName);
}
void printName() {
ALOGD("Name : %s", mName);
}
private:
sp<Bigclass> spB;
wp<Bigclass> wpB;
char mName[64];
};
};
void testStrongCrossRef()
{
sp<Bigclass> A = new Bigclass("testStrongClassA");
sp<Bigclass> B = new Bigclass("testStrongClassB");
A->setWeakRefs(B);
B->setWeakRefs(A);
}
int main()
{
ALOGD("Start testStrongClasses..");
testStrongCrossRef();
ALOGD("testStrongClasses Should be destructed!!");
return 0;
}
答案是: 不会.
上述例子中,只要 强引用计数 没有增加到 3, 就不会 retain cycle.
在实际参数到形式参数的传递中,也就是形式参数中的 wp 构造,并没有增加 引用计数.所以没有问题.