AutoreleasePool 中对象管理栈应用简介

155 阅读1分钟

在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; //返回栈顶元素的起始地址}
  • 判断栈是否为空

     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方法。