void *objc_autoreleasePoolPush(void)
{
return AutoreleasePoolPage::push();
}
void objc_autoreleasePoolPop(void *ctxt)
{
AutoreleasePoolPage::pop(ctxt);
}
复制代码
上面的方法看上去是对 AutoreleasePoolPage 对应静态方法 push
和 pop
的封装。bash
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
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
了解了 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
不满
hotPage
而且当前 page
已满