weak隆檀,dealloc

weak

https://blog.csdn.net/u013378438/article/details/82790332

Runtime 維護(hù)了一個(gè) weak表,用于存儲(chǔ)指向某個(gè)對(duì)象的所有weak指針粹湃。weak表 其實(shí)是一個(gè) hash(哈希)表刚操,Key 是所指對(duì)象的地址,Value是 weak指針 的地址(這個(gè)地址的值是所指對(duì)象指針的地址)數(shù)組再芋。

SideTables 有多個(gè) SideTable hash值到 一個(gè)
SideTable 內(nèi)部有 slock 引用計(jì)數(shù)表,weak_table
weak_table 內(nèi)部有 weak_entries坚冀, hash 到 對(duì)應(yīng) weak_entry_t

1济赎、初始化時(shí):runtime 會(huì)調(diào)用 objc_initWeak函數(shù),初始化一個(gè)新的 weak指針 指向?qū)ο蟮牡刂贰?br> 2记某、添加引用時(shí):objc_initWeak函數(shù) 會(huì)調(diào)用 objc_storeWeak() 函數(shù)司训, objc_storeWeak() 的作用是更新指針指向,創(chuàng)建對(duì)應(yīng)的弱引用表液南。
3壳猜、釋放時(shí),調(diào)用 clearDeallocating函數(shù)滑凉。clearDeallocating函數(shù)首先根據(jù)對(duì)象地址獲取所有 weak指針地址的數(shù)組统扳,然后遍歷這個(gè)數(shù)組把其中的數(shù)據(jù)設(shè)為 nil喘帚,最后把這個(gè) entry 從 weak表中刪除,最后清理對(duì)象的記錄咒钟。

struct SideTable {
    // 保證原子操作的自旋鎖
    spinlock_t slock;
    // 引用計(jì)數(shù)的 hash 表
    RefcountMap refcnts;
    // weak 引用全局 hash 表
    weak_table_t weak_table;
}

struct weak_table_t {
    // 保存了所有指向指定對(duì)象的 weak 指針
    weak_entry_t *weak_entries;
    // 存儲(chǔ)空間
    size_t    num_entries;
    // 參與判斷引用計(jì)數(shù)輔助量
    uintptr_t mask;
    // hash key 最大偏移值
    uintptr_t max_hash_displacement;
};

struct weak_entry_t {
    DisguisedPtr<objc_object> referent; // 被弱引用的對(duì)象
    
    // 引用該對(duì)象的對(duì)象列表吹由,聯(lián)合。 引用個(gè)數(shù)小于4朱嘴,用inline_referrers數(shù)組倾鲫。 用個(gè)數(shù)大于4,用動(dòng)態(tài)數(shù)組weak_referrer_t *referrers
    union {
        struct {
            weak_referrer_t *referrers;                      // 弱引用該對(duì)象的對(duì)象指針地址的hash數(shù)組
            uintptr_t        out_of_line_ness : 2;           // 是否使用動(dòng)態(tài)hash數(shù)組標(biāo)記位
            uintptr_t        num_refs : PTR_MINUS_2;         // hash數(shù)組中的元素個(gè)數(shù)
            uintptr_t        mask;                           // hash數(shù)組長(zhǎng)度-1萍嬉,會(huì)參與hash計(jì)算乌昔。(注意,這里是hash數(shù)組的長(zhǎng)度壤追,而不是元素個(gè)數(shù)磕道。比如,數(shù)組長(zhǎng)度可能是64大诸,而元素個(gè)數(shù)僅存了2個(gè))素個(gè)數(shù))捅厂。
            uintptr_t        max_hash_displacement;          // 可能會(huì)發(fā)生的hash沖突的最大次數(shù),用于判斷是否出現(xiàn)了邏輯錯(cuò)誤(hash表中的沖突次數(shù)絕不會(huì)超過(guò)改值)
        };
        struct {
            // out_of_line_ness field is low bits of inline_referrers[1]
            weak_referrer_t  inline_referrers[WEAK_INLINE_COUNT];
        };
    };

    bool out_of_line() {
        return (out_of_line_ness == REFERRERS_OUT_OF_LINE);
    }

    weak_entry_t& operator=(const weak_entry_t& other) {
        memcpy(this, &other, sizeof(other));
        return *this;
    }

    weak_entry_t(objc_object *newReferent, objc_object **newReferrer)
        : referent(newReferent) // 構(gòu)造方法资柔,里面初始化了靜態(tài)數(shù)組
    {
        inline_referrers[0] = newReferrer;
        for (int i = 1; i < WEAK_INLINE_COUNT; i++) {
            inline_referrers[i] = nil;
        }
    }
};
————————————————

