ios 自動(dòng)釋放池

什么是自動(dòng)釋放池

OC中的一種內(nèi)存自動(dòng)回收機(jī)制钩蚊,它可以延遲加入AutoreleasePool中的變量release的時(shí)機(jī)犁罩,即當(dāng)我們創(chuàng)建了一個(gè)對(duì)象,并把他加入到了自動(dòng)釋放池中時(shí)两疚,他不會(huì)立即被釋放,會(huì)等到一次runloop結(jié)束或者作用域超出{}或者超出[pool release]之后再被釋放

自動(dòng)釋放池的創(chuàng)建與銷(xiāo)毀時(shí)機(jī)
MRC:
NSAutoreleasePool *pool = [[ NSAutoreleasePool alloc]init ];//創(chuàng)建一個(gè)自動(dòng)釋放池
Person *person = [[Person alloc]init];
//調(diào)autorelease方法將對(duì)象加入到自動(dòng)釋放池
[person autorelease];
//手動(dòng)釋放自動(dòng)釋放池執(zhí)行完這行代碼是含滴,自動(dòng)釋放池會(huì)對(duì)加入他中的對(duì)象做一次release操作
[pool release];
···
自動(dòng)釋放池銷(xiāo)毀時(shí)機(jī):[pool release]代碼執(zhí)行完后.
ARC
@autoreleasepool {
    //在這個(gè){}之內(nèi)的變量默認(rèn)被添加到自動(dòng)釋放池
    Person *p = [[Person alloc] init];
}//除了這個(gè)括號(hào)诱渤,p被釋放
Autorelease實(shí)現(xiàn)原理

下面看一段簡(jiǎn)單的代碼

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // insert code here...
        NSLog(@"Hello, World!");
    }
    return 0;
}

然后在終端中使用clang -rewrite-objc main.m 命令將上述OC代碼重寫(xiě)成C++的實(shí)現(xiàn)
搜索main我們可以看到main函數(shù)的實(shí)現(xiàn)重寫(xiě)成了如下代碼:

