AutoreleasePool 重新梳理

AutoreleasePool 是一個(gè)抽象概念,并沒有實(shí)際結(jié)構(gòu),真實(shí)的結(jié)構(gòu)是一個(gè)雙向鏈表『AutoreleasePoolPage』,由C++實(shí)現(xiàn)。

1.數(shù)據(jù)結(jié)構(gòu)

其數(shù)據(jù)結(jié)構(gòu)如下:

class AutoreleasePoolPage 
{

#define POOL_SENTINEL nil
    static pthread_key_t const key = AUTORELEASE_POOL_KEY;
    static uint8_t const SCRIBBLE = 0xA3;  // 0xA3A3A3A3 after releasing
    static size_t const SIZE = 
#if PROTECT_AUTORELEASEPOOL
        PAGE_MAX_SIZE;  // must be multiple of vm page size
#else
        PAGE_MAX_SIZE;  // size and alignment, power of 2
#endif
    static size_t const COUNT = SIZE / sizeof(id);

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

成員變量說明:

next:游標(biāo),一直指向最新入棧的autorelease對象的下一個(gè)位置。

key:TLS技術(shù),既Thread Local Storage(TLS)線程局部存儲。目的很簡單,將一塊內(nèi)存作為某個(gè)線程專有的存儲,以key-value的形式進(jìn)行讀寫。AutoreleasePoolPage將這塊區(qū)域用作存儲最新的Page,既hotPage。

SIZE:單個(gè)page的最大存儲數(shù)量,AutoreleasePoolPage以雙向鏈表的形式存在,但是單個(gè)page的存儲是有限額的,(id *) ((uint8_t *)this+SIZE)。

thread:當(dāng)前線程pthread_self()

2.push和pop

當(dāng)我們手動調(diào)用@autoreleasePool的時(shí)候,編譯器會自動將大括號內(nèi)的所有對象標(biāo)記為autorelease前綴。AutoreleasePoolPage::autorelease((id)this)當(dāng)前對象本身作為參數(shù)入?yún)?,不過在討論對象的autorelease之前,編譯器還插入了兩個(gè)方法:

void *pool = objc_autoreleasePoolPush();
……
……
……
objc_autoreleasePoolPop(pool);

前者做了和對象的autorelease相同的事情:

static inline id *autoreleaseFast(id obj)
    {
        AutoreleasePoolPage *page = hotPage();
        if (page && !page->full()) {
            return page->add(obj);
        } else if (page) {
            return autoreleaseFullPage(obj, page);
        } else {
            return autoreleaseNoPage(obj);
        }
    }
id *add(id obj)
    {
        assert(!full());
        unprotect();
        id *ret = next;  // faster than `return next-1` because of aliasing
        *next++ = obj;
        protect();
        return ret;
    }

主要就是移動游標(biāo),并且返回當(dāng)前位置,這個(gè)返回參數(shù)的意義主要體現(xiàn)在

objc_autoreleasePoolPop(pool);的入?yún)⒅?,pool記錄著一個(gè)pool的初始位置,根據(jù)這個(gè)位置和當(dāng)前的hotPage位置,遍歷中間所有的對象,進(jìn)行釋放。并且由于雙向鏈表的結(jié)構(gòu),很容易跨page進(jìn)行遍歷。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容