Android指針管理:RefBase SP WP_第1頁
Android指針管理:RefBase SP WP_第2頁
Android指針管理:RefBase SP WP_第3頁
Android指針管理:RefBase SP WP_第4頁
Android指針管理:RefBase SP WP_第5頁
已閱讀5頁,還剩15頁未讀 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領

文檔簡介

1、Android中通過引用計數(shù)來實現(xiàn)智能指針,并且實現(xiàn)有強指針與弱指針。由對象本身來提供引用計數(shù)器,但是對象不會去維護引用計數(shù)器的值,而是由智能指針來管理。要達到所有對象都可用引用計數(shù)器實現(xiàn)智能指針管理的目標,可以定義一個公共類,提供引用計數(shù)的方法,所有對象都去繼承這個公共類,這樣就可以實現(xiàn)所有對象都可以用引用計數(shù)來管理的目標,在Android中,這個公共類就是RefBase,同時還有一個簡單版本LightRefBase。RefBase作為公共基類提供了引用計數(shù)的方法,但是并不去維護引用計數(shù)的值,而是由兩個智能指針來進行管理:sp(Strong Pointer)和wp(Weak

2、0;Pointer),代表強引用計數(shù)和弱引用計數(shù)。 一、輕量級引用計數(shù)的實現(xiàn):LightRefBaseLightRefBase的實現(xiàn)很簡單,只是內(nèi)部保存了一個變量用于保存對象被引用的次數(shù),并提供了兩個函數(shù)用于增加或減少引用計數(shù)。template <class T>class LightRefBasepublic: inline LightRefBase() : mCount(0) inline void incStrong(const void* id) const android_atomic_inc(&mCount); inline void decStron

3、g(const void* id) const if (android_atomic_dec(&mCount) = 1) delete static_cast<const T*>(this); /! DEBUGGING ONLY: Get current strong ref count. inline int32_t getStrongCount() const return mCount; typedef LightRefBase<T> basetype;protected: inline LightRefBase() private: mutable vo

4、latile int32_t mCount;二、sp(Strong Pointer)LightRefBase僅僅提供了引用計數(shù)的方法,具體引用數(shù)應該怎么管理,就要通過智能指針類來管理了,每當有一個智能指針指向?qū)ο髸r,對象的引用計數(shù)要加1,當一個智能指針取消指向?qū)ο髸r,對象的引用計數(shù)要減1,在C中,當一個對象生成和銷毀時會自動調(diào)用(拷貝)構(gòu)造函數(shù)和析構(gòu)函數(shù),所以,對對象引用數(shù)的管理就可以放到智能指針的(拷貝)構(gòu)造函數(shù)和析構(gòu)函數(shù)中。Android提供了一個智能指針可以配合LightRefBase使用:sp,sp的定義如下:template <typename T>class

5、sppublic: inline sp() : m_ptr(0) sp(T* other); sp(const sp<T>& other); template<typename U> sp(U* other); template<typename U> sp(const sp<U>& other); sp(); / Assignment sp& operator = (T* other); sp& operator = (const sp<T>& other); template<type

6、name U> sp& operator = (const 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; inlin

7、e 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_pt

8、r;代碼比較多,其中Accessors部分代碼重載了*、->操作符使我們使用sp的時候就像使用真實的對象指針一樣,可以直接操作對象的屬性或方法,COMPARE是宏定義,用于重載關系操作符,由于對引用計數(shù)的控制主要是由(拷貝)構(gòu)造函數(shù)和析構(gòu)函數(shù)控制,所以忽略其他相關代碼后,sp可以精簡為如下形式(賦值操作符也省略掉了,構(gòu)造函數(shù)省略相似的兩個):template <typename T>class sppublic: inline sp() : m_ptr(0) sp(T* other); sp(const sp<T>& other); sp(); priva

9、te: template<typename Y> friend class sp; template<typename Y> friend class wp; void set_pointer(T* ptr); T* m_ptr;默認構(gòu)造函數(shù)使智能指針不指向任何對象,sp(T* other)與sp(const sp<T>& other)的實現(xiàn)如下:template<typename T>sp<T>:sp(T* other): m_ptr(other) if (other) other->in

10、cStrong(this); template<typename T>sp<T>:sp(const sp<T>& other): m_ptr(other.m_ptr) if (m_ptr) m_ptr->incStrong(this);內(nèi)部變量m_ptr指向?qū)嶋H對象,并調(diào)用實際對象的incStrong函數(shù),T繼承自LightRefBase,所以此處調(diào)用的是LightRefBase的incStrong函數(shù),之后實際對象的引用計數(shù)加1。當智能指針銷毀的時候調(diào)用智能指針的析構(gòu)函數(shù):template<typename T>sp<T&g

