AutoreleasePool的实现

AutoreleasePool的基本函数

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

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

复制代码

上面的方法看上去是对 AutoreleasePoolPage 对应静态方法 pushpop 的封装。bash

AutoreleasePoolPage

class AutoreleasePoolPage 
{
     magic_t const magic;//完整性的校验
    id *next;//保存了当前页所在的线程
    pthread_t const thread;
    AutoreleasePoolPage * const parent;
    AutoreleasePoolPage *child;
    uint32_t const depth;
    uint32_t hiwat;
}


复制代码

每个自动释放池都是由一系列的 AutoreleasePoolPage 组成的,而且每个 AutoreleasePoolPage 的大小都是 4096 字节(16 进制 0x1000)函数

双向链表

自动释放池中的 AutoreleasePoolPage 是以双向链表的形式链接起来的:ui

parent 和 child 就是用来构造双向链表的指针。

POOL_BOUNDARY (哨兵对象)

POOL_BOUNDARY只是nil的别名spa

#define POOL_BOUNDARY nil
复制代码

在每一个自动释放池初始化调用 objc_autoreleasePoolPush 的时候,都会把一个 POOL_SENTINEL push 到自动释放池的栈顶,而且返回这个 POOL_BOUNDARY 哨兵对象。线程

int main(int argc, const char * argv[]) {
    {
        void * atautoreleasepoolobj = objc_autoreleasePoolPush();

        // do whatever you want

        objc_autoreleasePoolPop(atautoreleasepoolobj);
    }
    return 0;
}
复制代码

上面的 atautoreleasepoolobj 就是一个 POOL_BOUNDARY。指针

而当方法 objc_autoreleasePoolPop 调用时,就会向自动释放池中的对象发送 release 消息,直到第一个 POOL_BOUNDARY:code

objc_autoreleasePoolPush 方法

了解了 POOL_BOUNDARY,咱们来从新回顾一下 objc_autoreleasePoolPush 方法:cdn

static inline void *push() 
    {
        id *dest;
        if (DebugPoolAllocation) {
            // Each autorelease pool starts on a new pool page.
            dest = autoreleaseNewPage(POOL_BOUNDARY);
        } else {
            dest = autoreleaseFast(POOL_BOUNDARY);
        }
        assert(dest == EMPTY_POOL_PLACEHOLDER || *dest == POOL_BOUNDARY);
        return dest;
    }
复制代码

在这里会进入一个比较关键的方法 autoreleaseFast,并传入哨兵对象 POOL_SENTINEL:对象

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);
        }
    }
复制代码

上述方法分三种状况选择不一样的代码执行:blog

  • hotPage 而且当前 page 不满
    • 调用 page->add(obj) 方法将对象添加至 AutoreleasePoolPage 的栈中
  • hotPage 而且当前 page 已满
相关文章
相关标签/搜索