本文参考http://blog.youkuaiyun.com/luoshengyang/article/details/6786239
一、RefBash.h
class RefBase
{
public:
void incStrong(const void* id) const;
void decStrong(const void* id) const;
int getStrongCount() const;
class weakref_type
{
public:
RefBase* refBase() const;
void incWeak(const void* id);
void decWeak(const void* id);
bool attemptIncStrong(const void* id);
int getWeakCount() const;
};
weakref_type* createWeak(const void* id) const;
weakref_type* getWeakRefs() const;
protected:
RefBase();
virtual ~RefBase();//delete this时候会调用子类
enum {
OBJECT_LIFETIME_WEAK = 0x0001,
OBJECT_LIFETIME_FOREVER = 0x0003
};
void extendObjectLifetime(int mode);
enum {
FIRST_INC_STRONG = 0x0001
};
virtual bool onIncStrongAttempted(int flags, const void* id);//子类可以覆盖
private:
//friend class weakref_type;
class weakref_impl; //不能include,只能前向声明
RefBase(const RefBase& o);
RefBase& operator=(const RefBase& o);
weakref_impl* const mRefs;
};
// ---------------------------------------------------------------------------
template <typename T>
class sp
{
public:
typedef typename RefBase::weakref_type weakref_type;
//相当于typedef RefBase::weakref_type weakref_typ
sp(T* other);
sp(const sp<T>& other);
~sp();
inline T* get() const { return m_ptr; }
private:
template<typename Y> friend class wp;//wp可以操作sp的私有变量,如构造函数
sp(T* p, weakref_type* refs);
T* m_ptr;
};
// ---------------------------------------------------------------------------
template <typename T>
class wp
{
public:
typedef RefBase::weakref_type weakref_type;
wp(T* other);
wp(const wp<T>& other);
~wp();
sp<T> promote() const;
inline weakref_type* get_refs() const { return m_refs; }
private:
T* m_ptr;//strongPointer
weakref_type* m_refs;//weakref_impl
};
// ---------------------------------------------------------------------------
template<typename T>
sp<T>::sp(T* other)
: m_ptr(other)//strongPointer
{
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>
sp<T>::~sp()
{
if (m_ptr) m_ptr->decStrong(this);
}
template<typename T>
sp<T>::sp(T* p, weakref_type* refs)
: m_ptr((p && refs->attemptIncStrong(this)) ? p : 0)
{
}
// ---------------------------------------------------------------------------
template<typename T>
wp<T>::wp(T* other)
: m_ptr(other)//strongPointer
{
if (other) m_refs = other->createWeak(this);//weakref_impl
}
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()
{
if (m_ptr) m_refs->decWeak(this);
}
template<typename T>
sp<T> wp<T>::promote() const
{
return sp<T>(m_ptr, m_refs);
}
二、RefBase.cpp
#include "RefBase.h"
#include <iostream>
using namespace std;
#define INITIAL_STRONG_VALUE (1<<28)
class RefBase::weakref_impl : public RefBase::weakref_type
{
public:
volatile int mStrong;
volatile int mWeak;
RefBase* const mBase;
volatile int mFlags;
weakref_impl(RefBase* base)
: mStrong(INITIAL_STRONG_VALUE)
, mWeak(0)
, mBase(base)
, mFlags(0)
{
}
~weakref_impl()
{
cout << "~weakref_impl"<<endl;
}
};
// ---------------------------------------------------------------------------
void RefBase::incStrong(const void* id) const
{
weakref_impl* const refs = mRefs;
refs->incWeak(id);
const int c = refs->mStrong++;
if (c != INITIAL_STRONG_VALUE) {
return;
}
refs->mStrong = refs->mStrong - INITIAL_STRONG_VALUE;
}
void RefBase::decStrong(const void* id) const
{
weakref_impl* const refs = mRefs;
const int c = --refs->mStrong;
if (c == 0) {
if ((refs->mFlags&OBJECT_LIFETIME_WEAK) != OBJECT_LIFETIME_WEAK) {//受到强指针控制
delete this;
}
}
refs->decWeak(id);
}
int RefBase::getStrongCount() const
{
return mRefs->mStrong;
}
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->mWeak++;
}
void RefBase::weakref_type::decWeak(const void* id)
{
weakref_impl* const impl = static_cast<weakref_impl*>(this);
const int c = --impl->mWeak;
if (c != 0) return;
if ((impl->mFlags&OBJECT_LIFETIME_WEAK) != OBJECT_LIFETIME_WEAK) {//受强指针控制
if (impl->mStrong == INITIAL_STRONG_VALUE){
delete impl->mBase;
}
else {
delete impl;
}
} else {
if ((impl->mFlags&OBJECT_LIFETIME_FOREVER) != OBJECT_LIFETIME_FOREVER) {//受弱指针控制
delete impl->mBase;
}
}
}
bool RefBase::weakref_type::attemptIncStrong(const void* id)
{
incWeak(id);//先增加,后面有减少,整体不变
weakref_impl* const impl = static_cast<weakref_impl*>(this);
int curCount = impl->mStrong;
if (curCount > 0 && curCount != INITIAL_STRONG_VALUE) {//mStrong变化过,且大于0
impl->mStrong = curCount + 1;
curCount = impl->mStrong;
}
if (curCount <= 0 || curCount == INITIAL_STRONG_VALUE) {//mStrong没有变化过;或者变化后,为0
bool allow;
if (curCount == INITIAL_STRONG_VALUE) {
allow = (impl->mFlags&OBJECT_LIFETIME_WEAK) != OBJECT_LIFETIME_WEAK
|| impl->mBase->onIncStrongAttempted(FIRST_INC_STRONG, id);
} else {
allow = (impl->mFlags&OBJECT_LIFETIME_WEAK) == OBJECT_LIFETIME_WEAK
&& impl->mBase->onIncStrongAttempted(FIRST_INC_STRONG, id);
}
if (!allow) {
decWeak(id);//再减少
return false;
}
curCount = impl->mStrong++;
}
if (curCount == INITIAL_STRONG_VALUE) {
impl->mStrong = impl->mStrong - INITIAL_STRONG_VALUE;
}
return true;
}
int RefBase::weakref_type::getWeakCount() const
{
return static_cast<const weakref_impl*>(this)->mWeak;
}
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->mWeak == 0) {
delete mRefs;
}
}
void RefBase::extendObjectLifetime(int mode)
{
mRefs->mFlags = mode;
}
bool RefBase::onIncStrongAttempted(int flags, const void* id)
{
return (flags&FIRST_INC_STRONG) ? true : false;
}
void RefBase::decStrong(const void* id) const
{
weakref_impl* const refs = mRefs;
const int c = --refs->mStrong;
if (c == 0) {
if ((refs->mFlags&OBJECT_LIFETIME_WEAK) != OBJECT_LIFETIME_WEAK) {//受到强指针控制
delete this;
}
}
refs->decWeak(id);
}
减少强引用计数时候,同时减少弱引用计数,如果强引用计数为0,并且受强指针控制,那么调用子类和RefBase的析构函数
void RefBase::weakref_type::decWeak(const void* id)
{
weakref_impl* const impl = static_cast<weakref_impl*>(this);
const int c = --impl->mWeak;
if (c != 0) return;
if ((impl->mFlags&OBJECT_LIFETIME_WEAK) != OBJECT_LIFETIME_WEAK) {//受强指针控制
if (impl->mStrong == INITIAL_STRONG_VALUE){
delete impl->mBase;
}
else {
delete impl;
}
} else {
if ((impl->mFlags&OBJECT_LIFETIME_FOREVER) != OBJECT_LIFETIME_FOREVER) {//受弱指针控制
delete impl->mBase;
}
}
}
RefBase::~RefBase()
{
if (mRefs->mWeak == 0) {
delete mRefs;
}
}
减少弱引用计数,如果弱引用计数为0,并且受弱指针控制,那么调用delete impl->mBase,调用上面的析构函数,因为此时mWeek==0,所以执行delete mRefs
如果弱引用计数为0,并且不受强指针,也不受弱指针控制,那么由自己调用delete来删除
如果弱引用计数为0,并且受强指针控制,如果强引用计数为0,那么只delete impl,因为RefBase及其子类已经被delelte掉了
如果弱引用计数为0,并且受强指针控制,如果强引用计数为INITIAL_STRONG_VALUE,那么说明RefBase及其子类还没有删除,那么要delelte impl->mBase,调用上面的析构函数,因为此时mWeek==0,所以执行delete mRefs
bool RefBase::weakref_type::attemptIncStrong(const void* id)
{
incWeak(id);
weakref_impl* const impl = static_cast<weakref_impl*>(this);
int curCount = impl->mStrong;
if (curCount > 0 && curCount != INITIAL_STRONG_VALUE) {
impl->mStrong = curCount + 1;
curCount = impl->mStrong;
}
if (curCount <= 0 || curCount == INITIAL_STRONG_VALUE) {
bool allow;
if (curCount == INITIAL_STRONG_VALUE) {
allow = (impl->mFlags&OBJECT_LIFETIME_WEAK) != OBJECT_LIFETIME_WEAK
|| impl->mBase->onIncStrongAttempted(FIRST_INC_STRONG, id);
} else {
allow = (impl->mFlags&OBJECT_LIFETIME_WEAK) == OBJECT_LIFETIME_WEAK
&& impl->mBase->onIncStrongAttempted(FIRST_INC_STRONG, id);
}
if (!allow) {
decWeak(id);
return false;
}
curCount = impl->mStrong++;
}
if (curCount == INITIAL_STRONG_VALUE + 1) {
impl->mStrong = impl->mStrong - INITIAL_STRONG_VALUE;
}
return true;
}
if (curCount > 0 && curCount != INITIAL_STRONG_VALUE) {
impl->mStrong = curCount + 1;
curCount = impl->mStrong;
}
如果此时强引用计数不为0,或者初始值,那么说明RefBase及其子类还没有删除,所以可以提升为强引用
allow = (impl->mFlags&OBJECT_LIFETIME_WEAK) == OBJECT_LIFETIME_WEAK
&& impl->mBase->onIncStrongAttempted(FIRST_INC_STRONG, id);
如果此时强引用计数为0,并且还受强指针控制,那么此时,RefBase及其子类已经被删除了,所以不能提升为强引用
如果此时强引用计数为0,并且还受弱指针控制,那么此时,RefBase及其子类还没有删除,能不能提升就看impl->mBase->onIncStrongAttempted(FIRST_INC_STRONG, id)的了
allow = (impl->mFlags&OBJECT_LIFETIME_WEAK) != OBJECT_LIFETIME_WEAK
|| impl->mBase->onIncStrongAttempted(FIRST_INC_STRONG, id);
如果此时强引用计数为INITIAL_STRONG_VALUE,并且还受强指针控制,此时RefBase及其子类还没有删除,所以能够提升。
如果此时强引用计数为INITIAL_STRONG_VALUE,并且还受弱指针控制,此时RefBase及其子类还没有删除,能不能提升就看impl->mBase->onIncStrongAttempted(FIRST_INC_STRONG, id)的了
三、main.cpp
#include <stdio.h>
#include "RefBase.h"
#define INITIAL_STRONG_VALUE (1<<28)
class WeightClass: public RefBase {
public:
void printRefCount() {
int strong = getStrongCount();
weakref_type* ref = getWeakRefs();
printf("-----------------------\n");
printf("Strong Ref Count: %d.\n",
(strong == INITIAL_STRONG_VALUE ? 0 : strong));
printf("Weak Ref Count: %d.\n", ref->getWeakCount());
printf("-----------------------\n");
}
};
class StrongClass: public WeightClass {
public:
StrongClass() {
printf("Construct StrongClass Object.\n");
}
virtual ~StrongClass() {
printf("Destory StrongClass Object.\n");
}
};
class WeakClass: public WeightClass {
public:
WeakClass() {
extendObjectLifetime(OBJECT_LIFETIME_WEAK);
printf("Construct WeakClass Object.\n");
}
virtual ~WeakClass() {
printf("Destory WeakClass Object.\n");
}
};
class ForeverClass: public WeightClass {
public:
ForeverClass() {
extendObjectLifetime(OBJECT_LIFETIME_FOREVER);
printf("Construct ForeverClass Object.\n");
}
virtual ~ForeverClass() {
printf("Destory ForeverClass Object.\n");
}
};
void TestStrongClass(StrongClass* pStrongClass) {
wp<StrongClass> wpOut = pStrongClass;
pStrongClass->printRefCount();
{
sp<StrongClass> spInner = pStrongClass;
pStrongClass->printRefCount();
}
pStrongClass->printRefCount();
sp<StrongClass> spOut = wpOut.promote();
printf("spOut: %p.\n", spOut.get());
pStrongClass->printRefCount();
}
void TestStrongClass2(StrongClass* pStrongClass) {
wp<StrongClass> wpOut = pStrongClass;
pStrongClass->printRefCount();
}
void TestStrongClass4(StrongClass* pStrongClass) {
wp<StrongClass> wpOut = pStrongClass;
pStrongClass->printRefCount();
sp<StrongClass> spInner = pStrongClass;
pStrongClass->printRefCount();
sp<StrongClass> spOut = wpOut.promote();
printf("spOut: %p.\n", spOut.get());
pStrongClass->printRefCount();
}
void TestStrongClass3(StrongClass* pStrongClass) {
wp<StrongClass> wpOut = pStrongClass;
pStrongClass->printRefCount();
sp<StrongClass> spOut = wpOut.promote();
printf("spOut: %p.\n", spOut.get());
pStrongClass->printRefCount();
}
void TestWeakClass(WeakClass* pWeakClass) {
wp<WeakClass> wpOut = pWeakClass;
pWeakClass->printRefCount();
{
sp<WeakClass> spInner = pWeakClass;
pWeakClass->printRefCount();
}
pWeakClass->printRefCount();
sp<WeakClass> spOut = wpOut.promote();
printf("spOut: %p.\n", spOut.get());
pWeakClass->printRefCount();
}
void TestForeverClass(ForeverClass* pForeverClass) {
wp<ForeverClass> wpOut = pForeverClass;
pForeverClass->printRefCount();
{
sp<ForeverClass> spInner = pForeverClass;
pForeverClass->printRefCount();
}
pForeverClass->printRefCount();
}
int main(int argc, char** argv) {
/* printf("Test Strong Class: \n");
StrongClass* pStrongClass = new StrongClass();
TestStrongClass(pStrongClass);*/
/* printf("Test Strong Class2: \n");
StrongClass* pStrongClass = new StrongClass();
TestStrongClass2(pStrongClass);*/
/* printf("\nTest Weak Class: \n");
WeakClass* pWeakClass = new WeakClass();
TestWeakClass(pWeakClass);*/
/* printf("\nTest Froever Class: \n");
ForeverClass* pForeverClass = new ForeverClass();
TestForeverClass(pForeverClass);
pForeverClass->printRefCount();
delete pForeverClass;*/
/* printf("Test Strong Class3: \n");
StrongClass* pStrongClass = new StrongClass();
TestStrongClass3(pStrongClass);*/
printf("Test Strong Class4: \n");
StrongClass* pStrongClass = new StrongClass();
TestStrongClass4(pStrongClass);
return 0;
}
四、运行结果
第一个:
Test Strong Class:
Construct StrongClass Object.
-----------------------
Strong Ref Count: 0.
Weak Ref Count: 1.
-----------------------
-----------------------
Strong Ref Count: 1.
Weak Ref Count: 2.
-----------------------
Destory StrongClass Object.
-----------------------
Strong Ref Count: 0.
Weak Ref Count: 1.
-----------------------
spOut: (nil).
-----------------------
Strong Ref Count: 0.
Weak Ref Count: 1.
-----------------------
~weakref_impl
第二个:
Test Strong Class2:
Construct StrongClass Object.
-----------------------
Strong Ref Count: 0.
Weak Ref Count: 1.
-----------------------
Destory StrongClass Object.
~weakref_impl
第三个:
Test Weak Class:
Construct WeakClass Object.
-----------------------
Strong Ref Count: 0.
Weak Ref Count: 1.
-----------------------
-----------------------
Strong Ref Count: 1.
Weak Ref Count: 2.
-----------------------
-----------------------
Strong Ref Count: 0.
Weak Ref Count: 1.
-----------------------
spOut: 0x1d60010.
-----------------------
Strong Ref Count: 1.
Weak Ref Count: 2.
-----------------------
Destory WeakClass Object.
~weakref_impl
第四个:
Test Froever Class:
Construct ForeverClass Object.
-----------------------
Strong Ref Count: 0.
Weak Ref Count: 1.
-----------------------
-----------------------
Strong Ref Count: 1.
Weak Ref Count: 2.
-----------------------
-----------------------
Strong Ref Count: 0.
Weak Ref Count: 1.
-----------------------
-----------------------
Strong Ref Count: 0.
Weak Ref Count: 0.
-----------------------
Destory ForeverClass Object.
~weakref_impl
第五个:
Test Strong Class3:
Construct StrongClass Object.
-----------------------
Strong Ref Count: 0.
Weak Ref Count: 1.
-----------------------
spOut: 0x646010.
-----------------------
Strong Ref Count: 1.
Weak Ref Count: 2.
-----------------------
Destory StrongClass Object.
~weakref_impl
第六个:
Test Strong Class4:
Construct StrongClass Object.
-----------------------
Strong Ref Count: 0.
Weak Ref Count: 1.
-----------------------
-----------------------
Strong Ref Count: 1.
Weak Ref Count: 2.
-----------------------
spOut: 0x154e010.
-----------------------
Strong Ref Count: 2.
Weak Ref Count: 3.
-----------------------
Destory StrongClass Object.
~weakref_impl