2007年11月1日星期四

C里面实现GC的难点

上班真麻烦。

白天只能上班的时候偷偷的写点伪代码来打草稿。目前的模型基本上是基于C里面最常用的OO方式。当然,指针是不能暴露出来了。目前的思路是:

GC处于等待状态,除非被唤醒。
GC被唤醒仅仅因为需要GC并且Mem Reader Count == 0;
唤醒后挂起所有线程。(这个在嵌入式平台上只要关闭所有中断,但是别的系统还没想好,一个可接受的实现是借用目前GC用来保护读写锁的信号量互斥)。
MASK & CLEAN
继续等待。

GC有个crit和leave,crit里面会增加Reader计数。leave减之。
当某个类的实现需要解开引用去拿指针的时候,必须调用crit之后才能使用。防止指针被移动(GC的实现会对指针作改变)。

比较麻烦的是栈上的引用,C的栈是我无法控制的,不可能象虚拟机实现去遍历栈获取可用的引用,另外也不想用户通过deleteRef 这样的方式,因为这样就牺牲了很大的GC的好处。容易Memroy leak. 目前想的是一个比较低效的做法:
每个成员函数进入需要调用frame_enter,返回需要frame_leave.

frame代表当前的函数框架,同样很多frames表现为Stack形式。Frame里面自动存储以下引用:
new_object返回引用。
某个其他满足此规范的函数返回的引用。
当函数返回时:
如果有返回值是一个对象的引用,则添加到上一层调用者Frame的引用表。
弹出当前的frame.
GC在扫引用的时候,frame就代表了传统意义的栈。

难点又来了:线程怎么办。。
一般来说,一个线程就有一个Frame Stack.
但是必须由当前线程的环境ENV概念(比如JNI的JNIEnv)
目前比较麻烦的是如何生成ENV,如果类似与JNI的话,就需要用户主动ATTACH到线程。并且,所有的函数需要ENV参数。烦的很!如果把这ENV们存储到一个Thread ID的hash表里面倒是也行。根具当前Thread ID取查询对应ENV, 但是每次的上锁访问Hash表查询也是一个比较慢的办法。

如果使用者用起来的比较麻烦,这个也就失去了意义,说不定最后还是返回到DeleteRef这样的机制更容易让人接受。烦的很。

全局的引用时必须手动deleteRef的,相当于这个框架和外界并用的接口。

0 COMMENTS: