1、结构

struct magic_t {
    /* 魔法 */
    static const uint32_t M0 = 0xA1A1A1A1;
#   define M1 "AUTORELEASE!"
    static const size_t M1_len = 12;
    uint32_t m[4];
/* 省略各种方法 */
#   undef M1
}; /* AutotRelease 重要:重载了new和delete运算符号,使每个Page对象固定大小 */
class AutoreleasePoolPage 
{
#define POOL_SENTINEL nil
    static pthread_key_t const key = AUTORELEASE_POOL_KEY; /* TSD __PTK_FRAMEWORK_OBJC_KEY3 */
    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 (CGS. 4096 < bytes per 80386 page >)
#endif
    static size_t const COUNT = SIZE / sizeof(id);
    magic_t const magic;
    id *next;   /* objc 对象列表指向下一个未使用的区域 */
    pthread_t const thread; /* page对应线程 */
    /* 链表结构 */
    AutoreleasePoolPage * const parent; /* 父 */
    AutoreleasePoolPage *child;         /* 子 */
    uint32_t const depth;               /* 链表深度 */
    uint32_t hiwat;
    // SIZE-sizeof(*this) bytes of contents follow
//省略各种方法
//00000哨兵分割线
//各种objc对象,
}

2、 每个线程对应一个AutoReleasePoolPage 的对象列表

2.1) 线程销毁的时候,释放AutoReleasePoolPage 以及所有对象

2.2) AutoReleasePoolPage 为C++对象,由于重载了new 和 delete 运算符,确保每一个Page分配固定大小(貌似4K)。在类的实例变量/方法列表后存储Foundation对象。而类的next 成员变量则指向下一个Foundation对象。AutoReleasePoolPage 有判断是否为空和满的成员函数,以此来判断当前线程是否新创建一个AutoReleasePool对象。没创建一个对象,都会设置parent、chilid属性,构成双向链表,而hotPage则是存储在线程的本地存储中。系统初始化时会给线程初始化钩子函数  int r __unused = pthread_key_init_np(AutoreleasePoolPage::key,  AutoreleasePoolPage::tls_dealloc); 确保在线程销毁的时候,释放AutoReleasePool, 由于hotPage存存在TLS中,并且page为双向链表,可以通过hotPage遍历整个Page俩表,确保释放Page对象。

每个oc对象发送 autorelease 消息或者使用__autorelease 修饰的时候,从当前线程取出hotPage(), 整个函数从线程本地存储中取,如果没有AutoReleasePoolPage链表则创建一个,否则取出AutoReleasePoolPage,查看是否full,如果full则创建一个新的AutoReleasePoolPage,设置parent 和 child属性, 然后设置为hotPage(存入线程中本地存储中 TLS)。

  @autoreleasepool {

    //some code

  }

所有使用 @autoreleasepool block起来的代码,都会在形成

  void *pool = AutoReleasePoolPage::push();

  //some code

  AutoReleasePoolPage::pop(pool);

3、 主线程AutoReleasePoolPage何时pop?

文档中说每个 event loop(鼠标事件、点击事件等)都会在事件的will 时 pool->push(),did时 pool->pop(void *).。OS 会在主线程的RunLoop循环注册一些列观察者,在进入时调用 void *pool = AutoReleasePoolPage::push(); ,退出时调用 AutoReleasePoolPage::pop(pool); 这样子确保每一次循环都进行pool的释放。

												