int main(int argc, const char * argv[]) {
    /* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool; 

        NSLog((NSString *)&__NSConstantStringImpl__var_folders_49_sdbnp0nd07q4m_sh4_gw52r40000gn_T_main_9e48ee_mi_0);
    }
    return 0;
}

通過(guò)對(duì)比可以發(fā)現(xiàn),蘋(píng)果通過(guò)聲明一個(gè)__AtAutoreleasePool類(lèi)型的局部變量
@autoreleasepool被轉(zhuǎn)轉(zhuǎn)換成__AtAutoreleasePool 結(jié)構(gòu)體類(lèi)型

struct __AtAutoreleasePool {
  __AtAutoreleasePool() {atautoreleasepoolobj = objc_autoreleasePoolPush();}
  ~__AtAutoreleasePool() {objc_autoreleasePoolPop(atautoreleasepoolobj);}
  void * atautoreleasepoolobj;
};

可以看到 __AtAutoreleasePool() 構(gòu)造函數(shù)調(diào)用objc_autoreleasePoolPush(),~__AtAutoreleasePool() 析構(gòu)函數(shù)調(diào)用 objc_autoreleasePoolPop()

objc_autoreleasePoolPush 和 objc_autoreleasePoolPop 是什么呢谈况?
在 NSObject.mm 文件中:

void *objc_autoreleasePoolPush(void) {
        return AutoreleasePoolPage::push();
    }
    
void objc_autoreleasePoolPop(void *ctxt) {
        AutoreleasePoolPage::pop(ctxt);
    }

實(shí)際上是調(diào)用AutoreleasePoolPage的push和pop兩個(gè)類(lèi)方法

首先來(lái)看一下AutoreleasePoolPage這個(gè)類(lèi)

class AutoreleasePoolPage {
        magic_t const magic;
        id *next;
        pthread_t const thread;
        AutoreleasePoolPage * const parent;
        AutoreleasePoolPage *child;
        uint32_t const depth;
        uint32_t hiwat;
    };

magic:用來(lái)校驗(yàn) AutoreleasePoolPage 的結(jié)構(gòu)是否完整勺美;
next:指向棧頂,也就是最新入棧的autorelease對(duì)象的下一個(gè)位置碑韵;
thread:指向當(dāng)前線(xiàn)程赡茸;
parent:指向父節(jié)點(diǎn)
child:指向子節(jié)點(diǎn)
depth:表示鏈表的深度,也就是鏈表節(jié)點(diǎn)的個(gè)數(shù)
hiwat:表示high water mark(最高水位標(biāo)記)

每一個(gè)AutoreleasePoolPage都是以雙鏈表的形式連接起來(lái)的


1622234d47c6c602b193cb512f160cf4.png

parent指向前一個(gè)page , child指向下一個(gè)page

push
5948f2dadd36e4ea2274e5f8ad798cca.png

一個(gè) push 操作其實(shí)就是創(chuàng)建一個(gè)新的 autoreleasepool 祝闻,對(duì)應(yīng) AutoreleasePoolPage 的具體實(shí)現(xiàn)就是往 AutoreleasePoolPage 中的 next 位置插入一個(gè) POOL_SENTINEL 占卧,并且返回插入的 POOL_SENTINEL 的內(nèi)存地址。

執(zhí)行一個(gè)具體的插入操作時(shí),分別對(duì)三種情況進(jìn)行了不同的處理:

  1. 當(dāng)前 page 存在且沒(méi)有滿(mǎn)時(shí)华蜒,直接將對(duì)象添加到當(dāng)前 page 中辙纬,即 next 指向的位置;
  2. 當(dāng)前 page 存在且已滿(mǎn)時(shí)叭喜,創(chuàng)建一個(gè)新的 page 贺拣,并將對(duì)象添加到新創(chuàng)建的 page 中;
  3. 當(dāng)前 page 不存在時(shí)捂蕴,即還沒(méi)有 page 時(shí)譬涡,創(chuàng)建第一個(gè) page ,并將對(duì)象添加到新創(chuàng)建的 page 中啥辨。

每調(diào)用一次 push 操作就會(huì)創(chuàng)建一個(gè)新的 AutoreleasePoolPage 涡匀,即往 AutoreleasePoolPage 中插入一個(gè) POOL_SENTINEL ,并且返回插入的 POOL_SENTINEL 的內(nèi)存地址委可。

pop


6667ce10c80e53c23eab2f59c98af50b.png

pop 函數(shù)的入?yún)⒕褪?push 函數(shù)的返回值渊跋,也就是 POOL_SENTINEL 的內(nèi)存地址即 pool token 。當(dāng)執(zhí)行 pop 操作時(shí)着倾,內(nèi)存地址在 pool token 之后的所有 autoreleased 對(duì)象都會(huì)被 release 拾酝。直到 pool token 所在 page 的 next 指向 pool token 為止。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末卡者,一起剝皮案震驚了整個(gè)濱河市蒿囤,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌崇决,老刑警劉巖材诽,帶你破解...
    沈念sama閱讀 217,826評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異恒傻,居然都是意外死亡脸侥,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)盈厘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)睁枕,“玉大人,你說(shuō)我怎么就攤上這事沸手⊥庥觯” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,234評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵契吉,是天一觀(guān)的道長(zhǎng)跳仿。 經(jīng)常有香客問(wèn)我滨嘱,道長(zhǎng)荧恍,這世上最難降的妖魔是什么窄坦? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,562評(píng)論 1 293
  • 正文 為了忘掉前任庸汗,我火速辦了婚禮,結(jié)果婚禮上谨究,老公的妹妹穿的比我還像新娘恩袱。我一直安慰自己,他們只是感情好胶哲,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,611評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布畔塔。 她就那樣靜靜地躺著,像睡著了一般鸯屿。 火紅的嫁衣襯著肌膚如雪澈吨。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,482評(píng)論 1 302
  • 那天寄摆,我揣著相機(jī)與錄音谅辣,去河邊找鬼。 笑死婶恼,一個(gè)胖子當(dāng)著我的面吹牛桑阶,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播勾邦,決...
    沈念sama閱讀 40,271評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼蚣录,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了眷篇?” 一聲冷哼從身側(cè)響起萎河,我...
    開(kāi)封第一講書(shū)人閱讀 39,166評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎蕉饼,沒(méi)想到半個(gè)月后虐杯,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,608評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡昧港,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,814評(píng)論 3 336
  • 正文 我和宋清朗相戀三年擎椰,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片创肥。...
    茶點(diǎn)故事閱讀 39,926評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡确憨,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出瓤的,到底是詐尸還是另有隱情,我是刑警寧澤吞歼,帶...
    沈念sama閱讀 35,644評(píng)論 5 346
  • 正文 年R本政府宣布圈膏,位于F島的核電站,受9級(jí)特大地震影響篙骡,放射性物質(zhì)發(fā)生泄漏稽坤。R本人自食惡果不足惜丈甸,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,249評(píng)論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望尿褪。 院中可真熱鬧睦擂,春花似錦、人聲如沸杖玲。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,866評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)摆马。三九已至臼闻,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間囤采,已是汗流浹背述呐。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,991評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留蕉毯,地道東北人乓搬。 一個(gè)月前我還...
    沈念sama閱讀 48,063評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像代虾,于是被迫代替她去往敵國(guó)和親进肯。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,871評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容