dealloc

1.首先調(diào)用 _objc_rootDealloc()
2.接下來(lái)調(diào)用 rootDealloc()
3.這時(shí)候會(huì)判斷是否可以被釋放焙贷,判斷的依據(jù)主要有 5 個(gè),判斷是否有以上五種情況
? NONPointer_ISA? weakly_reference ? has_assoc? has_cxx_dtor? has_sidetable_rc
4-1.如果有以上五中任意一種贿堰,將會(huì)調(diào)用 object_dispose()方法辙芍,做下一步的處理。
4-2.如果沒(méi)有之前五種情況的任意一種羹与,則可以執(zhí)行釋放操作故硅,C 函數(shù)的 free()。
5.執(zhí)行完畢纵搁。
2.object_dispose() 調(diào)用流程吃衅。
? 1.直接調(diào)用 objc_destructInstance()。
? 2.之后調(diào)用 C 函數(shù)的 free()腾誉。

3.objc_destructInstance() 調(diào)用流程
? 1.先判斷 hasCxxDtor徘层,如果有 C++ 的相關(guān)內(nèi)容,要調(diào)用 object_cxxDestruct() 利职,銷毀 C++ 相關(guān)的內(nèi)容趣效。
? 2.再判斷hasAssocitatedObjects,如果有的話猪贪,要調(diào)用object_remove_associations()跷敬, 銷毀關(guān)聯(lián)對(duì)象的一系列操作。
? 3.然后調(diào)用 clearDeallocating()热押。
? 4.執(zhí)行完畢西傀。

4.clearDeallocating() 調(diào)用流程斤寇。
? 1.先執(zhí)行 sideTable_clearDellocating()。
? 2.再執(zhí)行 weak_clear_no_lock,在這一步驟中池凄,會(huì)將指向該對(duì)象的弱引用指針置為 nil抡驼。
? 3.接下來(lái)執(zhí)行 table.refcnts.eraser(),從引用計(jì)數(shù)表中擦除該對(duì)象的引用計(jì)數(shù)肿仑。
? 4.至此為止致盟,Dealloc 的執(zhí)行流程結(jié)束。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末尤慰,一起剝皮案震驚了整個(gè)濱河市馏锡,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌伟端,老刑警劉巖杯道,帶你破解...
    沈念sama閱讀 217,542評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異责蝠,居然都是意外死亡党巾,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門霜医,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)齿拂,“玉大人,你說(shuō)我怎么就攤上這事肴敛∈鸷#” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,912評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵医男,是天一觀的道長(zhǎng)砸狞。 經(jīng)常有香客問(wèn)我,道長(zhǎng)镀梭,這世上最難降的妖魔是什么刀森? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,449評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮报账,結(jié)果婚禮上撒强,老公的妹妹穿的比我還像新娘。我一直安慰自己笙什,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,500評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布胚想。 她就那樣靜靜地躺著琐凭,像睡著了一般。 火紅的嫁衣襯著肌膚如雪浊服。 梳的紋絲不亂的頭發(fā)上统屈,一...
    開(kāi)封第一講書(shū)人閱讀 51,370評(píng)論 1 302
  • 那天胚吁,我揣著相機(jī)與錄音,去河邊找鬼愁憔。 笑死腕扶,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的吨掌。 我是一名探鬼主播半抱,決...
    沈念sama閱讀 40,193評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼膜宋!你這毒婦竟也來(lái)了窿侈?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,074評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤秋茫,失蹤者是張志新(化名)和其女友劉穎史简,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體肛著,經(jīng)...
    沈念sama閱讀 45,505評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡圆兵,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,722評(píng)論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了枢贿。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片殉农。...
    茶點(diǎn)故事閱讀 39,841評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖萨咕,靈堂內(nèi)的尸體忽然破棺而出统抬,到底是詐尸還是另有隱情,我是刑警寧澤危队,帶...
    沈念sama閱讀 35,569評(píng)論 5 345
  • 正文 年R本政府宣布聪建,位于F島的核電站,受9級(jí)特大地震影響茫陆,放射性物質(zhì)發(fā)生泄漏金麸。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,168評(píng)論 3 328
  • 文/蒙蒙 一簿盅、第九天 我趴在偏房一處隱蔽的房頂上張望挥下。 院中可真熱鬧,春花似錦桨醋、人聲如沸棚瘟。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,783評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)偎蘸。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間迷雪,已是汗流浹背限书。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,918評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留章咧,地道東北人倦西。 一個(gè)月前我還...
    沈念sama閱讀 47,962評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像赁严,于是被迫代替她去往敵國(guó)和親扰柠。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,781評(píng)論 2 354