- AutoReleasePool的实现原理?
- AutoReleasePool为什么可以嵌套调用?
自动释放池
- 是以栈为节点通过双向链表的形式结合而成的
- 是和线程一一对应的
通过clang编译器查看@autoreleasepool{}
{
__AtAutoreleasePool __autoreleasepool;
...
}
__AtAutoreleasePool 又是什么?查看编译后的结构
struct __AtAutoreleasePool {
//// 构造函数,在创建结构体的时候调用
__AtAutoreleasePool() {atautoreleasepoolobj = objc_autoreleasePoolPush();}
//// 析构函数,在结构体销毁的时候调用
~__AtAutoreleasePool() {objc_autoreleasePoolPop(atautoreleasepoolobj);}
void * atautoreleasepoolobj;
};
__AtAutoreleasePool是一个结构体,所以创建时会调用其构造函数__AtAutoreleasePool(),当离开其作用域后,会调用其析构函数~__AtAutoreleasePool()
查看objc源码得到objc_autoreleasePoolPush和objc_autoreleasePoolPop的实现
void *
objc_autoreleasePoolPush(void)
{
return AutoreleasePoolPage::push();
}
void
objc_autoreleasePoolPop(void *ctxt)
{
AutoreleasePoolPage::pop(ctxt);
}
即相当于
objc_autoreleasePoolPush(void)
....{}中的代码
objc_autoreleasePoolPop(void *ctxt)
那么其实可以看出自动释放池是由AutoreleasePoolPage实现的
通过objc源码查看其数据结构,它是一个c++的class
class AutoreleasePoolPage {
....
magic_t const magic; //用来校验 AutoreleasePoolPage 的结构是否完整
id *next;//指向最新添加的 autoreleased 对象的下一个位置,初始化时指向 begin()
pthread_t const thread;//指向当前线程
AutoreleasePoolPage * const parent;//指向父结点,第一个结点的 parent 值为 nil
AutoreleasePoolPage *child;//指向子结点,最后一个结点的 child 值为 nil
uint32_t const depth;//代表深度,从 0 开始,往后递增 1
uint32_t hiwat;//代表 high water mark
...
}
每个AutoreleasePoolPage对象占用4096字节内存,除了用来存放它内部的成员变量,剩下的空间用来存放autorelease对象的地址
所有的AutoreleasePoolPage对象通过双向链表的形式连接在一起
一次pop相当于一次批量的pop操作