Lua5.1 三色标记gc

白色:待回收的对象

灰色:待遍历的对象

黑色:不回收的对象

主要流程:

1、从根集开始遍历

2、遍历到的白对象标灰入栈,遍历到灰色、黑色对象则跳过。

3、每次从栈中pop一个灰色对象标黑,并遍历它引用的对象(处理方式参考2)

4、直到栈为空,一次性将白色对象清理出内存。

流程特点:

第2、3步是可以分步进行的,但是要对新元素进行处理,避免遍历遗漏。

如何遍历table:

1、table要么没有被遍历到,整个被回收,要么其所有key、value最终是黑色,不会被回收

2、如果table的key、value都被设置了weak,那不用遍历了,这些key-value肯定要被回收,将table直接挂g->weak即可(table本身不回收)

如果table的key被设置了weak,这些key不需要遍历,肯定是要被回收,放白

如果table的value被设置了weak,这些value不需要遍历,和key同理

只要key被回收,整个key-value肯定是要从table中移除的,虽然不一定回收value。(value同理)

3、设置了weak的table需要标灰,但不再入栈。

   为什么不标黑,因为这样可以防止被再次被置灰入栈吗?参考<往table插入新数据>
   那么标黑会怎样?
   1) 如果是往其他table插入这个table,这个table本来就是黑色的,原逻辑啥也不干。没问题!
   2) 如果是往这个table添加元素,根据下面<往table插入新数据>,可能会被置灰入栈,
          但这其实是没必要的,因为这个table已是weak,不用遍历其元素了。
        
4、元表metatable也会被遍历到

往table插入新数据:

1、若table是白色的,不用管它,有被引用最后肯定会被遍历到,没有的话回收也是应该

2、若table是灰色的,不用管它,反正一会就遍历到它,它的新数据也会遍历到

3、若table是黑色且新数据是白色,将table置灰入栈待重新遍历。(将新数据置灰入栈也行,省去重新遍历已经遍历过的元素)

闭包(函数)如何遍历:

函数里其实是有很多对象是引用到的,比如upvalue。

需要将这些引用到的所有upvalue都遍历一下。

字符串如何回收:

线程如何回收:

线程引用的对象都在栈里,遍历栈即可

其他类型如何回收:

两种白色是啥:

https://blog.codingnow.com/2011/03/lua_gc_1.html