iOS - AutoreleasePoolPage 节点为空时的处理逻辑
1. 空 Page 的判断
struct AutoreleasePoolPage {
id *next; // 指向下一个可用位置
id *begin(); // 页面起始位置
bool empty() {
return next == begin(); // next 指针回到起始位置表示为空
}
// 页面的边界
id *begin() {
return (id *)(this + 1);
}
id *end() {
return (id *)((uint8_t *)this + SIZE);
}
};
2. Pop 时的处理
void pop(void *token) {
AutoreleasePoolPage *page = pageForPointer(token);
id *stop = (id *)token;
page->releaseUntil(stop);
// 如果 page 变空且不是第一个 page
if (page->empty() && !page->parent) {
// 将 page 销毁
page->kill();
}
}
3. 销毁机制
void kill() {
// 确保是在正确的线程上
assert(thread == pthread_self());
// 解除与父页面的链接
if (parent) {
parent->child = nullptr;
}
// 解除与子页面的链接
if (child) {
child->parent = nullptr;
}
delete this;
}
4. 处理流程
1. 检查是否为空
if (page->empty()) {
// 页面为空的处理
if (page->child) {
// 有子页面时不能删除
return;
}
if (!page->parent) {
// 是第一个页面时保留
return;
}
// 其他情况可以安全删除
page->kill();
}
2. 更新热页面
if (hotPage() == page) {
// 如果当前页面是热页面,需要更新
setHotPage(page->parent);
}
3. 内存回收
// 页面被销毁时
~AutoreleasePoolPage() {
// 清理工作
if (child) child->parent = parent;
if (parent) parent->child = child;
}
这种机制确保了:
- 内存的有效使用
- 避免空页面占用资源
- 保持页面链表的完整性
- 线程安全的处理