posts - 101,  comments - 29,  trackbacks - 0

                  Android系統(tǒng)的運(yùn)行時(shí)庫(kù)層代碼是用C++來(lái)編寫(xiě)的,用C++來(lái)寫(xiě)代碼最容易出錯(cuò)的地方就是指針了,一旦使用不當(dāng),輕則造成內(nèi)存泄漏,重則造成系統(tǒng)崩潰。不過(guò)系統(tǒng)為我們提供了智能指針,避免出現(xiàn)上述問(wèn)題,本文將系統(tǒng)地分析Android系統(tǒng)智能指針(輕量級(jí)指針、強(qiáng)指針和弱指針)的實(shí)現(xiàn)原理。

                  在使用C++來(lái)編寫(xiě)代碼的過(guò)程中,指針使用不當(dāng)造成內(nèi)存泄漏一般就是因?yàn)閚ew了一個(gè)對(duì)象并且使用完之后,忘記了delete這個(gè)對(duì)象,而造成系統(tǒng)崩潰一般就是因?yàn)橐粋€(gè)地方delete了這個(gè)對(duì)象之后,其它地方還在繼續(xù)使原來(lái)指向這個(gè)對(duì)象的指針。為了避免出現(xiàn)上述問(wèn)題,一般的做法就是使用引用計(jì)數(shù)的方法,每當(dāng)有一個(gè)指針指向了一個(gè)new出來(lái)的對(duì)象時(shí),就對(duì)這個(gè)對(duì)象的引用計(jì)數(shù)增加1,每當(dāng)有一個(gè)指針不再使用這個(gè)對(duì)象時(shí),就對(duì)這個(gè)對(duì)象的引用計(jì)數(shù)減少1,每次減1之后,如果發(fā)現(xiàn)引用計(jì)數(shù)值為0時(shí),那么,就要delete這個(gè)對(duì)象了,這樣就避免了忘記delete對(duì)象或者這個(gè)對(duì)象被delete之后其它地方還在使用的問(wèn)題了。但是,如何實(shí)現(xiàn)這個(gè)對(duì)象的引用計(jì)數(shù)呢?肯定不是由開(kāi)發(fā)人員來(lái)手動(dòng)地維護(hù)了,要開(kāi)發(fā)人員時(shí)刻記住什么時(shí)候該對(duì)這個(gè)對(duì)象的引用計(jì)數(shù)加1,什么時(shí)候該對(duì)這個(gè)對(duì)象的引用計(jì)數(shù)減1,一來(lái)是不方便開(kāi)發(fā),二來(lái)是不可靠,一不小心哪里多加了一個(gè)1或者多減了一個(gè)1,就會(huì)造成災(zāi)難性的后果。這時(shí)候,智能指針就粉墨登場(chǎng)了。首先,智能指針是一個(gè)對(duì)象,不過(guò)這個(gè)對(duì)象代表的是另外一個(gè)真實(shí)使用的對(duì)象,當(dāng)智能指針指向?qū)嶋H對(duì)象的時(shí)候,就是智能指針對(duì)象創(chuàng)建的時(shí)候,當(dāng)智能指針不再指向?qū)嶋H對(duì)象的時(shí)候,就是智能指針對(duì)象銷(xiāo)毀的時(shí)候,我們知道,在C++中,對(duì)象的創(chuàng)建和銷(xiāo)毀時(shí)會(huì)分別自動(dòng)地調(diào)用對(duì)象的構(gòu)造函數(shù)和析構(gòu)函數(shù),這樣,負(fù)責(zé)對(duì)真實(shí)對(duì)象的引用計(jì)數(shù)加1和減1的工作就落實(shí)到智能指針對(duì)象的構(gòu)造函數(shù)和析構(gòu)函數(shù)的身上了,這也是為什么稱(chēng)這個(gè)指針對(duì)象為智能指針的原因。

                  在計(jì)算機(jī)科學(xué)領(lǐng)域中,提供垃圾收集(Garbage Collection)功能的系統(tǒng)框架,即提供對(duì)象托管功能的系統(tǒng)框架,例如Java應(yīng)用程序框架,也是采用上述的引用計(jì)數(shù)技術(shù)方案來(lái)實(shí)現(xiàn)的,然而,簡(jiǎn)單的引用計(jì)數(shù)技術(shù)不能處理系統(tǒng)中對(duì)象間循環(huán)引用的情況。考慮這樣的一個(gè)場(chǎng)景,系統(tǒng)中有兩個(gè)對(duì)象A和B,在對(duì)象A的內(nèi)部引用了對(duì)象B,而在對(duì)象B的內(nèi)部也引用了對(duì)象A。當(dāng)兩個(gè)對(duì)象A和B都不再使用時(shí),垃圾收集系統(tǒng)會(huì)發(fā)現(xiàn)無(wú)法回收這兩個(gè)對(duì)象的所占據(jù)的內(nèi)存的,因?yàn)橄到y(tǒng)一次只能收集一個(gè)對(duì)象,而無(wú)論系統(tǒng)決定要收回對(duì)象A還是要收回對(duì)象B時(shí),都會(huì)發(fā)現(xiàn)這個(gè)對(duì)象被其它的對(duì)象所引用,因而就都回收不了,這樣就造成了內(nèi)存泄漏。這樣,就要采取另外的一種引用計(jì)數(shù)技術(shù)了,即對(duì)象的引用計(jì)數(shù)同時(shí)存在強(qiáng)引用和弱引用兩種計(jì)數(shù),例如,Apple公司提出的Cocoa框架,當(dāng)父對(duì)象要引用子對(duì)象時(shí),就對(duì)子對(duì)象使用強(qiáng)引用計(jì)數(shù)技術(shù),而當(dāng)子對(duì)象要引用父對(duì)象時(shí),就對(duì)父對(duì)象使用弱引用計(jì)數(shù)技術(shù),而當(dāng)垃圾收集系統(tǒng)執(zhí)行對(duì)象回收工作時(shí),只要發(fā)現(xiàn)對(duì)象的強(qiáng)引用計(jì)數(shù)為0,而不管它的弱引用計(jì)數(shù)是否為0,都可以回收這個(gè)對(duì)象,但是,如果我們只對(duì)一個(gè)對(duì)象持有弱引用計(jì)數(shù),當(dāng)我們要使用這個(gè)對(duì)象時(shí),就不直接使用了,必須要把這個(gè)弱引用升級(jí)成為強(qiáng)引用時(shí),才能使用這個(gè)對(duì)象,在轉(zhuǎn)換的過(guò)程中,如果對(duì)象已經(jīng)不存在,那么轉(zhuǎn)換就失敗了,這時(shí)候就說(shuō)明這個(gè)對(duì)象已經(jīng)被銷(xiāo)毀了,不能再使用了。

                 了解了這些背景知識(shí)后,我們就可以進(jìn)一步學(xué)習(xí)Android系統(tǒng)的智能指針的實(shí)現(xiàn)原理了。Android系統(tǒng)提供了強(qiáng)大的智能指針技術(shù)供我們使用,這些智能指針實(shí)現(xiàn)方案既包括簡(jiǎn)單的引用計(jì)數(shù)技術(shù),也包括了復(fù)雜的引用計(jì)數(shù)技術(shù),即對(duì)象既有強(qiáng)引用計(jì)數(shù),也有弱引用計(jì)數(shù),對(duì)應(yīng)地,這三種智能指針?lè)謩e就稱(chēng)為輕量級(jí)指針(Light Pointer)、強(qiáng)指針(Strong Pointer)和弱指針(Weak Pointer)。無(wú)論是輕量級(jí)指針,還是強(qiáng)指針和弱指針,它們的實(shí)現(xiàn)框架都是一致的,即由對(duì)象本身來(lái)提供引用計(jì)數(shù)器,但是它不會(huì)去維護(hù)這個(gè)引用計(jì)數(shù)器的值,而是由智能指針來(lái)維護(hù),就好比是對(duì)象提供素材,但是具體怎么去使用這些素材,就交給智能指針來(lái)處理了。由于不管是什么類(lèi)型的對(duì)象,它都需要提供引用計(jì)數(shù)器這個(gè)素材,在C++中,我們就可以把這個(gè)引用計(jì)數(shù)器素材定義為一個(gè)公共類(lèi),這個(gè)類(lèi)只有一個(gè)成員變量,那就是引用計(jì)數(shù)成員變量,其它提供智能指針引用的對(duì)象,都必須從這個(gè)公共類(lèi)繼承下來(lái),這樣,這些不同的對(duì)象就天然地提供了引用計(jì)數(shù)器給智能指針使用了。總的來(lái)說(shuō)就是我們?cè)趯?shí)現(xiàn)智能指會(huì)的過(guò)程中,第一是要定義一個(gè)負(fù)責(zé)提供引用計(jì)數(shù)器的公共類(lèi),第二是我們要實(shí)現(xiàn)相應(yīng)的智能指針對(duì)象類(lèi),后面我們會(huì)看到這種方案是怎么樣實(shí)現(xiàn)的。

                  接下來(lái),我們就先介紹輕量級(jí)指針的實(shí)現(xiàn)原理,然后再接著介紹強(qiáng)指針和弱指針的實(shí)現(xiàn)原理。

                  1. 輕量級(jí)指針

                  先來(lái)看一下實(shí)現(xiàn)引用計(jì)數(shù)的類(lèi)LightRefBase,它定義在frameworks/base/include/utils/RefBase.h文件中:

          template <class T>
          class LightRefBase
          {
          public:
          	inline LightRefBase() : mCount(0) { }
          	inline void incStrong(const void* id) const {
          		android_atomic_inc(&mCount);
          	}
          	inline void decStrong(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;
          	}
          
          protected:
          	inline ~LightRefBase() { }
          
          private:
          	mutable volatile int32_t mCount;
          };
                   這個(gè)類(lèi)很簡(jiǎn)單,它只一個(gè)成員變量mCount,這就是引用計(jì)數(shù)器了,它的初始化值為0,另外,這個(gè)類(lèi)還提供兩個(gè)成員函數(shù)incStrong和decStrong來(lái)維護(hù)引用計(jì)數(shù)器的值,這兩個(gè)函數(shù)就是提供給智能指針來(lái)調(diào)用的了,這里要注意的是,在decStrong函數(shù)中,如果當(dāng)前引用計(jì)數(shù)值為1,那么當(dāng)減1后就會(huì)變成0,于是就會(huì)delete這個(gè)對(duì)象。

           

                   前面說(shuō)過(guò),要實(shí)現(xiàn)自動(dòng)引用計(jì)數(shù),除了要有提供引用計(jì)數(shù)器的基類(lèi)外,還需要有智能指針類(lèi)。在Android系統(tǒng)中,配合LightRefBase引用計(jì)數(shù)使用的智能指針類(lèi)便是sp了,它也是定義在frameworks/base/include/utils/RefBase.h文件中:

          template <typename T>
          class sp
          {
          public:
          	typedef typename RefBase::weakref_type weakref_type;
          
          	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<typename 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; }
          	inline  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;
          
          	// Optimization for wp::promote().
          	sp(T* p, weakref_type* refs);
          
          	T*              m_ptr;
          };
                  這個(gè)類(lèi)的內(nèi)容比較多,但是這里我們只關(guān)注它的成員變量m_ptr、構(gòu)造函數(shù)和析構(gòu)函數(shù)。不難看出,成員變量m_ptr就是指向真正的對(duì)象了,它是在構(gòu)造函數(shù)里面初始化的。接下來(lái)我們就再看一下它的兩個(gè)構(gòu)造函數(shù),一個(gè)是普通構(gòu)造函數(shù),一個(gè)拷貝構(gòu)造函數(shù):

          template<typename T>
          sp<T>::sp(T* other)
              : m_ptr(other)
          {
              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);
          }
          
                  這兩個(gè)構(gòu)造函數(shù)都會(huì)首先初始化成員變量m_ptr,然后再調(diào)用m_ptr的incStrong函數(shù)來(lái)增加對(duì)象的引用計(jì)數(shù),在我們這個(gè)場(chǎng)景中,就是調(diào)用LightRefBase類(lèi)的incStrong函數(shù)了。

           

                  最后,看一下析構(gòu)函數(shù):

          template<typename T>
          sp<T>::~sp()
          {
              if (m_ptr) m_ptr->decStrong(this);
          }
          
                  析構(gòu)函數(shù)也很簡(jiǎn)單,只是調(diào)用m_ptr的成員函數(shù)decStrong來(lái)減少對(duì)象的引用計(jì)數(shù)值,這里就是調(diào)用LightRefBase類(lèi)的decStrong函數(shù)了,前面我們看到,當(dāng)這個(gè)引用計(jì)數(shù)減1后變成0時(shí),就會(huì)自動(dòng)delete這個(gè)對(duì)象了。

           

                  輕量級(jí)智能指針的實(shí)現(xiàn)原理大概就是這樣了,比較簡(jiǎn)單,下面我們?cè)儆靡粋€(gè)例子來(lái)說(shuō)明它的用法。

                  2. 輕量級(jí)指針的用法

                  參考在Ubuntu上為Android系統(tǒng)內(nèi)置C可執(zhí)行程序測(cè)試Linux內(nèi)核驅(qū)動(dòng)程序一文,我們?cè)趀xternal目錄下建立一個(gè)C++工程目錄lightpointer,它里面有兩個(gè)文件,一個(gè)lightpointer.cpp文件,另外一個(gè)是Android.mk文件。

                  源文件lightpointer.cpp的內(nèi)容如下:

          #include <stdio.h>
          #include <utils/RefBase.h>
          
          using namespace android;
          
          class LightClass : public LightRefBase<LightClass>
          {
          public:
                  LightClass()
                  {
                          printf("Construct LightClass Object.");
                  }
          
                  virtual ~LightClass()
                  {
                          printf("Destory LightClass Object.");
                  }
          };
          
          int main(int argc, char** argv)
          {
                  LightClass* pLightClass = new LightClass();
                  sp<LightClass> lpOut = pLightClass;
          
                  printf("Light Ref Count: %d.\n", pLightClass->getStrongCount());
          
                  {
                          sp<LightClass> lpInner = lpOut;
          
                          printf("Light Ref Count: %d.\n", pLightClass->getStrongCount());
                  }
          
                  printf("Light Ref Count: %d.\n", pLightClass->getStrongCount());
          
                  return 0;
          }
                  我們創(chuàng)建一個(gè)自己的類(lèi)LightClass,繼承了LightRefBase模板類(lèi),這樣類(lèi)LightClass就具有引用計(jì)數(shù)的功能了。在main函數(shù)里面,我們首先new一個(gè)LightClass對(duì)象,然后把這個(gè)對(duì)象賦值給智能指針lpOut,這時(shí)候通過(guò)一個(gè)printf語(yǔ)句來(lái)將當(dāng)前對(duì)象的引用計(jì)數(shù)值打印出來(lái),從前面的分析可以看出,如果一切正常的話(huà),這里打印出來(lái)的引用計(jì)數(shù)值為1。接著,我們又在兩個(gè)大括號(hào)里面定義了另外一個(gè)智能指針lpInner,它通過(guò)lpOut間接地指向了前面我們所創(chuàng)建的對(duì)象,這時(shí)候再次將當(dāng)前對(duì)象的引用計(jì)數(shù)值打印出來(lái),從前面 的分析也可以看出,如果一切正常的話(huà),這里打印出來(lái)的引用計(jì)數(shù)值應(yīng)該為2。程序繼承往下執(zhí)行,當(dāng)出了大括號(hào)的范圍的時(shí)候,智能指針對(duì)象lpInner就被析構(gòu)了,從前面的分析可以知道,智能指針在析構(gòu)的時(shí)候,會(huì)減少當(dāng)前對(duì)象的引用計(jì)數(shù)值,因此,最后一個(gè)printf語(yǔ)句打印出來(lái)的引用計(jì)數(shù)器值應(yīng)該為1。當(dāng)main函數(shù)執(zhí)行完畢后,智能指針lpOut也會(huì)被析構(gòu),被析構(gòu)時(shí),它會(huì)再次減少當(dāng)前對(duì)象的引用計(jì)數(shù),這時(shí)候,對(duì)象的引用計(jì)數(shù)值就為0了,于是,它就會(huì)被delete了。

           

                  編譯腳本文件Android.mk的內(nèi)容如下:

          LOCAL_PATH := $(call my-dir)
          include $(CLEAR_VARS)
          LOCAL_MODULE_TAGS := optional
          LOCAL_MODULE := lightpointer
          LOCAL_SRC_FILES := lightpointer.cpp
          LOCAL_SHARED_LIBRARIES := \
                  libcutils \
                  libutils
          include $(BUILD_EXECUTABLE)
                  最后,我們參照如何單獨(dú)編譯Android源代碼中的模塊一文,使用mmm命令對(duì)工程進(jìn)行編譯:
          USER-NAME@MACHINE-NAME:~/Android$ mmm ./external/lightpointer
                  編譯之后,就可以打包了:

          USER-NAME@MACHINE-NAME:~/Android$ make snod
                  最后得到可執(zhí)行程序lightpointer就位于設(shè)備上的/system/bin/目錄下。啟動(dòng)模擬器,通過(guò)adb shell命令進(jìn)入到模擬器終端,進(jìn)入到/system/bin/目錄,執(zhí)行l(wèi)ightpointer可執(zhí)行程序,驗(yàn)證程序是否按照我們?cè)O(shè)計(jì)的邏輯運(yùn)行:
          USER-NAME@MACHINE-NAME:~/Android$ adb shell
          root@android:/ # cd system/bin/        
          root@android:/system/bin # ./lightpointer                                      
          Construct LightClass Object.
          Light Ref Count: 1.
          Light Ref Count: 2.
          Light Ref Count: 1.
          Destory LightClass Object.

                 這里可以看出,程序一切都是按照我們的設(shè)計(jì)來(lái)運(yùn)行,這也驗(yàn)證了我們上面分析的輕量級(jí)智能指針的實(shí)現(xiàn)原理。

                 3. 強(qiáng)指針

                 強(qiáng)指針?biāo)褂玫囊糜?jì)數(shù)類(lèi)為RefBase,它LightRefBase類(lèi)要復(fù)雜多了,所以才稱(chēng)后者為輕量級(jí)的引用計(jì)數(shù)基類(lèi)吧。我們先來(lái)看看RefBase類(lèi)的實(shí)現(xiàn),它定義在frameworks/base/include/utils/RefBase.h文件中:

           

          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);
          
          		bool                attemptIncStrong(const void* id);
          
          		//! This is only safe if you have set OBJECT_LIFETIME_FOREVER.
          		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);
          	}
          
          protected:
          	RefBase();
          	virtual                 ~RefBase();
          
          	//! Flags for extendObjectLifetime()
          	enum {
          		OBJECT_LIFETIME_WEAK    = 0x0001,
          		OBJECT_LIFETIME_FOREVER = 0x0003
          	};
          
          	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);
          
          	weakref_impl* const mRefs;
          };
                  RefBase類(lèi)和LightRefBase類(lèi)一樣,提供了incStrong和decStrong成員函數(shù)來(lái)操作它的引用計(jì)數(shù)器;而RefBase類(lèi)與LightRefBase類(lèi)最大的區(qū)別是,它不像LightRefBase類(lèi)一樣直接提供一個(gè)整型值(mutable volatile int32_t mCount)來(lái)維護(hù)對(duì)象的引用計(jì)數(shù),前面我們說(shuō)過(guò),復(fù)雜的引用計(jì)數(shù)技術(shù)同時(shí)支持強(qiáng)引用計(jì)數(shù)和弱引用計(jì)數(shù),在RefBase類(lèi)中,這兩種計(jì)數(shù)功能是通過(guò)其成員變量mRefs來(lái)提供的。

           

                  RefBase類(lèi)的成員變量mRefs的類(lèi)型為weakref_impl指針,它實(shí)現(xiàn)在frameworks/base/libs/utils/RefBase.cpp文件中:

           

          class RefBase::weakref_impl : public RefBase::weakref_type
          {
          public:
          	volatile int32_t    mStrong;
          	volatile int32_t    mWeak;
          	RefBase* const      mBase;
          	volatile int32_t    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 addWeakRef(const void* /*id*/) { }
          	void removeWeakRef(const void* /*id*/) { }
          	void printRefs() const { }
          	void trackMe(bool, bool) { }
          
          #else
          	weakref_impl(RefBase* base)
          		: mStrong(INITIAL_STRONG_VALUE)
          		, mWeak(0)
          		, mBase(base)
          		, mFlags(0)
          		, mStrongRefs(NULL)
          		, mWeakRefs(NULL)
          		, mTrackEnabled(!!DEBUG_REFS_ENABLED_BY_DEFAULT)
          		, mRetain(false)
          	{
          		//LOGI("NEW weakref_impl %p for RefBase %p", this, base);
          	}
          
          	~weakref_impl()
          	{
          		LOG_ALWAYS_FATAL_IF(!mRetain && mStrongRefs != NULL, "Strong references remain!");
          		LOG_ALWAYS_FATAL_IF(!mRetain && mWeakRefs != NULL, "Weak references remain!");
          	}
          
          	void addStrongRef(const void* id)
          	{
          		addRef(&mStrongRefs, id, mStrong);
          	}
          
          	void removeStrongRef(const void* id)
          	{
          		if (!mRetain)
          			removeRef(&mStrongRefs, id);
          		else
          			addRef(&mStrongRefs, id, -mStrong);
          	}
          
          	void addWeakRef(const void* id)
          	{
          		addRef(&mWeakRefs, id, mWeak);
          	}
          	void removeWeakRef(const void* id)
          	{
          		if (!mRetain)
          			removeRef(&mWeakRefs, id);
          		else
          			addRef(&mWeakRefs, id, -mWeak);
          	}
          
          	void trackMe(bool track, bool retain)
          	{
          		mTrackEnabled = track;
          		mRetain = retain;
          	}
          
          	......
          
          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* ref = *refs;
          			while (ref != NULL) {
          				if (ref->id == id) {
          					*refs = ref->next;
          					delete ref;
          					return;
          				}
          
          				refs = &ref->next;
          				ref = *refs;
          			}
          
          			LOG_ALWAYS_FATAL("RefBase: removing id %p on RefBase %p (weakref_type %p) that doesn't exist!",
          				id, mBase, this);
          		}
          	}
          
          	......
          
          	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
          };
                  這個(gè)類(lèi)看起來(lái)實(shí)現(xiàn)得很復(fù)雜,其實(shí)不然,這個(gè)類(lèi)的實(shí)現(xiàn)可以分成兩部分:

           

          #if !DEBUG_REFS
          
          ......
          
          #else
                  編譯指令之間的這部分源代碼是Release版本的源代碼,它的成員函數(shù)都是空實(shí)現(xiàn);

           

          #else 
          
          ......
          
          #endif
                  編譯指令之間的部分源代碼是Debug版本的源代碼,它的成員函數(shù)都是有實(shí)現(xiàn)的,實(shí)現(xiàn)這些函數(shù)的目的都是為了方便開(kāi)發(fā)人員調(diào)試引用計(jì)數(shù)用的,除此之外,還在內(nèi)部實(shí)現(xiàn)了一個(gè)結(jié)構(gòu)體ref_entry:

           

          struct ref_entry
          {
          	ref_entry* next;
          	const void* id;
          #if DEBUG_REFS_CALLSTACK_ENABLED
          	CallStack stack;
          #endif
          	int32_t ref;
          };
                  這個(gè)結(jié)構(gòu)體也是為了方便調(diào)試而使用的,我們可以不關(guān)注這部分用于調(diào)試的代碼。

                  總的來(lái)說(shuō),weakref_impl類(lèi)只要提供了以下四個(gè)成員變量來(lái)維護(hù)對(duì)象的引用計(jì)數(shù):

          volatile int32_t    mStrong;
          volatile int32_t    mWeak;
          RefBase* const      mBase;
          volatile int32_t    mFlags;
                  其中mStrong和mWeak分別表示對(duì)象的強(qiáng)引用計(jì)數(shù)和弱引用計(jì)數(shù);RefBase類(lèi)包含了一個(gè)weakref_impl類(lèi)指針mRefs,而這里的weakref_impl類(lèi)也有一個(gè)成員變量mBase來(lái)指向它的宿主類(lèi)RefBase;mFlags是一個(gè)標(biāo)志位,它指示了維護(hù)對(duì)象引用計(jì)數(shù)所使用的策略,后面我們將會(huì)分析到,它的取值為0,或者以下的枚舉值:

           

          //! Flags for extendObjectLifetime()
              enum {
                  OBJECT_LIFETIME_WEAK    = 0x0001,
                  OBJECT_LIFETIME_FOREVER = 0x0003
              };
          
                  這里我們還需要注意的一點(diǎn)的是,從weakref_impl的類(lèi)名來(lái)看,它應(yīng)該是一個(gè)實(shí)現(xiàn)類(lèi),那么,就必然有一個(gè)對(duì)應(yīng)的接口類(lèi),這個(gè)對(duì)應(yīng)的接口類(lèi)的就是RefBase類(lèi)內(nèi)部定義的weakref_type類(lèi)了,這是一種把類(lèi)的實(shí)現(xiàn)與接口定義分離的設(shè)計(jì)方法。學(xué)習(xí)過(guò)設(shè)計(jì)模式的讀者應(yīng)該知道,在設(shè)計(jì)模式里面,非常強(qiáng)調(diào)類(lèi)的接口定義和類(lèi)的實(shí)現(xiàn)分離,以便利于后續(xù)擴(kuò)展和維護(hù),這里就是用到了這種設(shè)計(jì)思想。

           

                  說(shuō)了這多,RefBase類(lèi)給人的感覺(jué)還是挺復(fù)雜的,不要緊,我們一步步來(lái),先通過(guò)下面這個(gè)圖來(lái)梳理一下這些類(lèi)之間的關(guān)系:


                  從這個(gè)類(lèi)圖可以看出,每一個(gè)RefBase對(duì)象包含了一個(gè)weakref_impl對(duì)象,而weakref_impl對(duì)象實(shí)現(xiàn)了weakref_type接口,同時(shí)它可以包含多個(gè)ref_entry對(duì)象,前面說(shuō)過(guò),ref_entry是調(diào)試用的一個(gè)結(jié)構(gòu)體,實(shí)際使用中可以不關(guān)注。

                  提供引用計(jì)數(shù)器的類(lèi)RefBase我們就暫時(shí)介紹到這里,后面我們?cè)俳Y(jié)合智能指針類(lèi)一起分析,現(xiàn)在先來(lái)看看強(qiáng)指針類(lèi)和弱指針類(lèi)的定義。強(qiáng)指針類(lèi)的定義我們?cè)谇懊娼榻B輕量級(jí)指針的時(shí)候已經(jīng)見(jiàn)到了,就是sp類(lèi)了,這里就不再把它的代碼列出來(lái)了。我們來(lái)看看它的構(gòu)造函數(shù)的實(shí)現(xiàn):

           

          template<typename T>
          sp<T>::sp(T* other)
              : m_ptr(other)
          {
              if (other) other->incStrong(this);
          }

                  這里傳進(jìn)來(lái)的參數(shù)other一定是繼承于RefBase類(lèi)的,因此,在函數(shù)的內(nèi)部,它調(diào)用的是RefBase類(lèi)的incStrong函數(shù),它定義在frameworks/base/libs/utils/RefBase.cpp文件中:

           

          void RefBase::incStrong(const void* id) const
          {
              weakref_impl* const refs = mRefs;
              refs->addWeakRef(id);
              refs->incWeak(id);
              refs->addStrongRef(id); 
          
              const int32_t c = android_atomic_inc(&refs->mStrong); 
              LOG_ASSERT(c > 0, "incStrong() called on %p after last strong ref", refs);
          
              #if PRINT_REFS 
              LOGD("incStrong of %p from %p: cnt=%d\n", this, id, c);
              #endif 
          
              if (c != INITIAL_STRONG_VALUE) { 
                  return; 
              } 
          
              android_atomic_add(-INITIAL_STRONG_VALUE, &refs->mStrong); 
              const_cast<RefBase*>(this)->onFirstRef();
          }

           

           

                  成員變量mRefs是在RefBase類(lèi)的構(gòu)造函數(shù)中創(chuàng)建的:

           

           

          RefBase::RefBase()
              : mRefs(new weakref_impl(this))
          {
          //    LOGV("Creating refs %p with RefBase %p\n", mRefs, this);
          }
                  在這個(gè)incStrong函數(shù)中,主要做了三件事情:

           

                  一是增加弱引用計(jì)數(shù):

          refs->addWeakRef(id);
          refs->incWeak(id);
                  二是增加強(qiáng)引用計(jì)數(shù):
          refs->addStrongRef(id);
          const int32_t c = android_atomic_inc(&refs->mStrong);
                  三是如果發(fā)現(xiàn)是首次調(diào)用這個(gè)對(duì)象的incStrong函數(shù),就會(huì)調(diào)用一個(gè)這個(gè)對(duì)象的onFirstRef函數(shù),讓對(duì)象有機(jī)會(huì)在對(duì)象被首次引用時(shí)做一些處理邏輯:
          if (c != INITIAL_STRONG_VALUE)  {
              return;
          }
          
          android_atomic_add(-INITIAL_STRONG_VALUE, &refs->mStrong);
          const_cast<RefBase*>(this)->onFirstRef();
                 這里的c返回的是refs->mStrong加1前的值,如果發(fā)現(xiàn)等于INITIAL_STRONG_VALUE,就說(shuō)明這個(gè)對(duì)象的強(qiáng)引用計(jì)數(shù)是第一次被增加,因此,refs->mStrong就是初始化為INITIAL_STRONG_VALUE的,它的值為:

           

          #define INITIAL_STRONG_VALUE (1<<28)
                  這個(gè)值加1后等于1<<28 + 1,不等于1,因此,后面要再減去-INITIAL_STRONG_VALUE,于是,refs->mStrong就等于1了,就表示當(dāng)前對(duì)象的強(qiáng)引用計(jì)數(shù)值為1了,這與這個(gè)對(duì)象是第一次被增加強(qiáng)引用計(jì)數(shù)值的邏輯是一致的。

                  回過(guò)頭來(lái)看弱引用計(jì)數(shù)是如何增加的,首先是調(diào)用weakref_impl類(lèi)的addWeakRef函數(shù),我們知道,在Release版本中,這個(gè)函數(shù)也不做,而在Debug版本中,這個(gè)函數(shù)增加了一個(gè)ref_entry對(duì)象到了weakref_impl對(duì)象的mWeakRefs列表中,表示此weakref_impl對(duì)象的弱引用計(jì)數(shù)被增加了一次。接著又調(diào)用了weakref_impl類(lèi)的incWeak函數(shù),真正增加弱引用計(jì)數(shù)值就是在這個(gè)函數(shù)實(shí)現(xiàn)的了,weakref_impl類(lèi)的incWeak函數(shù)繼承于其父類(lèi)weakref_type的incWeak函數(shù):

          void RefBase::weakref_type::incWeak(const void* id)
          {
              weakref_impl* const impl = static_cast<weakref_impl*>(this);
              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);
          }
          
                 增加弱引用計(jì)數(shù)是下面語(yǔ)句執(zhí)行的:
          const int32_t c = android_atomic_inc(&impl->mWeak);
                  但是前面為什么又調(diào)用了一次addWeakRef函數(shù)呢?前面不是已經(jīng)調(diào)用過(guò)了嗎?在Release版本中,因?yàn)閣eakref_impl類(lèi)的addWeakRef函數(shù)是空實(shí)現(xiàn),這里再調(diào)用一次沒(méi)有什么害處,但是如果在Debug版本,豈不是冗余了嗎?搞不清,有人問(wèn)過(guò)負(fù)責(zé)開(kāi)發(fā)Android系統(tǒng)Binder通信機(jī)制模塊的作者Dianne Hackborn這個(gè)問(wèn)題,他是這樣回答的:

           

                  http://groups.google.com/group/android-platform/browse_thread/thread/cc641db8487dd83

                  Ah I see.  Well the debug code may be broken, though I wouldn't leap to that 
                  conclusion without actually testing it; I know it has been used in the 
                  past.  Anyway, these things get compiled out in non-debug builds, so there 
                  is no reason to change them unless you are actually trying to use this debug 
                  code and it isn't working and need to do this to fix it. 

                  既然他也不知道怎么回事,我們也不必深究了,知道有這么回事就行。

                  這里總結(jié)一下強(qiáng)指針類(lèi)sp在其構(gòu)造函數(shù)里面所做的事情就是分別為目標(biāo)對(duì)象的強(qiáng)引用計(jì)數(shù)和弱引和計(jì)數(shù)增加了1。

                  再來(lái)看看強(qiáng)指針類(lèi)的析構(gòu)函數(shù)的實(shí)現(xiàn):

          template<typename T>
          sp<T>::~sp()
          {
              if (m_ptr) m_ptr->decStrong(this);
          }
          
                 同樣,這里的m_ptr指向的目標(biāo)對(duì)象一定是繼承了RefBase類(lèi)的,因此,這里調(diào)用的是RefBase類(lèi)的decStrong函數(shù),這也是定義在frameworks/base/libs/utils/RefBase.cpp文件中:

          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 PRINT_REFS
              LOGD("decStrong of %p from %p: cnt=%d\n", this, id, c);
          #endif
              LOG_ASSERT(c >= 1, "decStrong() called on %p too many times", refs);
              if (c == 1) {
                  const_cast<RefBase*>(this)->onLastStrongRef(id);
                  if ((refs->mFlags&OBJECT_LIFETIME_WEAK) != OBJECT_LIFETIME_WEAK) {
                      delete this;
                  }
              }
              refs->removeWeakRef(id);
              refs->decWeak(id);
          }
                  這里的refs->removeStrongRef函數(shù)調(diào)用語(yǔ)句是對(duì)應(yīng)前面在RefBase::incStrong函數(shù)里的refs->addStrongRef函數(shù)調(diào)用語(yǔ)句的,在Release版本中,這也是一個(gè)空實(shí)現(xiàn)函數(shù),真正實(shí)現(xiàn)強(qiáng)引用計(jì)數(shù)減1的操作是下面語(yǔ)句:
          const int32_t c = android_atomic_dec(&refs->mStrong);
                  如果發(fā)現(xiàn)減1前,此對(duì)象的強(qiáng)引用計(jì)數(shù)為1,就說(shuō)明從此以后,就再?zèng)]有地方引用這個(gè)目標(biāo)對(duì)象了,這時(shí)候,就要看看是否要delete這個(gè)目標(biāo)對(duì)象了:

          if (c == 1) {
              const_cast<RefBase*>(this)->onLastStrongRef(id);
              if ((refs->mFlags&OBJECT_LIFETIME_WEAK) != OBJECT_LIFETIME_WEAK) {
                  delete this;
              }
          }
                  在強(qiáng)引用計(jì)數(shù)為0的情況下,如果對(duì)象的標(biāo)志位OBJECT_LIFETIME_WEAK被設(shè)置了,就說(shuō)明這個(gè)對(duì)象的生命周期是受弱引用計(jì)數(shù)所控制的,因此,這時(shí)候就不能delete對(duì)象,要等到弱引用計(jì)數(shù)也為0的情況下,才能delete這個(gè)對(duì)象。

           

                  接下來(lái)的ref->removeWeakRef函數(shù)調(diào)用語(yǔ)句是對(duì)應(yīng)前面在RefBase::incStrong函數(shù)里的refs->addWeakRef函數(shù)調(diào)用語(yǔ)句的,在Release版本中,這也是一個(gè)空實(shí)現(xiàn)函數(shù),真正實(shí)現(xiàn)強(qiáng)引用計(jì)數(shù)減1的操作下面的refs->decWeak函數(shù),weakref_impl類(lèi)沒(méi)有實(shí)現(xiàn)自己的decWeak函數(shù),它繼承了weakref_type類(lèi)的decWeak函數(shù):

          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(&impl->mWeak);
              LOG_ASSERT(c >= 1, "decWeak called on %p too many times", this);
              if (c != 1) return;
          
              if ((impl->mFlags&OBJECT_LIFETIME_WEAK) != OBJECT_LIFETIME_WEAK) {
                  if (impl->mStrong == INITIAL_STRONG_VALUE)
                      delete impl->mBase;
                  else {
          //            LOGV("Freeing refs %p of old RefBase %p\n", this, impl->mBase);
                      delete impl;
                  }
              } else {
                  impl->mBase->onLastWeakRef(id);
                  if ((impl->mFlags&OBJECT_LIFETIME_FOREVER) != OBJECT_LIFETIME_FOREVER) {
                      delete impl->mBase;
                  }
              }
          }
                 這里又一次調(diào)用了weakref_impl對(duì)象的removeWeakRef函數(shù),這也是和RefBase::weakref_type::incWeak函數(shù)里面的impl->addWeakRef語(yǔ)句所對(duì)應(yīng)的,實(shí)現(xiàn)弱引用計(jì)數(shù)減1的操作是下面語(yǔ)句:

           

          const int32_t c = android_atomic_dec(&impl->mWeak);
                 減1前如果發(fā)現(xiàn)不等于1,那么就什么也不用做就返回了,如果發(fā)現(xiàn)等于1,就說(shuō)明當(dāng)前對(duì)象的弱引用計(jì)數(shù)值為0了,這時(shí)候,就要看看是否要delete這個(gè)對(duì)象了:

          if ((impl->mFlags&OBJECT_LIFETIME_WEAK) != OBJECT_LIFETIME_WEAK) {
              if (impl->mStrong == INITIAL_STRONG_VALUE)
                  delete impl->mBase;
              else {
          //      LOGV("Freeing refs %p of old RefBase %p\n", this, impl->mBase);
                  delete impl;
              }
          } else {
              impl->mBase->onLastWeakRef(id);
              if ((impl->mFlags&OBJECT_LIFETIME_FOREVER) != OBJECT_LIFETIME_FOREVER) {
                  delete impl->mBase;
              }
          }
                  如果目標(biāo)對(duì)象的生命周期是不受弱引用計(jì)數(shù)控制的,就執(zhí)行下面語(yǔ)句:

          if (impl->mStrong == INITIAL_STRONG_VALUE)
              delete impl->mBase;
          else {
          //  LOGV("Freeing refs %p of old RefBase %p\n", this, impl->mBase);
              delete impl;
          }
                  這個(gè)代碼段是什么意思呢?這里是減少對(duì)象的弱引用計(jì)數(shù)的地方,如果調(diào)用到這里,那么就說(shuō)明前面一定有增加過(guò)此對(duì)象的弱引用計(jì)數(shù),而增加對(duì)象的弱引用計(jì)數(shù)有兩種場(chǎng)景的,一種場(chǎng)景是增加對(duì)象的強(qiáng)引用計(jì)數(shù)的時(shí)候,會(huì)同時(shí)增加對(duì)象的弱引用計(jì)數(shù),另一種場(chǎng)景是當(dāng)我們使用一個(gè)弱指針來(lái)指向?qū)ο髸r(shí),在弱指針對(duì)象的構(gòu)造函數(shù)里面,也會(huì)增加對(duì)象的弱引用計(jì)數(shù),不過(guò)這時(shí)候,就只是增加對(duì)象的弱引用計(jì)數(shù)了,并沒(méi)有同時(shí)增加對(duì)象的強(qiáng)引用計(jì)數(shù)。因此,這里在減少對(duì)象的弱引用計(jì)數(shù)時(shí),就要分兩種情況來(lái)考慮。

           

                  如果是前一種場(chǎng)景,這里的impl->mStrong就必然等于0,而不會(huì)等于INITIAL_STRONG_VALUE值,因此,這里就不需要delete目標(biāo)對(duì)象了(impl->mBase),因?yàn)榍懊娴腞efBase::decStrong函數(shù)會(huì)負(fù)責(zé)delete這個(gè)對(duì)象。這里唯一需要做的就是把weakref_impl對(duì)象delete掉,但是,為什么要在這里delete這個(gè)weakref_impl對(duì)象呢?這里的weakref_impl對(duì)象是在RefBase的構(gòu)造函數(shù)里面new出來(lái)的,理論上說(shuō)應(yīng)該在在RefBase的析構(gòu)函數(shù)里delete掉這個(gè)weakref_impl對(duì)象的。在RefBase的析構(gòu)函數(shù)里面,的確是會(huì)做這件事情:

          RefBase::~RefBase()
          {
          //    LOGV("Destroying RefBase %p (refs %p)\n", this, mRefs);
              if (mRefs->mWeak == 0) {
          //        LOGV("Freeing refs %p of old RefBase %p\n", mRefs, this);
                  delete mRefs;
              }
          }

           

                  但是不要忘記,在這個(gè)場(chǎng)景下,目標(biāo)對(duì)象是前面的RefBase::decStrong函數(shù)delete掉的,這時(shí)候目標(biāo)對(duì)象就會(huì)被析構(gòu),但是它的弱引用計(jì)數(shù)值尚未執(zhí)行減1操作,因此,這里的mRefs->mWeak == 0條件就不成立,于是就不會(huì)delete這個(gè)weakref_impl對(duì)象,因此,就延遲到執(zhí)行這里decWeak函數(shù)時(shí)再執(zhí)行。

                  如果是后一種情景,這里的impl->mStrong值就等于INITIAL_STRONG_VALUE了,這時(shí)候由于沒(méi)有地方會(huì)負(fù)責(zé)delete目標(biāo)對(duì)象,因此,就需要把目標(biāo)對(duì)象(imp->mBase)delete掉了,否則就會(huì)造成內(nèi)存泄漏。在delete這個(gè)目標(biāo)對(duì)象的時(shí)候,就會(huì)執(zhí)行RefBase類(lèi)的析構(gòu)函數(shù),這時(shí)候目標(biāo)對(duì)象的弱引用計(jì)數(shù)等于0,于是,就會(huì)把weakref_impl對(duì)象也一起delete掉了。

                  回到外層的if語(yǔ)句中,如果目標(biāo)對(duì)象的生命周期是受弱引用計(jì)數(shù)控制的,就執(zhí)行下面語(yǔ)句:

          impl->mBase->onLastWeakRef(id);
          if ((impl->mFlags&OBJECT_LIFETIME_FOREVER) != OBJECT_LIFETIME_FOREVER) {
              delete impl->mBase;
          }
                  理論上說(shuō),如果目標(biāo)對(duì)象的生命周期是受弱引用計(jì)數(shù)控制的,那么當(dāng)強(qiáng)引用計(jì)數(shù)和弱引用計(jì)數(shù)都為0的時(shí)候,這時(shí)候就應(yīng)該delete目標(biāo)對(duì)象了,但是這里還有另外一層控制,我們可以設(shè)置目標(biāo)對(duì)象的標(biāo)志值為OBJECT_LIFETIME_FOREVER,即目標(biāo)對(duì)象的生命周期完全不受強(qiáng)引用計(jì)數(shù)和弱引用計(jì)數(shù)控制,在這種情況下,即使目標(biāo)對(duì)象的強(qiáng)引用計(jì)數(shù)和弱引用計(jì)數(shù)都同時(shí)為0,這里也不能delete這個(gè)目標(biāo)對(duì)象,那么,由誰(shuí)來(lái)delete掉呢?當(dāng)然是誰(shuí)new出來(lái)的,就誰(shuí)來(lái)delete掉了,這時(shí)候智能指針就完全退化為普通指針了,這里的智能指針設(shè)計(jì)的非常強(qiáng)大。

           

                  分析到這里,有必要小結(jié)一下:

                  A. 如果對(duì)象的標(biāo)志位被設(shè)置為0,那么只要發(fā)現(xiàn)對(duì)象的強(qiáng)引用計(jì)數(shù)值為0,那就會(huì)自動(dòng)delete掉這個(gè)對(duì)象;

                  B. 如果對(duì)象的標(biāo)志位被設(shè)置為OBJECT_LIFETIME_WEAK,那么只有當(dāng)對(duì)象的強(qiáng)引用計(jì)數(shù)和弱引用計(jì)數(shù)都為0的時(shí)候,才會(huì)自動(dòng)delete掉這個(gè)對(duì)象;

                  C. 如果對(duì)象的標(biāo)志位被設(shè)置為OBJECT_LIFETIME_FOREVER,那么對(duì)象就永遠(yuǎn)不會(huì)自動(dòng)被delete掉,誰(shuí)new出來(lái)的對(duì)象誰(shuí)來(lái)delete掉。

                  到了這里,強(qiáng)指針就分析完成了,最后來(lái)分析弱指針。

                  4. 弱指針

                  弱指針?biāo)褂玫囊糜?jì)數(shù)類(lèi)與強(qiáng)指針一樣,都是RefBase類(lèi),因此,這里就不再重復(fù)介紹了,我們直接來(lái)弱指針的實(shí)現(xiàn),它定義在frameworks/base/include/utils/RefBase.h文件中:

          template <typename T>
          class wp
          {
          public:
          	typedef 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>& 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>& other);
          	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() const { return m_ptr; }
          
          	// Operators
          
          	COMPARE_WEAK(==)
          		COMPARE_WEAK(!=)
          		COMPARE_WEAK(>)
          		COMPARE_WEAK(<)
          		COMPARE_WEAK(<=)
          		COMPARE_WEAK(>=)
          
          		inline bool operator == (const wp<T>& o) const {
          			return (m_ptr == o.m_ptr) && (m_refs == o.m_refs);
          	}
          	template<typename U>
          	inline bool operator == (const wp<U>& o) const {
          		return m_ptr == o.m_ptr;
          	}
          
          	inline bool operator > (const wp<T>& o) const {
          		return (m_ptr == o.m_ptr) ? (m_refs > o.m_refs) : (m_ptr > o.m_ptr);
          	}
          	template<typename U>
          	inline bool operator > (const wp<U>& o) const {
          		return (m_ptr == o.m_ptr) ? (m_refs > o.m_refs) : (m_ptr > o.m_ptr);
          	}
          
          	inline bool operator < (const wp<T>& o) const {
          		return (m_ptr == o.m_ptr) ? (m_refs < o.m_refs) : (m_ptr < o.m_ptr);
          	}
          	template<typename U>
          	inline bool operator < (const wp<U>& o) const {
          		return (m_ptr == o.m_ptr) ? (m_refs < o.m_refs) : (m_ptr < o.m_ptr);
          	}
          	inline bool operator != (const wp<T>& o) const { return m_refs != o.m_refs; }
          	template<typename U> inline bool operator != (const wp<U>& o) const { return !operator == (o); }
          	inline bool operator <= (const wp<T>& o) const { return !operator > (o); }
          	template<typename U> inline bool operator <= (const wp<U>& o) const { return !operator > (o); }
          	inline bool operator >= (const wp<T>& o) const { return !operator < (o); }
          	template<typename U> inline bool operator >= (const wp<U>& o) const { return !operator < (o); }
          
          private:
          	template<typename Y> friend class sp;
          	template<typename Y> friend class wp;
          
          	T*              m_ptr;
          	weakref_type*   m_refs;
          };
                  與強(qiáng)指針類(lèi)相比,它們都有一個(gè)成員變量m_ptr指向目標(biāo)對(duì)象,但是弱指針還有一個(gè)額外的成員變量m_refs,它的類(lèi)型是weakref_type指針,下面我們分析弱指針的構(gòu)造函數(shù)時(shí)再看看它是如果初始化的。這里我們需要關(guān)注的仍然是弱指針的構(gòu)造函數(shù)和析構(gòu)函數(shù)。

                  先來(lái)看構(gòu)造函數(shù):

          template<typename T>
          wp<T>::wp(T* other)
              : m_ptr(other)
          {
              if (other) m_refs = other->createWeak(this);
          }
                  這里的參數(shù)other一定是繼承了RefBase類(lèi),因此,這里調(diào)用了RefBase類(lèi)的createWeak函數(shù),它定義在frameworks/base/libs/utils/RefBase.cpp文件中:

          RefBase::weakref_type* RefBase::createWeak(const void* id) const
          {
              mRefs->incWeak(id);
              return mRefs;
          }
                  這里的成員變量mRefs的類(lèi)型為weakref_impl指針,weakref_impl類(lèi)的incWeak函數(shù)我們?cè)谇懊嬉呀?jīng)看過(guò)了,它的作用就是增加對(duì)象的弱引用計(jì)數(shù)。函數(shù)最后返回mRefs,于是,弱指針對(duì)象的成員變量m_refs就指向目標(biāo)對(duì)象的weakref_impl對(duì)象了。

                  再來(lái)看析構(gòu)函數(shù):

          template<typename T>
          wp<T>::~wp()
          {
              if (m_ptr) m_refs->decWeak(this);
          }
                  這里,弱指針在析構(gòu)的時(shí)候,與強(qiáng)指針析構(gòu)不一樣,它直接就調(diào)用目標(biāo)對(duì)象的weakref_impl對(duì)象的decWeak函數(shù)來(lái)減少弱引用計(jì)數(shù)了,當(dāng)弱引用計(jì)數(shù)為0的時(shí)候,就會(huì)根據(jù)在目標(biāo)對(duì)象的標(biāo)志位(0、OBJECT_LIFETIME_WEAK或者OBJECT_LIFETIME_FOREVER)來(lái)決定是否要delete目標(biāo)對(duì)象,前面我們已經(jīng)介紹過(guò)了,這里就不再介紹了。

           

                  分析到這里,弱指針還沒(méi)介紹完,它最重要的特性我們還沒(méi)有分析到。前面我們說(shuō)過(guò),弱指針的最大特點(diǎn)是它不能直接操作目標(biāo)對(duì)象,這是怎么樣做到的呢?秘密就在于弱指針類(lèi)沒(méi)有重載*和->操作符號(hào),而強(qiáng)指針重載了這兩個(gè)操作符號(hào)。但是,如果我們要操作目標(biāo)對(duì)象,應(yīng)該怎么辦呢,這就要把弱指針升級(jí)為強(qiáng)指針了:

          template<typename T>
          sp<T> wp<T>::promote() const
          {
              return sp<T>(m_ptr, m_refs);
          }
                  升級(jí)的方式就使用成員變量m_ptr和m_refs來(lái)構(gòu)造一個(gè)強(qiáng)指針sp,這里的m_ptr為指目標(biāo)對(duì)象的一個(gè)指針,而m_refs則是指向目標(biāo)對(duì)象里面的weakref_impl對(duì)象。

                  我們?cè)賮?lái)看看這個(gè)強(qiáng)指針的構(gòu)造過(guò)程:

          template<typename T>
          sp<T>::sp(T* p, weakref_type* refs)
              : m_ptr((p && refs->attemptIncStrong(this)) ? p : 0)
          {
          }
                  主要就是初始化指向目標(biāo)對(duì)象的成員變量m_ptr了,如果目標(biāo)對(duì)象還存在,這個(gè)m_ptr就指向目標(biāo)對(duì)象,如果目標(biāo)對(duì)象已經(jīng)不存在,m_ptr就為NULL,升級(jí)成功與否就要看refs->attemptIncStrong函數(shù)的返回結(jié)果了:
          bool RefBase::weakref_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 != INITIAL_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
          			// 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);
          		} else {
          			// 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->mBase->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.  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->addStrongRef(id);
          
          #if PRINT_REFS
          	LOGD("attemptIncStrong of %p from %p: cnt=%d\n", this, id, curCount);
          #endif
          
          	if (curCount == INITIAL_STRONG_VALUE) {
          		android_atomic_add(-INITIAL_STRONG_VALUE, &impl->mStrong);
          		impl->mBase->onFirstRef();
          	}
          
          	return true;
          }

                  這個(gè)函數(shù)的作用是試圖增加目標(biāo)對(duì)象的強(qiáng)引用計(jì)數(shù),但是有可能會(huì)失敗,失敗的原因可能是因?yàn)槟繕?biāo)對(duì)象已經(jīng)被delete掉了,或者是其它的原因,下面會(huì)分析到。前面我們?cè)谟懻搹?qiáng)指針的時(shí)候說(shuō)到,增加目標(biāo)對(duì)象的強(qiáng)引用計(jì)數(shù)的同時(shí),也會(huì)增加目標(biāo)對(duì)象的弱引用計(jì)數(shù),因此,函數(shù)在開(kāi)始的地方首先就是調(diào)用incWeak函數(shù)來(lái)先增加目標(biāo)對(duì)象的引用計(jì)數(shù),如果后面試圖增加目標(biāo)對(duì)象的強(qiáng)引用計(jì)數(shù)失敗時(shí),會(huì)調(diào)用decWeak函數(shù)來(lái)回滾前面的incWeak操作。

                  這里試圖增加目標(biāo)對(duì)象的強(qiáng)引用計(jì)數(shù)時(shí),分兩種情況討論,一種情況是此時(shí)目標(biāo)對(duì)象正在被其它強(qiáng)指針引用,即它的強(qiáng)引用計(jì)數(shù)大于0,并且不等于INITIAL_STRONG_VALUE,另一種情況是此時(shí)目標(biāo)對(duì)象沒(méi)有被任何強(qiáng)指針引用,即它的強(qiáng)引用計(jì)數(shù)小于等于0,或者等于INITIAL_STRONG_VALUE。

                  第一種情況比較簡(jiǎn)單,因?yàn)檫@時(shí)候說(shuō)明目標(biāo)對(duì)象一定存在,因此,是可以將這個(gè)弱指針提升為強(qiáng)指針的,在這種情況下,只要簡(jiǎn)單地增加目標(biāo)對(duì)象的強(qiáng)引用計(jì)數(shù)值就行了:

           

              while (curCount > 0 && curCount != INITIAL_STRONG_VALUE) {
          	if (android_atomic_cmpxchg(curCount, curCount+1, &impl->mStrong) == 0) {
          		break;
          	}
          	curCount = impl->mStrong;
              }
                  當(dāng)我們?cè)谶@里對(duì)目標(biāo)對(duì)象的強(qiáng)引用計(jì)數(shù)執(zhí)行加1操作時(shí),要保證原子性,因?yàn)槠渌胤揭灿锌赡苷趯?duì)這個(gè)目標(biāo)對(duì)象的強(qiáng)引用計(jì)數(shù)執(zhí)行加1的操作,前面我們一般是調(diào)用android_atomic_inc函數(shù)來(lái)完成,但是這里是通過(guò)調(diào)用android_atomic_cmpxchg函數(shù)來(lái)完成,android_atomic_cmpxchg函數(shù)是體系結(jié)構(gòu)相關(guān)的函數(shù),在提供了一些特殊的指令的體系結(jié)構(gòu)上,調(diào)用android_atomic_cmpxchg函數(shù)來(lái)執(zhí)行加1操作的效率會(huì)比調(diào)用android_atomic_inc函數(shù)更高一些。函數(shù)android_atomic_cmpxchg是在system/core/include/cutils/atomic.h文件中定義的一個(gè)宏:

           

           

          int android_atomic_release_cas(int32_t oldvalue, int32_t newvalue,
                  volatile int32_t* addr);
          
          #define android_atomic_cmpxchg android_atomic_release_cas
                  它實(shí)際執(zhí)行的函數(shù)是android_atomic_release_cas,這個(gè)函數(shù)的工作原理大概是這樣的:如果它發(fā)現(xiàn)*addr == oldvalue,就會(huì)執(zhí)行*addr = newvalue的操作,然后返回0,否則什么也不做,返回1。在我們討論的這個(gè)場(chǎng)景中,oldvalue等于curCount,而newvalue等于curCount + 1,于是,在*addr == oldvalue的條件下,就相當(dāng)于是對(duì)目標(biāo)對(duì)象的強(qiáng)引用計(jì)數(shù)值增加了1。什么情況下*addr != oldvalue呢?在調(diào)用android_atomic_release_cas函數(shù)之前,oldvalue和值就是從地址addr讀出來(lái)的,如果在執(zhí)行android_atomic_release_cas函數(shù)的時(shí)候,有其它地方也對(duì)地址addr進(jìn)行操作,那么就會(huì)有可能出現(xiàn)*addr != oldvalue的情況,這時(shí)候就說(shuō)明其它地方也在操作目標(biāo)對(duì)象的強(qiáng)引用計(jì)數(shù)了,因此,這里就不能執(zhí)行增加目標(biāo)對(duì)象的強(qiáng)引用計(jì)數(shù)的操作了,它必須要等到其它地方操作完目標(biāo)對(duì)象的強(qiáng)引用計(jì)數(shù)之后再重新執(zhí)行,這就是為什么要通過(guò)一個(gè)while循環(huán)來(lái)執(zhí)行了。

           

                  第二種情況比較復(fù)雜一點(diǎn),因?yàn)檫@時(shí)候目標(biāo)對(duì)象可能還存在,也可能不存了,這要根據(jù)實(shí)際情況來(lái)判斷。如果此時(shí)目標(biāo)對(duì)象的強(qiáng)引用計(jì)數(shù)值等于INITIAL_STRONG_VALUE,說(shuō)明此目標(biāo)對(duì)象還從未被強(qiáng)指針引用過(guò),這時(shí)候弱指針能夠被提升為強(qiáng)指針的條件就為:

           

          allow = (impl->mFlags&OBJECT_LIFETIME_WEAK) != OBJECT_LIFETIME_WEAK
          	|| impl->mBase->onIncStrongAttempted(FIRST_INC_STRONG, id);

                  即如果目標(biāo)對(duì)象的生命周期只受到強(qiáng)引用計(jì)數(shù)控制或者在目標(biāo)對(duì)象的具體實(shí)現(xiàn)中總是允許這種情況發(fā)生。怎么理解呢?如果目標(biāo)對(duì)象的生命周期只受強(qiáng)引用計(jì)數(shù)控制(它的標(biāo)志位mFlags為0),而這時(shí)目標(biāo)對(duì)象又還未被強(qiáng)指針引用過(guò),它自然就不會(huì)被delete掉,因此,這時(shí)候可以判斷出目標(biāo)對(duì)象是存在的;如果目標(biāo)對(duì)象的生命周期受弱引用計(jì)數(shù)控制(OBJECT_LIFETIME_WEAK),這時(shí)候由于目標(biāo)對(duì)象正在被弱指針引用,因此,弱引用計(jì)數(shù)一定不為0,目標(biāo)對(duì)象一定存在;如果目標(biāo)對(duì)象的生命周期不受引用計(jì)數(shù)控制(BJECT_LIFETIME_FOREVER),這時(shí)候目標(biāo)對(duì)象也是下在被弱指針引用,因此,目標(biāo)對(duì)象的所有者必須保證這個(gè)目標(biāo)對(duì)象還沒(méi)有被delete掉,否則就會(huì)出問(wèn)題了。在后面兩種場(chǎng)景下,因?yàn)槟繕?biāo)對(duì)象的生命周期都是不受強(qiáng)引用計(jì)數(shù)控制的,而現(xiàn)在又要把弱指針提升為強(qiáng)指針,就需要進(jìn)一步調(diào)用目標(biāo)對(duì)象的onIncStrongAttempted來(lái)看看是否允許這種情況發(fā)生,這又該怎么理解呢?可以這樣理解,目標(biāo)對(duì)象的設(shè)計(jì)者可能本身就不希望這個(gè)對(duì)象被強(qiáng)指針引用,只能通過(guò)弱指針來(lái)引用它,因此,這里它就可以重載其父類(lèi)的onIncStrongAttempted函數(shù),然后返回false,這樣就可以阻止弱指針都被提升為強(qiáng)指針。在RefBase類(lèi)中,其成員函數(shù)onIncStrongAttempted默認(rèn)是返回true的:

           

          bool RefBase::onIncStrongAttempted(uint32_t flags, const void* id)
          {
              return (flags&FIRST_INC_STRONG) ? true : false;
          }

           

                  如果此時(shí)目標(biāo)對(duì)象的強(qiáng)引用計(jì)數(shù)值小于等于0,那就說(shuō)明該對(duì)象之前一定被強(qiáng)指針引用過(guò),這時(shí)候就必須保證目標(biāo)對(duì)象是被弱引用計(jì)數(shù)控制的(BJECT_LIFETIME_WEAK),否則的話(huà),目標(biāo)對(duì)象就已經(jīng)被delete了。同樣,這里也要調(diào)用一下目標(biāo)對(duì)象的onIncStrongAttempted成員函數(shù),來(lái)詢(xún)問(wèn)一下目標(biāo)對(duì)象在強(qiáng)引用計(jì)數(shù)值小于等于0的時(shí)候,是否允計(jì)將弱指針提升為強(qiáng)指針。下面這個(gè)代碼段就是執(zhí)行上面所說(shuō)的邏輯:

           

          allow = (impl->mFlags&OBJECT_LIFETIME_WEAK) == OBJECT_LIFETIME_WEAK
          	&& impl->mBase->onIncStrongAttempted(FIRST_INC_STRONG, id);
                 繼續(xù)往下看:

           

           

          if (!allow) {
          	decWeak(id);
          	return false;
          }
          curCount = android_atomic_inc(&impl->mStrong);
                  如果allow值為false,那么就說(shuō)明不允計(jì)把這個(gè)弱指針提升為強(qiáng)指針,因此就返回false了,在返回之前,要先調(diào)用decWeak函數(shù)來(lái)減少目標(biāo)對(duì)象的弱引用計(jì)數(shù),因?yàn)楹瘮?shù)的開(kāi)頭不管三七二十一,首先就調(diào)用了incWeak來(lái)增加目標(biāo)對(duì)象的弱引用計(jì)數(shù)值。

           

                  函數(shù)attemptIncStrong的主體邏輯大概就是這樣了,比較復(fù)雜,讀者要細(xì)細(xì)體會(huì)一下。函數(shù)的最后,如果此弱指針是允計(jì)提升為強(qiáng)指針的,并且此目標(biāo)對(duì)象是第一次被強(qiáng)指針引用,還需要調(diào)整一下目標(biāo)對(duì)象的強(qiáng)引用計(jì)數(shù)值:

           

          if (curCount == INITIAL_STRONG_VALUE) {
          	android_atomic_add(-INITIAL_STRONG_VALUE, &impl->mStrong);
          	impl->mBase->onFirstRef();
          }
                  這個(gè)邏輯我們?cè)谇懊娣治鰪?qiáng)指針時(shí)已經(jīng)分析過(guò)了,這里不再詳述。

           

                  分析到這里,弱指針就介紹完了。強(qiáng)指針和弱指針的關(guān)系比較密切,同時(shí)它們也比較復(fù)雜,下面我們?cè)倥e一個(gè)例子來(lái)說(shuō)明強(qiáng)指針和弱指針的用法,同時(shí)也驗(yàn)證一下它們的實(shí)現(xiàn)原理。

                  5. 強(qiáng)指針和弱指針的用法

                  參考在Ubuntu上為Android系統(tǒng)內(nèi)置C可執(zhí)行程序測(cè)試Linux內(nèi)核驅(qū)動(dòng)程序一文,我們?cè)趀xternal目錄下建立一個(gè)C++工程目錄weightpointer,它里面有兩個(gè)文件,一個(gè)weightpointer.cpp文件,另外一個(gè)是Android.mk文件。

                  源文件weightpointer.cpp的內(nèi)容如下:

          #include <stdio.h>
          #include <utils/RefBase.h>
          
          #define INITIAL_STRONG_VALUE (1<<28)
          
          using namespace android;
          
          class WeightClass : public RefBase
          {
          public:
                  void printRefCount()
                  {
                          int32_t 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();
                  }
          
                  sp<StrongClass> spOut = wpOut.promote();
                  printf("spOut: %p.\n", spOut.get());
          }
          
          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());
          }
          
          
          void TestForeverClass(ForeverClass* pForeverClass)
          {
                  wp<ForeverClass> wpOut = pForeverClass;
                  pForeverClass->printRefCount();
          
                  {
                          sp<ForeverClass> spInner = pForeverClass;
                          pForeverClass->printRefCount();
                  }
          }
          
          int main(int argc, char** argv)
          {
                  printf("Test Strong Class: \n");
                  StrongClass* pStrongClass = new StrongClass();
                  TestStrongClass(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;
          
                  return 0;
          }

           

                  首先定義了一個(gè)基類(lèi)WeightClass,繼承于RefBase類(lèi),它只有一個(gè)成員函數(shù)printRefCount,作用是用來(lái)輸出引用計(jì)數(shù)。接著分別定義了三個(gè)類(lèi)StrongClass、WeakClass和ForeverClass,其中實(shí)例化StrongClass類(lèi)的得到的對(duì)象的標(biāo)志位為默認(rèn)值0,實(shí)例化WeakClass類(lèi)的得到的對(duì)象的標(biāo)志位為OBJECT_LIFETIME_WEAK,實(shí)例化ForeverClass類(lèi)的得到的對(duì)象的標(biāo)志位為OBJECT_LIFETIME_FOREVER,后兩者都是通過(guò)調(diào)用RefBase類(lèi)的extendObjectLifetime成員函數(shù)來(lái)設(shè)置的。

                  在main函數(shù)里面,分別實(shí)例化了這三個(gè)類(lèi)的對(duì)象出來(lái),然后分別傳給TestStrongClass函數(shù)、TestWeakClass函數(shù)和TestForeverClass函數(shù)來(lái)說(shuō)明智能指針的用法,我們主要是通過(guò)考察它們的強(qiáng)引用計(jì)數(shù)和弱引用計(jì)數(shù)來(lái)驗(yàn)證智能指針的實(shí)現(xiàn)原理。

                  編譯腳本文件Android.mk的內(nèi)容如下:

           

          LOCAL_PATH := $(call my-dir)
          include $(CLEAR_VARS)
          LOCAL_MODULE_TAGS := optional
          LOCAL_MODULE := weightpointer
          LOCAL_SRC_FILES := weightpointer.cpp
          LOCAL_SHARED_LIBRARIES := \
                  libcutils \
                  libutils
          include $(BUILD_EXECUTABLE)
                  最后,我們參照如何單獨(dú)編譯Android源代碼中的模塊一文,使用mmm命令對(duì)工程進(jìn)行編譯:
          USER-NAME@MACHINE-NAME:~/Android$ mmm ./external/weightpointer
                  編譯之后,就可以打包了:

           

          USER-NAME@MACHINE-NAME:~/Android$ make snod
                  最后得到可執(zhí)行程序weightpointer就位于設(shè)備上的/system/bin/目錄下。啟動(dòng)模擬器,通過(guò)adb shell命令進(jìn)入到模擬器終端,進(jìn)入到/system/bin/目錄,執(zhí)行weightpointer可執(zhí)行程序,驗(yàn)證程序是否按照我們?cè)O(shè)計(jì)的邏輯運(yùn)行:
          USER-NAME@MACHINE-NAME:~/Android$ adb shell
          root@android:/ # cd system/bin/        
          root@android:/system/bin # ./weightpointer  
                  執(zhí)行TestStrongClass函數(shù)的輸出為:

           

          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.
          spOut: 0x0.

           

                  在TestStrongClass函數(shù)里面,首先定義一個(gè)弱批針wpOut指向從main函數(shù)傳進(jìn)來(lái)的StrongClass對(duì)象,這時(shí)候我們可以看到StrongClass對(duì)象的強(qiáng)引用計(jì)數(shù)和弱引用計(jì)數(shù)值分別為0和1;接著在一個(gè)大括號(hào)里面定義一個(gè)強(qiáng)指針spInner指向這個(gè)StrongClass對(duì)象,這時(shí)候我們可以看到StrongClass對(duì)象的強(qiáng)引用計(jì)數(shù)和弱引用計(jì)數(shù)值分別為1和2;當(dāng)程序跳出了大括號(hào)之后,強(qiáng)指針spInner就被析構(gòu)了,從上面的分析我們知道,強(qiáng)指針spInner析構(gòu)時(shí),會(huì)減少目標(biāo)對(duì)象的強(qiáng)引用計(jì)數(shù)值,因?yàn)榍懊娴玫降膹?qiáng)引用計(jì)數(shù)值為1,這里減1后,就變?yōu)?了,又由于這個(gè)StrongClass對(duì)象的生命周期只受強(qiáng)引用計(jì)數(shù)控制,因此,這個(gè)StrongClass對(duì)象就被delete了,這一點(diǎn)可以從后面的輸出(“Destory StrongClass Object.”)以及試圖把弱指針wpOut提升為強(qiáng)指針時(shí)得到的對(duì)象指針為0x0得到驗(yàn)證。

                  執(zhí)行TestWeakClass函數(shù)的輸出為:

           

          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: 0xa528.
          Destory WeakClass Object.

           

                  TestWeakClass函數(shù)和TestStrongClass函數(shù)的執(zhí)行過(guò)程基本一樣,所不同的是當(dāng)程序跳出大括號(hào)之后,雖然這個(gè)WeakClass對(duì)象的強(qiáng)引用計(jì)數(shù)值已經(jīng)為0,但是由于它的生命周期同時(shí)受強(qiáng)引用計(jì)數(shù)和弱引用計(jì)數(shù)控制,而這時(shí)它的弱引用計(jì)數(shù)值大于0,因此,這個(gè)WeakClass對(duì)象不會(huì)被delete掉,這一點(diǎn)可以從后面試圖把弱批針wpOut提升為強(qiáng)指針時(shí)得到的對(duì)象指針不為0得到驗(yàn)證。

                  執(zhí)行TestForeverClass函數(shù)的輸出來(lái):

           

          Test Froever Class: 
          Construct ForeverClass Object.
          -----------------------
          Strong Ref Count: 0.
          Weak Ref Count: 1.
          -----------------------
          -----------------------
          Strong Ref Count: 1.
          Weak Ref Count: 2.
          -----------------------
                 當(dāng)執(zhí)行完TestForeverClass函數(shù)返回到main函數(shù)的輸出來(lái):

           

           

          -----------------------
          Strong Ref Count: 0.
          Weak Ref Count: 0.
          -----------------------
          Destory ForeverClass Object.
                  這里我們可以看出,雖然這個(gè)ForeverClass對(duì)象的強(qiáng)引用計(jì)數(shù)和弱引用計(jì)數(shù)值均為0了,但是它不自動(dòng)被delete掉,雖然由我們手動(dòng)地delete這個(gè)對(duì)象,它才會(huì)被析構(gòu),這是因?yàn)檫@個(gè)ForeverClass對(duì)象的生命周期是既不受強(qiáng)引用計(jì)數(shù)值控制,也不會(huì)弱引用計(jì)數(shù)值控制。

           

                  這樣,從TestStrongClass、TestWeakClass和TestForeverClass這三個(gè)函數(shù)的輸出就可以驗(yàn)證了我們上面對(duì)Android系統(tǒng)的強(qiáng)指針和弱指針的實(shí)現(xiàn)原理的分析。

                  至此,Android系統(tǒng)的智能指針(輕量級(jí)指針、強(qiáng)指針和弱指針)的實(shí)現(xiàn)原理就分析完成了,它實(shí)現(xiàn)得很小巧但是很精致,希望讀者可以通過(guò)實(shí)際操作細(xì)細(xì)體會(huì)一下。

          作者:Luoshengyang 發(fā)表于2011-9-23 0:59:13 原文鏈接
          閱讀:7184 評(píng)論:23 查看評(píng)論
          posted on 2012-04-17 21:32 mixer-a 閱讀(1012) 評(píng)論(0)  編輯  收藏

          只有注冊(cè)用戶(hù)登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 汉源县| 汾阳市| 永平县| 且末县| 乳山市| 营山县| 和平区| 龙州县| 商洛市| 淮安市| 宜春市| 平乐县| 永胜县| 四川省| 岗巴县| 清镇市| 巧家县| 海南省| 溧阳市| 长治市| 黄骅市| 贺兰县| 黑水县| 连云港市| 娱乐| 田阳县| 许昌市| 鄂托克前旗| 泰宁县| 天水市| 尉氏县| 庄浪县| 青冈县| 宁明县| 中宁县| 三江| 新河县| 许昌县| 濉溪县| 福安市| 双城市|