随笔 - 119  文章 - 290  trackbacks - 0

博客搬家了哦,请移步
叫我abc

常用链接

留言簿(12)

随笔分类

我的博客

搜索

  •  

积分与排名

  • 积分 - 299381
  • 排名 - 84

最新评论

阅读排行榜

cache_flush算是这个库最糟糕的一段代码了,总共有100多行,缩进糟糕,做很多不同的工作。我就纳闷,为什么不抽些子函数出来,这样的代码基本上不具备维护价值,因为自己重写一次,比搞明白这个函数有趣多了。
由于这个函数实在太长,所以不一次全贴上来,一部分一部分的看吧。

qsort(E.cache,CACHE_SIZE,sizeof(struct cache_node),cache_node_cmp);

//----------------------------------------
static int
cache_node_cmp(
const void *a,const void *b)
{
    
const struct cache_node *ca=(const struct cache_node *)a;
    
const struct cache_node *cb=(const struct cache_node *)b;
    
if (ca->parent != cb->parent) {
        
return cb->parent - ca->parent;
    }

    
if (ca->parent == -1 ) {
        
return 0;
    }

    
return (ca->child & ~ UNSET_MASK) - (cb->child & ~UNSET_MASK);
}
首先,对 E.cache进行排序,比较子是cache_node_cmp。
return cb->parent - ca->parent ,是用 cb减去ca的,因此首先根据parent_id进行降序排序。注意,在这一比较结果中,如果ca->parent = -1,那么比较结果为正,空闲节点ca往数组右边移动;如果cb->parent = -1,那么比较结果为负,空闲节点cb还是会处在数组右边。
为什么要注意这个呢?因为本次排序的一个结果就是,那些空闲节点都集中到了cache数组的右边,只要遍历cache的过程中遇到了第一个空闲节点,那么剩下的必然都是空闲节点了。
当然要达成这个排序结果,还需要下面的这步,if (ca->parent == -1 ) {return 0;}
比较子的最后一句,在parent_id相同的情况下,按child_id升序排序。

E.cache经过排序后,呈现出以下状况:
1.根据parent_id呈降序排序,并且parent_id相同的节点紧挨在一起
2.空闲的cache节点全部都排在了数组的右边
3.parent_id相同的节点,按child_id升序排序

    while (i<CACHE_SIZE) {

        
if (parent==-1{
            
return;
        }
排序之后,就是遍历有序的cache数组。可以看到排序的效果了,当parent_id = -1的时候,就只剩下空闲的cache_node,因此可以退出遍历。

        head=&E.cache[i];
        next
=head;
        sz
=0;

        
while (next->parent == parent && i<CACHE_SIZE) {
            sz 
+= 1 - UNSET_MASK_BIT(next->child);
            
++next;
            
++i;
        }
这一段代码,是统计同一parent_id下child的数目。因为有些child_id被标记了 UNSET_MASK,因此这种cache节点就不用统计到总数中了。其中UNSET_MASK_BIT是位移操作,如果child被标记了UNSET_MASK,那么位移的结果就是1,1-1=0,也就没有统计到总数中了。

struct node *node=&E.pool[parent];
children
=node->u.n.children;
统计了parent拥有的child之后,接下来就是要把这些child记录到parent的数据结构上了。这里不得不回顾一下struct node的定义,上次看的时候,并没有探讨struct link *children是做什么的,现在可以看看link的定义
struct link {
    
int number;
    
int children[1];
}
;
这个结构就是parent用来记录其所有child_id的地方。其中number用来记录child的总数量,而children则是一个整数数组,用来记录所有的child_id。
cache_flush剩下的操作,就是把新的child_id添加到children中去,当然其中包含其他一些细节处理。这里先把这些东西交代清楚,因为其后的代码将是比较难以理解的,我仍不是十分的明白。
posted on 2008-09-15 21:34 LOGOS 阅读(2121) 评论(1)  编辑 收藏 引用

FeedBack:
# re: 垃圾收集的那点事(E) 2008-09-16 10:04 zuhd
写的不错,云风这段代码是用c实现的,读起来确实有点晦涩,作者分析的精神很赞!  回复  更多评论
  

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理