本文参考http://blog.csdn.net/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) { 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) { 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) { impl->mStrong = impl->mStrong - INITIAL_STRONG_VALUE; } return true; }
如果此时强指针不为0,或者初始值,那么说明RefBase及其子类还没有删除,所以可以提升为强指针
如果此时强指针为0,并且还受强指针控制,那么此时,RefBase及其子类已经被删除了,所以不能提升为强指针
如果此时强指针为0,并且还受弱指针控制,那么此时,RefBase及其子类还没有删除,能不能提升就看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