1
void*
2
gc_malloc(size_t sz,void *parent,void (*finalizer)(void *))
3

{
4
void *ret=my_malloc(sz);
5
int id=map_id(ret);
6
E.pool[id].u.n.finalizer=finalizer;
7
if (parent)
{
8
gc_link(parent,0,ret);
9
}
10
else
{
11
stack_push(id);
12
}
13
return ret;
14
}
void*2
gc_malloc(size_t sz,void *parent,void (*finalizer)(void *))3


{4
void *ret=my_malloc(sz);5
int id=map_id(ret);6
E.pool[id].u.n.finalizer=finalizer;7

if (parent)
{8
gc_link(parent,0,ret);9
}10

else
{11
stack_push(id);12
}13
return ret;14
}首先,第4行分配了指定大小的內存。
然后是第5行map_id(ret),這是什么呢?先不深究其實現,我簡單的說說他所做的工作:
因為這是一個gc庫,所以本質工作就是管理內存,因此將分配出來的新內存記錄到一個容器中以便于以后的管理。yfgc管理采用的容器是一個數組。分配新內存后,在數組容器中找到一個空閑的位置,將內存指針記錄到該位置上。
不過光做這個還是不夠的,以后要是再遇上這塊內存,怎么知道它被記錄在數組容器的哪個位置上呢?雖然遍歷查找也可以,不過我想應該沒人會那么做吧。源碼采用了hash_map,將這塊內存的指針map到數組的索引上。
綜上,map_id(ret)大體這么做了
pool[id].mem = ret;
map[ ret ] = id;總而言之,id就是內存在容器中的索引啦。從第6行可以看出,E.pool就是這個管理容器了。這句用來設置內存的析構回調函數。
E.pool是一個node結構數組,現在來看看node的定義,簡單起見,我暫時去掉了不相關的東西:
1
struct node
{
2
union
{
3
struct
{
4
void * mem;
5
struct link *children;
6
void (*finalizer)(void *);
7
} n;
8
} u;
9
};
mem和finalizer很眼熟對吧,因為剛剛才看過。children可以先不管,不過從名稱看來,是管理父子關系,更準確的說是依賴關系的東東了。
struct node
{2

union
{3

struct
{4
void * mem;5
struct link *children;6
void (*finalizer)(void *);7
} n;8
} u;9
};OK,現在來看看7、8、9行,出現了gc_link,我記得這是一個public接口,用來管理兩塊內存之間的依賴關系的?,F在,因為傳入了parent實參,要在新分配的內存和parent之間建立依賴關系,所以調用了gc_link。
我想else部分可以先不管,只要記住出現了stack_push即可?,F在非常好奇,gc_link是如何建立這一依賴關系的,采用了何種數據結構,所以接下來就要去看看gc_link的實現了。


