资源的管理及加解锁
周末我们遇到一个问题。运行时的资源需要统一的管理,资源本身是用垃圾回收的方法管理的。但是,有时候资源需要 lock 住,发生 gc 的时候绝对不能清理掉。我们最初的想法是,把加栽的资源 lock 的时候挂到一个 lock 链上,unlock 的时候取下来。
但是资源这个东西经常被重复使用,而我们又没有引用记数,导致 unlock 的操作无法正确工作。
最容易想到的解决的方法是给对象加上引用计数,但是直觉告诉我,肯定有方法避免。因为使用 gc ,原本就想避免繁琐的加减引用的过程。还需要给资源接口添加引用控制的方法,(我们的设计里,基类是没有引用控制的方法的)而且不是每个对象都需要保存引用计数这个变量。如果引用计数不放在对象上,就只能放在链表节点上,我们还需要提供一个资源对象映射到 lock 链表节点的途径。显然,去使用一个代价昂贵的 map 非常的傻。
最后使用的解决方案是这样的:
使用一个指针数组,每次 lock 或 unlock 一个资源对象指针的时候,直接把地址压进数组里。当然,因为是指针,我们可以用一个比较 trick 的方法区分是 lock 还是 unlock 。那就是 unlock 的时候把地址加一。因为一般对象地址都是 dword 对齐的。
因为我们可以根据 lock 和 unlock 的次数来知道实际 lock 的对象有多少个,当 lock 次数和 unlock 次数相等的时候,就把数组清空即可。在实际应用中,往往也可以调用 unlock_all 的方法全部清空(通常是在一帧图片渲染完毕后)。
当数组的大小远大于实际被 lock 的对象数量的时候,我们认为数据冗余过多。这个时候对数组先排序,然后可以用一个简单的一次扫描的算法,把对相同地址的 lock 和 unlock 操作合并了。这个整理过程被调用的频率很低,同时也可以快速的完成。
Comments
Posted by: 西游学员 | (2) December 3, 2014 04:19 AM
Posted by: gaser | (1) February 25, 2011 10:36 PM