如上图这杯鸡尾酒.Autoreleasepool与他有相似之处.
1.Autoreleasepool
其实就是由很多个AutoreleasePoolPage
对象组成的一个双链表.就像很多个并排的酒杯.
2.每个AutoreleasePoolPage
就像一个装着鸡尾酒的杯子,杯子+里面的酒质量有4K.
3.现在,有一个Autoreleasepool
- push()
了,就相当于拿到了一个空杯子(AutoreleasePoolPage
质量为56字节).并且加入一个栅栏..(POOL_SENTINEL
哨兵:可以理解为漂浮在鸡尾酒某颜色层分界处的栅栏,提示你一口气只能喝这么多酒...)
4.现在开始注入酒了(被标记为autorelease
的对象入栈),第一次注入了三种颜色,红、黄、蓝.目前杯子里从上到下变成了:蓝 - 黄 - 红 - 栅栏.如图.
5.现在又调用了Autoreleasepool
- push()
.又要加入一个漂浮栅栏.然后加入了颜色为,白、绿的酒(被标记为autorelease的对象入栈).那么酒杯中变成了什么呢?对了,是绿 - 白 - 栅栏 - 蓝 - 黄 - 红 - 栅栏.
6.现在开始罚你喝酒了.也就是Autoreleasepool
- pop(void *token)
..先喝了绿 - 白 - 栅栏...碰到你必须喝到的那个栅栏了..我就不能再喝了,我需要把栅栏掏出来,毕竟你喝进去一个栅栏,是要进医院的...(⚠️token是栅栏的地址!!!)
7.如果你有多个酒杯怎么办?当然是一个一个喝了,直到喝到某个酒杯里有那个你需要喝到的栅栏为止.(static inline void pop(void *token)
token
是 POOL_SENTINEL的地址
就是栅栏的位置)
8.每喝一层颜色的酒,就相当于对某个被标记为autorelease的对象做一次release.
9.酒杯喝完了就摔了(AutoreleasePoolPage
page->kill()
)
⚠️特殊情况:如果喝到某一杯的栅栏,发现这杯酒还有一半以上没有喝,就不摔掉前一个杯子,为什么呢?因为下一次加酒,当前杯子很大概率不够装,需要一个杯子,不摔上一个杯子,就节约了成本...真机智啊..其实屁用没有..
10.我现在一次要调好1000层酒怎么办?(一个page大概装(4096总质量 - 56(杯子占用质量)) / 8(指针占用质量),质量可理解为内存空间. = 505).第一步找到当前杯子,看看满不满,不满就往里加一个栅栏(POOL_SENTINEL),然后开始一层一层注入酒,当一个杯子满了,再造一个杯子..重复3.里面的逻辑.
好了,这就是我理解的Autoreleasepool简略版理解.
其实我也有个问题,就是栈是由高地址向低地址排列的,但是这里,是从低地址往高地址走...
另外有什么错误希望大家指正.