美文网首页
自动释放池

自动释放池

作者: 痴人会说梦 | 来源:发表于2018-12-12 00:17 被阅读2次
  • 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操作

相关文章

网友评论

      本文标题:自动释放池

      本文链接:https://www.haomeiwen.com/subject/iemyhqtx.html