11、t;:sp() if (m_ptr) m_ptr->decStrong(this);調(diào)用實際對象即LightRefBase的decStrong函數(shù),其實現(xiàn)如下:inline void decStrong(const void* id) const if (android_atomic_dec(&mCount) = 1) delete static_cast<const T*>(this); android_atomic_dec返回mCount減1之前的值,如果返回1表示這次減過之后引用計數(shù)就是0了,就把對象delete掉。三、RefBaseRefBase提供了更強大的

12、引用計數(shù)的管理。class RefBasepublic: 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

13、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 voi

14、d* 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

15、 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

16、: 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(); /!

17、Flags for extendObjectLifetime() enum OBJECT_LIFETIME_STRONG = 0x0000, OBJECT_LIFETIME_WEAK = 0x0001, OBJECT_LIFETIME_MASK = 0x0003 ; void extendObjectLifetime(int32_t mode); /! Flags for onIncStrongAttempted() enum FIRST_INC_STRONG = 0x0001 ; virtual void onFirstRef(); virtual void onLastStrongRef(

18、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); weakref_impl* const mRefs;不同于LightRefBa

19、se的是,RefBase內(nèi)部并沒有使用一個變量來維護引用計數(shù),而是通過一個weakref_impl *類型的成員來維護引用計數(shù),并且同時提供了強引用計數(shù)和弱引用計數(shù)。weakref_impl繼承于RefBase:weakref_type,代碼比較多,不過大都是調(diào)試代碼,由宏定義分開,Release是不包含調(diào)試代碼的,去除這些代碼后其定義為:#define INITIAL_STRONG_VALUE (1<<28) class RefBase:weakref_impl : public RefBase:weakref_type public: volatile int32_t

20、 mStrong; volatile int32_t mWeak; RefBase* const mBase; volatile int32_t mFlags; 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 addWeakRef(const void* /*id*/) void re

21、moveWeakRef(const void* /*id*/) void printRefs() const void trackMe(bool, bool) ;weakref_impl中的函數(shù)都是作為調(diào)試用,Release版的實現(xiàn)都是空的,成員變量分別表示強引用數(shù)、弱引用數(shù)、指向?qū)嶋H對象的指針與flag,flag可控制實際對象的生命周期,取值為0或RefBase中定義的枚舉值。RefBase提供了incStrong與decStrong函數(shù)用于控制強引用計數(shù)值,其弱引用計數(shù)值是由weakref_impl控制,強引用計數(shù)與弱引用數(shù)都保存在weakref_impl *類型的成員變量mRe

22、fs中。RefBase同LightRefBase一樣為對象提供了引用計數(shù)的方法,對引用計數(shù)的管理同樣要由智能指針控制,由于RefBase同時實現(xiàn)了強引用計數(shù)與弱引用計數(shù),所以就有兩種類型的智能指針,sp(Strong Pointer)與wp(Weak Pointer)。sp前面已經(jīng)說過,其(拷貝)構(gòu)造函數(shù)調(diào)用對象即RefBase的incStrong函數(shù)。void RefBase:incStrong(const void* id) const weakref_impl* const refs = mRefs; refs->incWeak(id); refs->ad