Objective-C RunTime 学习笔记 之 AutoReleasPool的更多相关文章

  1. 我的runtime学习笔记

    0.简介: OC方法不同于C语言函数,属于动态调用过程,在编译的时候并不能决定真正调用哪个函数,只有在真正运行的时候才会根据函数的名称找到对应的函数来调用. 至于其他理论上的东西不必讲太多,编程讲的就 ...

  2. runtime学习笔记

    获取属性objc_property_t * propertys = class_copyPropertyList(clazz, &outCount); 获取属性名NSString * key ...

  3. iOS Runtime学习笔记

    Associated Objects: @interface NSObject (AssociatedObject) @property (nonatomic, strong) id associat ...

  4. Objective-C学习笔记---构造函数和析构函数

    简单的讲,构造函数就是在创建一个对象的时候起到初始化的作用,对这个对象里的一些成员变量进行初始化,析构函数就是在对象被删除进行一些清理工作,也就是专门的扫尾工作,下面用代码来进行具体说明. 一.构造函 ...

  5. Objective-C RunTime 学习笔记 之 消息转发流程

    1) 当向某个对象发送消息时,先从cache(cache_t)中查找方法对象(method_t),如果找到则进行回调:否则通过查找对象的类(元类)定义中方法列表,一直追溯到NSObject, 如果找到 ...

  6. Objective-C RunTime 学习笔记 之 atomic/nonatomic 关键字

    atomic修饰的是变量/方法,对于可变对象的指针变量是安全的,内部实现加了锁,但是对可变对象本身没什么影响,不安全还是不安全.另外atomic仅仅对编译器生产的getter.setter有效,如果自 ...

  7. Objective-C RunTime 学习笔记 之 基础结构体

    1.OC 运行期常用对象结构体 基本的结构体定义 typedef objc_class Class; /* 类 */ typedef objc_object *id; /* 各种类型,只要第一个字段为 ...

  8. Flink学习笔记:Flink Runtime

    本文为<Flink大数据项目实战>学习笔记,想通过视频系统学习Flink这个最火爆的大数据计算框架的同学,推荐学习课程: Flink大数据项目实战:http://t.cn/EJtKhaz ...

  9. objc_msgSend消息传递学习笔记 – 消息转发

    该文是 objc_msgSend消息传递学习笔记 – 对象方法消息传递流程 的基础上继续探究源码,请先阅读上文. 消息转发机制(message forwarding) Objective-C 在调用对 ...

随机推荐

  1. Linux系统时间同步方法小结

    在Windwos中,系统时间的设置很简单,界面操作,通俗易懂,而且设置后,重启,关机都没关系.系统时间会自动保存在BIOS时钟里面,启动计算机的时候,系统会自动在BIOS里面取硬件时间,以保证时间的不 ...

  2. libGDX开发环境搭建-Android Studio 最新版

    http://blog.csdn.net/renwuqiangg/article/details/53088720 —————————————————————————————————————————— ...

  3. c++线程池小例子

    ThreadPool.h #ifndef __THREADPOOL_H #define __THREADPOOL_H #define HAVE_STRUCT_TIMESPEC //#include & ...

  4. Vim文档编辑

    >##一.vim重复命令       ###1.重复执行上次命令       在普通模式下`.`(小数点)表示重复上一次的命令操作       拷贝测试文件到本地目录       ```   $ ...

  5. nginx default_server的作用

    用来处理没有成功匹配server_name的请求 https://www.oschina.net/question/12_3565 https://segmentfault.com/a/1190000 ...

  6. osggeometry修改更新顶点

    osg::Geometry *geometry = geode->getDrawable()->asGeometry();geometry->setDataVariance(osg: ...

  7. ThinkPHP3.2.3中M()和D()的区别详解

    在实例化的过程中,经常使用D方法和M方法, 区别在于:M方法实例化模型无需用户为每个数据表定义模型类,如果D方法没有找到定义的模型类,则会自动调用M方法. 通俗一点说:1.M实例化参数是数据库的表名, ...

  8. nw.js---创建一个hello word的方法

    一.如果用nw.js 来开发桌面应用 首先到Nw.js中文网下载软件: https://nwjs.org.cn/download.html 下载下来进行解压就可以了,绿色的免安装的,整个目录结果是这样 ...

  9. vue动态组件切换(选项卡)

    vue的动态组件 <template :is='变量'></template> 可以通过改变变量,来改变template的替换内容.达到选项卡的功能 如果想要切换保持不重新创建 ...

  10. PHP指定时间戳/日期加一天,一年,一周,一月

    PHP指定时间戳加上1天,1周,1月,一年其实是不需要用上什么函数的!指定时间戳本身就是数字整型,我们只需要再计算1天,1周它的秒数相加即可! 博主搜索php指定时间戳加一天一年,结果许多的文章给出来 ...