Objective-C RunTime 学习笔记 之 AutoReleasPool
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对象, }
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)。
无论遇到什么困难、一往直前