23、dStrongRef(id); const int32_t c = android_atomic_inc(&refs->mStrong); LOG_ASSERT(c > 0, "incStrong() called on %p after last strong ref", refs); if (c != INITIAL_STRONG_VALUE) return; android_atomic_add(-INITIAL_STRONG_VALUE, &refs->mStrong); refs->mBase->onFirstRef(

24、);addStrong的函數(shù)體為空,incStrong函數(shù)內(nèi)部首先調(diào)用成員變量mRefs的incWeak函數(shù)將弱引用數(shù)加1,然后再將強引用數(shù)加1,由于android_atomic_inc返回變量的舊值,所以如果其不等于INITIAL_STRONG_VALUE就直接返回,則則是第一次由強智能指針(sp)引用,將其減去INITIAL_STRONG_VALUE后變成1,然后調(diào)用對象的onFirstRef。成員變量mRefs是在對象的構(gòu)造函數(shù)中初始化的:RefBase:RefBase() : mRefs(new weakref_impl(this)weakrel_impl的incWeak繼承自父類we

25、akrel_type的incWeak:void RefBase:weakref_type:incWeak(const void* id) weakref_impl* const impl = static_cast<weakref_impl*> impl->addWeakRef(id); const int32_t c = android_atomic_inc(&impl->mWeak); LOG_ASSERT(c >= 0, "incWeak called on %p after last weak ref", this);addWe

26、akRef實現(xiàn)同樣為空,所以只是將弱引用計數(shù)加1。所以當對象被sp引用后,強引用計數(shù)與弱引用計數(shù)會同時加1。當sp銷毀時其析構(gòu)函數(shù)調(diào)用對象即RefBase的decStrong函數(shù):void RefBase:decStrong(const void* id) const weakref_impl* const refs = mRefs; refs->removeStrongRef(id); const int32_t c = android_atomic_dec(&refs->mStrong); if (c = 1) const_cast<RefBase*>(th

27、is)->onLastStrongRef(id); if (refs->mFlags&OBJECT_LIFETIME_WEAK) != OBJECT_LIFETIME_WEAK) delete this; refs->removeWeakRef(id); refs->decWeak(id); decStrong中將強引用數(shù)與弱引用數(shù)同時減1,如果這是最后一個強引用的話,會調(diào)用對象的onLastStrongRef,并且判斷成員變量mRefs的成員變量mFlags來決定是否在對象的強引用數(shù)為0時釋放對象。mFlags可以為0或以下兩個枚舉值:enum OBJECT_

28、LIFETIME_WEAK = 0x0001, OBJECT_LIFETIME_FOREVER = 0x0003;mFlags的值可以通過extendObjectLifetime函數(shù)改變:void RefBase:extendObjectLifetime(int32_t mode) android_atomic_or(mode, &mRefs->mFlags);OBJECT_LIFETIME_FOREVER包含OBJECT_LIFETIME_WEAK(位運算中其二進制11包含01),所以當refs->mFlags&OBJECT_LIFETIME_WEAK) != O

29、BJECT_LIFETIME_WEAK為true時表示mFlags為0,實際對象的生命周期受強引用數(shù)控制,所以在強引用數(shù)為0時delete this,否則實際對象的生命周期就由弱引用數(shù)控制。再來看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 = android_atomic_dec(&im

30、pl->mWeak); if (c != 1) return; if (impl->mFlags&OBJECT_LIFETIME_WEAK) != OBJECT_LIFETIME_WEAK) if (impl->mStrong = INITIAL_STRONG_VALUE) delete impl->mBase; else delete impl; else impl->mBase->onLastWeakRef(id); if (impl->mFlags&OBJECT_LIFETIME_FOREVER) != OBJECT_LIFETI

31、ME_FOREVER) delete impl->mBase; 將弱引用數(shù)減1,若減1后不為0直接返回,否則判斷(impl->mFlags&OBJECT_LIFETIME_WEAK) != OBJECT_LIFETIME_WEAK若判斷結(jié)果為true:    實際對象生命周期被強引用數(shù)控制,接下來判斷:mpl->mStrong = INITIAL_STRONG_VALUE1. 如果判斷為true表示對象只被弱引用引用過,現(xiàn)在弱引用數(shù)為0,直接刪除實際對象。2. 如果判斷為false,表示對象曾經(jīng)被強引用引用過,但現(xiàn)在強引用為變?yōu)?了(因為增加或減小

32、強引用數(shù)時一定同時增加或減小弱引用數(shù),所以弱引用數(shù)為0時,強引用數(shù)一定為0),弱引用數(shù)為0了,直接釋放mRefs,而實際對象由于受強引用數(shù)控制,已經(jīng)在RefBase:decStrong中被delete了。若判斷結(jié)果為false:    判斷mFlgs是否是OBJECT_LIFETIME_FOREVER,如果是,什么都不作由用戶自己控制對象的生命周期,否則,實際對象的生命周期受弱引用數(shù)控制,現(xiàn)在弱引用數(shù)為0,delete實際對象。四、wp(Weak Pointer)定義如下:template <typename T>class wppublic: typ

33、edef typename RefBase:weakref_type weakref_type; inline wp() : m_ptr(0) wp(T* other); wp(const wp<T>& other); wp(const sp<T>& other); template<typename U> wp(U* other); template<typename U> wp(const sp<U>& other); template<typename U> wp(const wp<U&

34、gt;& other); 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>& oth

35、er); 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() cons

36、t return m_ptr; / Operators COMPARE(=) COMPARE(!=) COMPARE(>) COMPARE(<) COMPARE(<=) COMPARE(>=) private: template<typename Y> friend class sp; template<typename Y> friend class wp; T* m_ptr; weakref_type* m_refs;同sp一樣,m_ptr指向?qū)嶋H對象,但wp還有一個成員變量m_refs。template<typename T>w

