下面是android 7.1.1中的源碼
先從簡單的LightRefBase開始, 它里面只用了簡單的mCount來計數(shù).
## LightRefBase
template <class T>
class LightRefBase
{
public:
inline LightRefBase() : mCount(0) { }
//計數(shù)+1
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 {
//計數(shù)-1, 返回減1之前的值
if (mCount.fetch_sub(1, std::memory_order_release) == 1) {
std::atomic_thread_fence(std::memory_order_acquire);
delete static_cast<const T*>(this); //如果減掉后引用計數(shù)為0, 刪掉該引用
}
}
inline int32_t getStrongCount() const {
return mCount.load(std::memory_order_relaxed);
}
private:
mutable std::atomic<int32_t> mCount;
};
int main(int argc, char** argv)
{
//自定義LightClass 繼承LightRefBase
LightClass* pLightClass = new LightClass();
//調(diào)用① sp的一個參數(shù)的構(gòu)造函數(shù)
sp<LightClass> lpOut = pLightClass;
//pLightClass 引用計數(shù)+1, 所以下面輸出 1
printf("Light Ref Count: %d.\n", pLightClass->getStrongCount());
{
//調(diào)用② sp的另一個構(gòu)造函數(shù)
sp<LightClass> lpInner = lpOut;
//上面pLight的引用計數(shù)+1, 所以這里輸出2
printf("Light Ref Count: %d.\n", pLightClass->getStrongCount());
}
//上面作用域結(jié)束所以, lpInner調(diào)用析構(gòu)函數(shù)③
//pLightClass引用計數(shù)-1, 這里輸出 1
printf("Light Ref Count: %d.\n", pLightClass->getStrongCount());
return 0;
}
//StrongPointer.h
//①
template<typename T>
sp<T>::sp(T* other) //other在上面的例子為pLightClass
: m_ptr(other) {
if (other)
//調(diào)用LightRefBase的incStrong, LightRefBase的mCount+1;
other->incStrong(this);
}
//②
template<typename T>
sp<T>::sp(const sp<T>& other) //other參數(shù)在上面的例子中為lpOut
: m_ptr(other.m_ptr) { //other.m_ptr為 pLightClass, m_ptr其實就是pLightClass的引用
if (m_ptr)
m_ptr->incStrong(this); //引用計數(shù)+1
}
//③
template<typename T>
sp<T>::~sp() {
if (m_ptr) //m_ptr為pLightClass的引用
m_ptr->decStrong(this);
}
## RefBase
# RefBase原型
//RefBase.h
class RefBase
{
private:
//weakref_impl為RefBase的內(nèi)部類weakref_type的實現(xiàn)類,
//mRefs包含強引用計數(shù), 弱引用計數(shù), flag, 以及指向外部類RefBase的指針mBase
weakref_impl* const mRefs;
protected:
RefBase(); //構(gòu)造函數(shù)中 new weakref_impl()
virtual ~RefBase(); //析構(gòu)做了較多工作
//! Flags for extendObjectLifetime()
enum { //沒有了forever
OBJECT_LIFETIME_STRONG = 0x0000, //對象受強引用控制, 默認
OBJECT_LIFETIME_WEAK = 0x0001, //對象受弱引用控制
OBJECT_LIFETIME_MASK = 0x0001
};
public:
void incStrong(const void* id) const;
void decStrong(const void* id) const;
weakref_type* createWeak(const void* id) const;
//...省略
}
上面是RefBase中的幾個重要函數(shù)聲明, 接下來是weakref_impl的聲明
# weakref_type, weakref_impl原型
//RefBase.h
class weakref_type
{
public:
void incWeak(const void* id);
void decWeak(const void* id);
bool attemptIncStrong(const void* id);
//..省略
}
//RefBase.cpp
class RefBase::weakref_impl : public RefBase::weakref_type //weakref_type定義了幾個函數(shù)
{
public:
std::atomic<int32_t> mStrong; //強引用計數(shù)
std::atomic<int32_t> mWeak; //弱引用計數(shù)
RefBase* const mBase; //引用外部指針
std::atomic<int32_t> mFlags; //標(biāo)記
//..省略空方法
}
后面都是控制weakref_impl對象, 這里只要記住有四個變量, 和加減引用計數(shù)的方法, 接下來先看下它們的實現(xiàn)
# weakref_type, weakref_impl實現(xiàn)
//RefBase.cpp
weakref_impl(RefBase* base)
: mStrong(INITIAL_STRONG_VALUE) //強引用計數(shù)默認值
, mWeak(0) //弱引用計數(shù)0
, mBase(base) //引用外部對象 RefBase
, mFlags(0){} //flag默認0, 表示受強引用控制
void RefBase::weakref_type::incWeak(const void* id)
{
weakref_impl* const impl = static_cast<weakref_impl*>(this);
impl->addWeakRef(id); //空方法
const int32_t c __unused = impl->mWeak.fetch_add(1, //弱引用計數(shù)+1
std::memory_order_relaxed);
}
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); //弱引用-1
if (c != 1) return; //減1后弱引用計數(shù)不為0, 直接返回
//弱引用計數(shù)為0, 接著往下執(zhí)行
//弱引用計數(shù)>=強引用計數(shù)
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) {
// 受強引用計數(shù)影響, 默認
if (impl->mStrong.load(std::memory_order_relaxed)
== INITIAL_STRONG_VALUE) {
//如果強引用計數(shù)為初始值, 回收RefBase
delete impl->mBase;
} else {
//強引用計數(shù)為0, 回收weakref_impl
delete impl;
}
} else {
// 受弱引用計數(shù)控制, 回收RefBase
impl->mBase->onLastWeakRef(id);
delete impl->mBase;
}
}
bool RefBase::weakref_type::attemptIncStrong(const void* id)
{
//該方法是, 弱引用變?yōu)閺娨? 所以強引用計數(shù)+1, 弱引用計數(shù)也需要+1
//這里弱引用計數(shù)先+1, 如果變?yōu)閺娨檬? 則再-1
incWeak(id);
weakref_impl* const impl = static_cast<weakref_impl*>(this);
int32_t curCount = impl->mStrong.load(std::memory_order_relaxed);
//下面判斷成立, 說明已經(jīng)有強引用, 說明可以, 升級為強引用
//while為了解決多線程的問題
while (curCount > 0 && curCount != INITIAL_STRONG_VALUE) {
if (impl->mStrong.compare_exchange_weak(curCount, curCount+1,
std::memory_order_relaxed)) {
break;
}
}
if (curCount <= 0 || curCount == INITIAL_STRONG_VALUE) {
// 兩種情況
// - 沒有過強引用
// - 或者強引用都被回收了
int32_t flags = impl->mFlags.load(std::memory_order_relaxed);
if ((flags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_STRONG) {
// 默認受強引用控制時
// 當(dāng)最后的強引用被釋放了, 所以curCount<=0
if (curCount <= 0) {
// 強引用<=0 肯定是從1減到了0, 根據(jù)decStrong()方法, 受強引用控制時, 釋放RefBase
// 所以不能升級為強引用
decWeak(id); //弱引用計數(shù)-1, 因為上面加過1
return false;
}
//curCount為初始值, 說明沒有過強引用, 可以嘗試一下
while (curCount > 0) {
//mStrong + 1
if (impl->mStrong.compare_exchange_weak(curCount, curCount+1,
std::memory_order_relaxed)) {
break;
}
}
if (curCount <= 0) {
// 其他線程破壞了這次的升級, promote()失敗
decWeak(id);
return false;
}
} else {
// 受弱引用控制
// onIncStrongAttempted()默認為true, 但是可以重寫該方法
// 能否promote()成功取決于開發(fā)者.
if (!impl->mBase->onIncStrongAttempted(FIRST_INC_STRONG, id)) {
decWeak(id);
return false;
}
// 可以升級為強引用, 強引用計數(shù)+1
curCount = impl->mStrong.fetch_add(1, std::memory_order_relaxed);
// 多線程問題, 別的線程動了強引用計數(shù)
if (curCount != 0 && curCount != INITIAL_STRONG_VALUE) {
impl->mBase->onLastStrongRef(id);
}
}
}
impl->addStrongRef(id);// 空方法
// 修正強引用計數(shù)為1
if (curCount == INITIAL_STRONG_VALUE) {
impl->mStrong.fetch_sub(INITIAL_STRONG_VALUE,
std::memory_order_relaxed);
}
return true;
}
# RefBase實現(xiàn)
//RefBase.cpp
RefBase::RefBase() //無參構(gòu)造函數(shù)
: mRefs(new weakref_impl(this)){}
RefBase::~RefBase() //析構(gòu)函數(shù)
{
if (mRefs->mStrong.load(std::memory_order_relaxed)
== INITIAL_STRONG_VALUE) {
//沒有用過強引用, 刪除weakref_impl
delete mRefs;
} else {
int32_t flags = mRefs->mFlags.load(std::memory_order_relaxed);
if ((flags & OBJECT_LIFETIME_MASK) != OBJECT_LIFETIME_STRONG) {
if (mRefs->mWeak.load(std::memory_order_relaxed) == 0) {
//受弱引用控制, 并且若引用計數(shù) = 0, 刪除weakref_impl
delete mRefs;
}
}
}
// for debugging purposes, clear this.
const_cast<weakref_impl*&>(mRefs) = NULL;
}
//wp中需要調(diào)用
RefBase::weakref_type* RefBase::createWeak(const void* id) const
{
mRefs->incWeak(id);
return mRefs;
}
//incStrong
void RefBase::incStrong(const void* id) const
{
weakref_impl* const refs = mRefs;
refs->incWeak(id); //弱引用計數(shù)+1
refs->addStrongRef(id); //空方法
//強引用+1
const int32_t c = refs->mStrong.fetch_add(1, std::memory_order_relaxed);
if (c != INITIAL_STRONG_VALUE) {
return;
}
//強引用默認值為1<<28, 減去1<<28, 現(xiàn)在值為1
int32_t old = refs->mStrong.fetch_sub(INITIAL_STRONG_VALUE,
std::memory_order_relaxed);
refs->mBase->onFirstRef();
}
void RefBase::decStrong(const void* id) const
{
weakref_impl* const refs = mRefs;
refs->removeStrongRef(id);//空方法
//強引用-1
const int32_t c = refs->mStrong.fetch_sub(1, std::memory_order_release);
if (c == 1) { //減去后強引用計數(shù) = 0
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) {
//受強引用計數(shù)控制, 默認, 刪掉RefBase, 并且調(diào)用RefBase的析構(gòu)函數(shù)
delete this;
}
}
refs->decWeak(id);
}
-
RefBase::RefBase()
new weakref_impl(), weakref_impl初始化
-
RefBase::~RefBase()
強引用計數(shù)為初始值 || (受弱引用控制&&弱引用計數(shù)==0) -> 刪掉weakref_impl
-
RefBase::incStrong()
調(diào)用 weakref_type::incWeak (弱引用+1)
強引用+1(如果第一次加1, 那么減掉初始值, 最終為1),
-
RefBase::decStrong()
強引用-1, 減去后如果強引用計數(shù)為0, 并且受強引用控制, 釋放RefBase(實際對象)
調(diào)用 weakref_type::decWeak (弱引用-1, 還有其他邏輯)
-
RefBase::weakref_type::incWeak()
強引用+1
-
RefBase::weakref_type::decWeak()
弱引用-1, 減去后如果弱引用計數(shù)為0, 分兩種情況, 受強引用控制, 受弱引用控制
其實弱引用計數(shù)為0, 不管受強引用還是弱引用控制, RefBase和weakref_impl都需要釋放, 下面的判斷是為了不重復(fù)釋放
-
受強引用控制, 強引用計數(shù)為初始值, 釋放RefBase, 不為初始值, 釋放weakref_impl
強引用計數(shù)為初始值, 釋放RefBase, RefBase調(diào)用析構(gòu)函數(shù), 釋放weakref_impl
強引用計數(shù)不為初始值說明, 調(diào)用過decStrong(), 并且受強引用控制, 所以會釋放RefBase, 這里只需再釋放weakref_impl就可以了
-
受弱引用控制, 釋放RefBase
受弱引用控制, 釋放RefBase, RefBase調(diào)用析構(gòu)函數(shù), 釋放weakref_impl
-
-
RefBase::weakref_type::attemptIncStrong()
不考慮多線程的情況下, 首先如果已經(jīng)有強引用, 那么可以直接升級強引用.
當(dāng)強引用<=0, 或者沒有初始化過強引用時分兩種情況, 受強引用或者弱引用控制
-
受強引用控制
強引用<=0, 說明RefBase已經(jīng)被釋放了, 升級失敗
強引用為默認值, 說明沒有過強引用, 可以升級
-
受弱引用控制
首先判斷開發(fā)者是否希望可以升級, 默認為true, 升級OK
-
RefBase的重要函數(shù)都說明完了, 接下來是strong pointer和 weak pointer, 如果上面的RefBase弄明白了, sp和wp就很簡單, 只要關(guān)注它們的構(gòu)造函數(shù)和析構(gòu)函數(shù), 加上wp的promote()函數(shù)即可.
## sp和wp
# sp實現(xiàn)
//StrongPointer.h
template<typename T>
class sp {
public:
inline sp() : m_ptr(0) { }
//構(gòu)造方法很多, 其他也都一樣調(diào)用RefBase的incStrong()函數(shù)
template<typename T>
sp<T>::sp(const sp<T>& other)
: m_ptr(other.m_ptr) {
if (m_ptr)
m_ptr->incStrong(this);
}
//析構(gòu)函數(shù)
template<typename T>
sp<T>::~sp() {
if (m_ptr)
m_ptr->decStrong(this);
}
// 特殊! 用于ProcessState, 不關(guān)注
void force_set(T* other);
// 操作符重載 sp可以自由使用引用對象
inline T& operator* () const { return *m_ptr; }
inline T* operator-> () const { return m_ptr; }
inline T* get() const { return m_ptr; }
// 也是為了 sp自由使用引用對象, 宏定義就不貼了
COMPARE(==)
COMPARE(!=)
COMPARE(>)
COMPARE(<)
COMPARE(<=)
COMPARE(>=)
private:
template<typename Y> friend class sp;
template<typename Y> friend class wp;
void set_pointer(T* ptr) { m_ptr = ptr; }
T* m_ptr; //引用對象
};
這里只需明白3點:
- 構(gòu)造函數(shù)調(diào)用 incStrong(), 強引用+1, 弱引用+1
- 析構(gòu)函數(shù)調(diào)用 decStrong(), 強引用-1, 弱引用-1 (還有其他一些邏輯)
- sp可以自由操作引用對象
# wp實現(xiàn)
//RefBase.h
template <typename T>
class wp
{
public:
template<typename T> //構(gòu)造函數(shù)
wp<T>::wp(T* other): m_ptr(other)
{
//createWeak()方法很簡單, 上面有實現(xiàn), 只是調(diào)用下incWeak, 返回weakref_impl對象
if (other) m_refs = other->createWeak(this);
}
template<typename T> //析構(gòu)函數(shù)
wp<T>::~wp()
{
if (m_ptr) m_refs->decWeak(this);
}
template<typename T>
sp<T> wp<T>::promote() const //重點方法, wp升級sp
{
sp<T> result;
if (m_ptr && m_refs->attemptIncStrong(&result)) {
result.set_pointer(m_ptr);
}
return result; //如果升級失敗, 引用對象為空
}
private:
template<typename Y> friend class sp;
template<typename Y> friend class wp;
T* m_ptr; //引用對象
weakref_type* m_refs; //RefBase中的weakref_impl, 因為要調(diào)用weakref_impl的方法
};
wp的要明白4點:
- 構(gòu)造函數(shù)調(diào)用 createWeak(), 弱引用+1
- 析構(gòu)函數(shù)調(diào)用 decWeak() 弱引用-1 (還有其他一些邏輯)
- wp不可以自由操作引用對象
- wp的promote()方法, 可以升級為sp, 但是如果升級失敗sp的引用對象為空, 所以需要做判斷
OK, 智能指針的基本方法都已經(jīng)講清楚, 這里用老羅的例子實踐一下.
class WeightClass : public RefBase
{
public:
void printRefCount()
{
int32_t strong = getStrongCount();
weakref_type* ref = getWeakRefs();
printf("-----------------------\n");
printf("Strong Ref Count: %d.\n", strong); //打印強引用計數(shù)
printf("Weak Ref Count: %d.\n", ref->getWeakCount()); //打印弱引用計數(shù)
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");
}
};
void TestStrongClass(StrongClass* pStrongClass)
{
wp<StrongClass> wpOut = pStrongClass; //弱引用計數(shù) +1
pStrongClass->printRefCount();
{
sp<StrongClass> spInner = pStrongClass; //強引用計數(shù)+1, 弱引用計數(shù)+1
pStrongClass->printRefCount();
}//調(diào)用sp的析構(gòu)函數(shù), 強引用 = 0, 弱引用 = 1, 因受強引用控制, 所以對象被刪除
sp<StrongClass> spOut = wpOut.promote(); //升級失敗
printf("spOut: %p.\n", spOut.get());
}
void TestWeakClass(WeakClass* pWeakClass)
{
wp<WeakClass> wpOut = pWeakClass; //弱引用計數(shù) +1
pWeakClass->printRefCount();
{
sp<WeakClass> spInner = pWeakClass; //強引用計數(shù)+1, 弱引用計數(shù)+1
pWeakClass->printRefCount();
}//調(diào)用sp的析構(gòu)函數(shù), 強引用 = 0, 弱引用 = 1, 因受弱引用控制, 所以對象不會被刪除
pWeakClass->printRefCount();
sp<WeakClass> spOut = wpOut.promote(); //升級成功
printf("spOut: %p.\n", spOut.get());
}
int main(int argc, const char * argv[]) {
printf("Test Strong Class: \n");
StrongClass* pStrongClass = new StrongClass();
TestStrongClass(pStrongClass);
printf("\nTest Weak Class: \n");
WeakClass* pWeakClass = new WeakClass();
TestWeakClass(pWeakClass);
return 0;
}
//輸出:
/*
Test Strong Class:
Construct StrongClass Object.
-----------------------
Strong Ref Count: 268435456.
Weak Ref Count: 1.
-----------------------
-----------------------
Strong Ref Count: 1.
Weak Ref Count: 2.
-----------------------
Destory StrongClass Object.
spOut: 0x0.
Test Weak Class:
Construct WeakClass Object.
-----------------------
Strong Ref Count: 268435456.
Weak Ref Count: 1.
-----------------------
-----------------------
Strong Ref Count: 1.
Weak Ref Count: 2.
-----------------------
-----------------------
Strong Ref Count: 0.
Weak Ref Count: 1.
-----------------------
spOut: 0x100300060.
Destory WeakClass Object.
*/