本文主要內容
- 進程通信概念
- 智能指針概念
- 強指針
- 弱指針
進程通信概念
同一個程序中兩個函數(shù)能互相調用的根本原因是處于相同的內存空間中
因為是在同一個內存空間當中唬格,虛擬地址的映射規(guī)則完全一致盛卡,所以不同函數(shù)間能找到另一函數(shù)的內存地址,所以可以調用到芙扎。
反之不同進程間,它們是沒有辦法直接調用另一進程的方法或者變量的。
Binder芜飘,粘合劑恍风,它是android中使用最廣泛的IPC機制蹦狂。如果將Binder和TCP網(wǎng)絡類比誓篱,會發(fā)現(xiàn)他們很相似:
- Binder驅動器 —— 路由器
- Service Manager ——DNS
- Binder Client —— 客戶端
- Binder Server —— 服務器
智能指針概念
c/c++指針常常會有以下問題:
- 指針沒有初始化
- new了對象后沒有及時delete
- 野指針,如果指針ptr指向對象obj凯楔,obj已經(jīng)被delete了窜骄,但唯一沒做的是將ptr置空,此時ptr就是野指針摆屯,如果在其它地方使用ptr邻遏,程序肯定會發(fā)生異常
針對以上三個問題,智能指針出現(xiàn)了虐骑。
第1個問題很好解決准验,只要在智能指針出現(xiàn)的時候置null即可。
為了解決第2個問題廷没,我們使用引用計數(shù)法糊饱,計算當前對象被引用的次數(shù),如果引用次數(shù)大于0颠黎,則不刪除另锋,反之則刪除。
計數(shù)器由object自身管理狭归,不能由智能指針管理夭坪,因為智能指針不能處理自己之外的引用。
object中實現(xiàn)增加計數(shù)和減少計數(shù)的方法唉铜,當智能指針引用此object時候增加計數(shù)台舱,不再引用時則減少計數(shù)。
如上圖所示潭流,重載等號竞惋,在使用行號賦值的時候調用object的增加計數(shù)方法,在析構函數(shù)中灰嫉,調用減少計數(shù)的方法拆宛。
如果有兩個智能指針同時引用一個object,就會出現(xiàn)下圖所示:
強指針SP
強指針sp讼撒,是StrongPointer的縮寫浑厚,來看看它的代碼:
它和前一小節(jié)的SmartPointer稍微有所不同,比如等號重載根盒。
如果此前 m_ptr 不為空钳幅,則說明此智能指針正在引用其它object,此時則要將之前的object減少計數(shù)炎滞。
而其它構造函數(shù)和析構函數(shù)則與SmartPointer類似敢艰。強指針比較簡單,不再贅述册赛。
弱指針
引用計數(shù)法钠导,有一個問題震嫉,就是循環(huán)引用問題,如果有兩個對象互相引用牡属,而且沒有任何其它對象引用二者票堵,那么這兩對對象的計數(shù)器不為0,則永遠不會被刪除逮栅。
弱指針的主要使命就是解決循環(huán)引用問題悴势,另外弱指針只有升級為強指針,才能訪問它所指向的目標证芭。
和sp相比瞳浦,wp在定義上有以下區(qū)別:
- 除了指向目標的m_ptr之外担映,wp另外還有一個m-refs指針废士,類型為 weakref_type
- 沒有重載 -> ,* 等運行符
- 有一個prmote方法將弱指針升級為強指針
- 目標對象的父類不是 LightRefBase蝇完,而我 RefBase
智能指針的套路官硝,大致就是指針在引用的時候或者在析構的時候調用object的增加計數(shù)或者減少計數(shù),那么弱指針會有什么不一樣短蜕,查看其構造函數(shù)
在sp中氢架,構造時會把計數(shù)器加1,但在wp中朋魔,調用createWeak方法岖研,并且給m_refs賦值,并沒有計數(shù)器警检,wp中m_refs充當計數(shù)器的功能孙援。
這個函數(shù)屬于前面提到的RefBase類,如下所示:
RefBase嵌套了一個重要的類weak_type扇雕,也就是前面的m_refs指針所屬的類型拓售,RefBase中也有一個weak_impl類型,從名稱上看它是weakref_type的實現(xiàn)類镶奉。
weak_impl中有mWeak和mStrong础淤,分別對應為弱引用計數(shù)器和強引用計數(shù)器,而且在構造的時候哨苛,把弱引用計數(shù)器賦值為0鸽凶,強引用計數(shù)器賦值為另一個常量,因為理論上來說建峭,弱引用計數(shù)器值大于強引用計數(shù)器玻侥。
到目前為止還沒有看到createWeak,它定義在RefBase中迹缀,查看其實現(xiàn):
createWeak先增加了mRefs的弱引用計數(shù)值使碾,然后返回這個值蜜徽。如果還有其它wp指向它,弱引用計數(shù)值繼續(xù)增加
這個mRefs值被RefBase(object角色)和wp同時引用著票摇,mRefs在RefBase構造時被創(chuàng)建拘鞋,wp通過調用createWeak方法得到mRefs, 它們之間的關系如下:
弱指針看起來很復雜矢门,但和強指針相比盆色,只有一點不同,sp的計數(shù)器是int值祟剔,但wp的計數(shù)器是由weakref_impl管理隔躲。
如果有sp指向這個對象呢?
代碼也比較簡單物延,sp指向此對象時宣旱,需要增加弱引用計數(shù)值,也要增加強引用計數(shù)值叛薯。因為強引用計數(shù)值在初始化的時候被賦值為常量浑吟,如果是第一次,還需要加這個常量值耗溜,以保證強引用計數(shù)值從0開始组力。
接下來我們看對象什么時候會被釋放:
當減少強引用計數(shù)的時候,先減少強引用計數(shù)值抖拴,如果強引用計數(shù)值已經(jīng)為0燎字,則刪除對象自己,即RefBase阿宅,同時還要減少弱引用計數(shù)值候衍,查看減少弱引用計數(shù)的方法:
此函數(shù)分成兩個部分看,上述部分比較簡單家夺,只是減少弱引用計數(shù)即可脱柱。
這部分與weakref_impl的mFlags值有關,如果弱引用計數(shù)值為0拉馋,然后根據(jù)mFlags值榨为,如果weakref_impl它的mStrong值是常量或者其它情況,分別刪除 impl-mBase或者impl煌茴,這里就是釋放weakref_impl的地方随闺。
為什么不在RefBase被釋放的時候釋放weakref_impl呢?因為做不到蔓腐,當強引用計數(shù)值為0的時候矩乐,弱引用計數(shù)器往往不為0,所以RefBase的析構函數(shù)無法生效。