37、p<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); RefBase:weakref_type* RefBase:createWeak(const void* id) const

38、 mRefs->incWeak(id); return mRefs;可以看到,wp的m_refs就是RefBase即實際對象的mRefs。wp析構(gòu)的時候減少弱引用計數(shù):template<typename T>wp<T>:wp() if (m_ptr) m_refs->decWeak(this);由于弱指針沒有重載*與->操作符,所以不能直接操作指向的對象,雖然有unsafe_get函數(shù),但像名字所示的,不建議使用,直接使用實際對象指針的話就沒必要用智能指針了。因為弱指針不能直接操作對象,所以要想操作對象的話就要將其轉(zhuǎn)換為強指針,即wp:promote方

39、法:template<typename T>sp<T> wp<T>:promote() const return sp<T>(m_ptr, m_refs); template<typename T>sp<T>:sp(T* p, weakref_type* refs) : m_ptr(p && refs->attemptIncStrong(this) ? p : 0)是否能從弱指針生成一個強指針關鍵是看refs->attemptIncStrong,看其定義:bool RefBase:weakref

40、_type:attemptIncStrong(const void* id) incWeak(id); weakref_impl* const impl = static_cast<weakref_impl*>(this); int32_t curCount = impl->mStrong; LOG_ASSERT(curCount >= 0, "attemptIncStrong called on %p after underflow", this); while (curCount > 0 && curCount != INI

41、TIAL_STRONG_VALUE) if (android_atomic_cmpxchg(curCount, curCount+1, &impl->mStrong) = 0) break; curCount = impl->mStrong; if (curCount <= 0 | curCount = INITIAL_STRONG_VALUE) bool allow; if (curCount = INITIAL_STRONG_VALUE) / Attempting to acquire first strong reference. this is allowed

42、 / if the object does NOT have a longer lifetime (meaning the / implementation doesn't need to see this), or if the implementation / allows it to happen. allow = (impl->mFlags&OBJECT_LIFETIME_WEAK) != OBJECT_LIFETIME_WEAK | impl->mBase->onIncStrongAttempted(FIRST_INC_STRONG, id); el

43、se / Attempting to revive the object. this is allowed / if the object DOES have a longer lifetime (so we can safely / call the object with only a weak ref) and the implementation / allows it to happen. allow = (impl->mFlags&OBJECT_LIFETIME_WEAK) = OBJECT_LIFETIME_WEAK && impl->mBas

44、e->onIncStrongAttempted(FIRST_INC_STRONG, id); if (!allow) decWeak(id); return false; curCount = android_atomic_inc(&impl->mStrong); / If the strong reference count has already been incremented by / someone else, the implementor of onIncStrongAttempted() is holding / an unneeded reference.

45、 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->addWeakRef(id); impl->addS

46、trongRef(id); #if PRINT_REFS LOGD("attemptIncStrong of %p from %p: cnt=%dn", this, id, curCount);#endif if (curCount = INITIAL_STRONG_VALUE) android_atomic_add(-INITIAL_STRONG_VALUE, &impl->mStrong); impl->mBase->onFirstRef(); return true;首先通過incWeak將弱引用數(shù)加1(被強指針sp引用會導致強引用數(shù)和弱引用

47、數(shù)同時加1),然后:int32_t curCount = impl->mStrong;while (curCount > 0 && curCount != INITIAL_STRONG_VALUE) if (android_atomic_cmpxchg(curCount, curCount+1, &impl->mStrong) = 0) break; curCount = impl->mStrong;如果之前已經(jīng)有強引用,直接將強引用數(shù)加1,android_atomic_cmpxchg表示如果impl->mStrong的值為curCount

48、,則把impl->mString的值改為curCount+1,此處用while循環(huán)是防止其他線程已經(jīng)增加了強引用數(shù)。接下來:if (curCount <= 0 | curCount = INITIAL_STRONG_VALUE)表示對象目前沒有強引用,這就要判斷對象是否存在了。如果curCount = INITIAL_STRONG_VALUE,表示對象沒有被sp引用過。接下來判斷:allow = (impl->mFlags&OBJECT_LIFETIME_WEAK) != OBJECT_LIFETIME_WEAK | impl->mBase->onIncStrongAttempted(FIRST_INC_STRONG, id); 表示:如果對象的生命周期只受強引用控制,對象一定存在,要

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論