来源:
http://blog.csdn.net/shift_wwx/article/details/78864099
前言:
关于android 智能指针,前面详细分析了sp 和 wp的source code,但是还有一些疑问,在这一篇中全部解释,因为所有的源头都是来自于这里。
更多信息可以看 sp的博文 和 wp的博文
本文总结基于Android 7.0
source code:
system/core/include/utils/RefBase.h
system/core/include/libutils/RefBase.cpp
可能最开始有人注意到,sp 和 wp都是模板类,模板参数是T 或者是U,构造函数或者重载运算符的函数中形参看到的是T * 、 U *,或者是sp
例如:
class MediaPlayer : public BnMediaPlayerClient,
public virtual IMediaDeathNotifier
{
public:
MediaPlayer();
~MediaPlayer();
void died();
void disconnect();
父类是BnMediaPlayerClient 和 IMediaDeathNotifier,
class IMediaDeathNotifier: virtual public RefBase
{
public:
IMediaDeathNotifier() { addObitRecipient(this); }
virtual ~IMediaDeathNotifier() { removeObitRecipient(this); }
随便找个,可以看到是继承RefBase,注意的是虚拟继承。
注意,有可能后面会有很多类继承自RefBase,为了避免继承二义性,RefBase 的派生类都必须要虚拟继承。
来看下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;
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;
};
1、在sp 中看到的指针m_ptr都是通过incStrong 和decStrong 来控制计数,最终调用的就是这里的
2、在wp 中的m_refs的类型是weakref_type类型的指针,在这里也能看到了
所以对于wp中的指针来说,确切的说是RefBase类型的指针,只能调用createWeak,而incWeak和decWeak是weakref_type的对象才能调用。
这就解释了 wp博文 中遗留问题的第 1 、2
3、RefBase的关键是mRefs,类型为weakref_impl *,这个是整个智能指针的关键
下面来详细看下RefBase的实现,首先来看下RefBase的构造函数:
RefBase::RefBase()
: mRefs(new weakref_impl(this))
{
}
只有一个默认的构造函数,就是为了初始化mRefs,也就是说,以后RefBase的派生类在构造的时候,都会有个mRefs的指针变量。
来看下核心变量mRefs的类型weakref_impl:
class RefBase::weakref_impl : public RefBase::weakref_type
{
public:
std::atomic mStrong; //对于强引用计数控制是通过这个变量
std::atomic mWeak; //对于弱引用的计数控制是通过这个变量
RefBase* const mBase; //当前指针的标志,以后可能有很多对该指针引用,但是这个mBase只有一个
std::atomic mFlags; //判断是强引用还是弱引用
#if !DEBUG_REFS
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) { }
#else
weakref_impl(RefBase* base) //构造函数
: mStrong(INITIAL_STRONG_VALUE) //默认强引用计数为1<<28
, mWeak(0) //默认弱引用的计数为0
, mBase(base) //RefBase,也就是后来的指针,注意,后来weakref_impl需要delete的时候,这里mBase 也需要delete,具体看decWeak
, mFlags(0)
, mStrongRefs(NULL) //所有的强引用,用链表存储在这里
, mWeakRefs(NULL) //所有的弱引用,用链表存储
, mTrackEnabled(!!DEBUG_REFS_ENABLED_BY_DEFAULT)
, mRetain(false)
{
}
~weakref_impl()
{
bool dumpStack = false;
if (!mRetain && mStrongRefs != NULL) {
dumpStack = true;
ALOGE("Strong references remain:");
ref_entry* refs = mStrongRefs;
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 (!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);
}
}
void addStrongRef(const void* id) { //强引用的指针地址会做为id存放在mStrongRefs链表中
//ALOGD_IF(mTrackEnabled,
// "addStrongRef: RefBase=%p, id=%p", mBase, id);
addRef(&mStrongRefs, id, mStrong.load(std::memory_order_relaxed));
}
void removeStrongRef(const void* id) {
//ALOGD_IF(mTrackEnabled,
// "removeStrongRef: RefBase=%p, id=%p", mBase, id);
if (!mRetain) {
removeRef(&mStrongRefs, id);
} else {
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) { //将弱引用的指针作为id存放链表mWeakRefs中
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];
sprintf(buf, "Strong references on RefBase %p (weakref_type %p):\n", mBase, this);
text.append(buf);
printRefsLocked(&text, mStrongRefs);
sprintf(buf, "Weak references on RefBase %p (weakref_type %p):\n", mBase, this);
text.append(buf);
printRefsLocked(&text, mWeakRefs);
}
{
char name[100];
snprintf(name, 100, 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;
#if DEBUG_REFS_CALLSTACK_ENABLED
CallStack stack;
#endif
int32_t ref;
};
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;
}
}
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);
}
}
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 ? '+' : '-';
sprintf(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
};
再来看下incWeak():
void RefBase::weakref_type::incWeak(const void* id)
{
weakref_impl* const impl = static_cast(this);
impl->addWeakRef(id);//添加弱引用到链表中
const int32_t c __unused = impl->mWeak.fetch_add(1,
std::memory_order_relaxed); //计数加1
ALOG_ASSERT(c >= 0, "incWeak called on %p after last weak ref", this);
}
其中addWeakRef():
void addWeakRef(const void* id) {
addRef(&mWeakRefs, id, mWeak.load(std::memory_order_relaxed));
}
添加弱引用到链表。
再来看下decWeak():
void RefBase::weakref_type::decWeak(const void* id)
{
weakref_impl* const impl = static_cast(this);
impl->removeWeakRef(id); //删除弱引用
const int32_t c = impl->mWeak.fetch_sub(1, std::memory_order_release); //计数减1
ALOG_ASSERT(c >= 1, "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
// outlive 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) {
// 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 {
// This is the OBJECT_LIFETIME_WEAK case. The last weak-reference
// is gone, we can destroy the object.
impl->mBase->onLastWeakRef(id);
delete impl->mBase; //如果没有其他引用了,就释放当前指针
}
}
再来看下incStrong():
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(); //第一次添加需要调用onFirstRef()
}
再来看下decStrong():
void RefBase::decStrong(const void* id) const
{
weakref_impl* const refs = mRefs;
refs->removeStrongRef(id);//移除强引用链表中的引用id
const int32_t c = refs->mStrong.fetch_sub(1, std::memory_order_release);//计数减1
#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);//如果不是最后一个,需要减少弱引用链表
}
这样, wp博文中的第2、4点就解释完了。
小结一下:
1、incStrong和incWeak方法比较简单,就是增加一下强引用和弱引用计数,需要注意的是,incStrong方法中会调用incWeak方法
2、decWeak方法有点复杂,要做的事有两件:是否要释放真实对象,是否要释放影子对象:
1) 如果生命周期是弱引用来控制,那么在这里就需要做判断,弱应用的计数是否为0,是否要释放真实对象和影子对象
2) 如果生命周期是强引用来控制的,那么这里也要判断一下,如果强引用计数为0的话,需要释放真实对象,弱引用计数是否为0,是否要释放影子对象
从这里我们可以看到:
弱引用计数是关系影子对象的,如果弱引用计数为0,那么影子对象一定要释放,但是真实对象不一定要释放
强引用计数是关系真实对象的,如果强引用计数为0,那么真实对象一定要释放的,但是影子对象不一定释放
3、decStrong方法主要做:就是看看是否要释放真实对象,因为强引用和真实对象关联的
4、RefBase的析构方法:真实对象被销毁的时候,需要做一个工作就是释放影子对象
释放影子对象有两个场景:
1) 如果强引用计数根本没有被使用过,那么直接释放
2) 如果强引用计数使用过,但是采用的是非强生命周期管理方式,也是释放
通过RefBase的执行过程,结合wp的构造来看,最终wp中维护的m_ptr并没有使用的地方,而整个过程都是在维护弱引用的链表。
所以,wp如果要使用必须要通过promote函数,转换成sp,再通过sp的重载运算符* 和 运算符 ->来调用指针的成员。
这也就是解释了wp博文中的第 3 点。
android中除了RefBase,还有个轻量级的引用LightRefBase,前面看到的是很多类继承RefBase,后面通过sp、wp实现了智能指针。
如果只是想通过计数方式使用智能指针,也可以用LightRefBase。
先来看下LightRefBase的定义:
template
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(this);
}
}
//! DEBUGGING ONLY: Get current strong ref count.
inline int32_t getStrongCount() const {
return mCount.load(std::memory_order_relaxed);
}
typedef LightRefBase 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 mCount;
};
从整个定义来看,就一个核心变量mCount,为什么这里有incStrong、decStrong,就是为了后面使用sp准备。
可以看个例子:
class MyClass : virtual public LightRefBase {
public:
void test();
};
在main中使用的时候需要通过sp使用:
sp sp(new MyClass());
sp->test();
1、LightRefBase 同RefBase一样,必须是某个指针的基类
2、LightRefBase 轻量级引用,采用的是模板机制,而不是复杂的OOP,不需要虚拟继承
3、轻量级引用基类轻在内存,只拥有一个成员变量,用以计数。其引用计数类模板不含有虚函数,如果尾端类(不被其他类继承的类)直接继承引用计数基类,那尾端类也不需要虚的析构函数,不会出现因部分删除而产生内存泄露,因为模板类代码中有一处使用static_cast向下转型,模板确保其安全。
4、RefBase持有弱引用,持有指针,在进行删除工作时较为复杂。
缺陷:
1、不支持弱引用。
2、轻量级引用类,使用模版技术,所以模版技术的缺陷,轻量级引用亦有,很明显一点就是你会需要很多不同轻量级引用类。
3、编译级别支持引用栈对象,运行时会崩溃,Scott Meyers说过只要编译器允许,就一定有人这么干。此问题需要使用者解决-----利用protected dector 和 friend class refbase
到此,android中只能指针部分就告一段落,后期会在碰到问题继续补充说明。也请大神不吝赐教。
参考:
http://blog.csdn.net/xielinhua88/article/details/51823442
http://blog.csdn.net/zjq2008wd/article/details/17614417
https://www.cnblogs.com/angeldevil/archive/2013/03/10/2952586.html