在Objective-C 中 AutoreleasePool 用于管理对象内存,也叫自动释放池。其中每一个AutoreleasePoolPage 内部是 Stack 方式进行管理的。
本文将以OC代码分析如何以 Stack 数据结构管理对象。
- AutoreleasePoolPage 对象创建
在存储对象的时候,起始位置是每一个A utoreleasePoolPage 对象结构体的末尾作为开始的。
return (id *)((uint8_t *)self + class_getInstanceSize(self.class));
- Stack 类实例变量说明
栈结构体中保存一个用于存储数据的指针对象 next
@interface Stack() {
@package
__unsafe_unretained id * _next;
}
- (instancetype)init { self = [super init]; if (self) { _next = [self begin]; } return self;
}
- 先push哨兵对象
哨兵对象用户判断,当next指针为哨兵对象时,一次清空一组入栈对象
- (id *)push {
return [self add:POOL_BOUNDARY];
}
-
对象实例化后,系统将对象push入栈
- (id *)add:(id)obj {
assert(!self.full);
id *newObj = _next; //先保存原来栈顶对象 *_next = obj; //将新入栈对象入栈,存入next指针位置 _next++ //next指针加1
return newObj; //返回栈顶元素的起始地址}
- (id *)add:(id)obj {
-
判断栈是否为空
next指针为底部时候则为空
- (BOOL)full {
return _next == [self end];
}
- 获取栈尾
SIZE为指定栈的预定大小
- (id *)end {
return (id *) ((uint8_t *)self + SIZE);
}
- 对象引用计数变为0时候,对象出栈
- (void)pop:(id *)stop {
while (self->_next != stop) { //while循环,当栈不为空时候
id obj = *--_next; //先next对象赋值为obj
memset((void*)_next, SCRIBBLE, sizeof(*_next)); 将next所指对象指针赋值为指定特殊地址(目的为将对象地址释放)
[obj release]; //引用计数-1
}
}
每当有对象创建或引用计数增加时,系统将对象入栈,对应代码则调用 add:(id)obj 方法,对象引用出栈,对应则调用pop方法。