hmap理解



     hash map数据结构在openvswitch代码中经常用到。每个hmap_node 中包括哈希值和指针next,具有相似hash值得节点会通过next域串联起来(注意:所有hash值都是不同的,只是在一个桶中链接的结点hash值具有某种可追踪性or局部性,即与mask相掩之后值相同),可以缩短查找时间。容器hmap中buckets是一个pointer to struct hmap_node * , 可以理解为一个 指针数组,其中每一项指向具有某一块hash值得链表头结点。mask域的存在使得可以直接得到对应的桶,即 buckets[node->hash & hmap->mask] ;在一个映射表rehash(可以理解为超过了装载因子限制,需要重新分配空间)之前,可以达到的最大节点数是 mask*2+1 (loadfactor是0.5 ?).
hmap理解_第1张图片

/* A hash map node, to be embedded inside the data structure being mapped. */
struct hmap_node {
    size_t hash;                /* Hash value. */
    struct hmap_node *next;     /* Next in linked list. */
};

/* A hash map. */
struct hmap {
    struct hmap_node **buckets; /* Must point to 'one' iff 'mask' == 0. */
    struct hmap_node *one;
    size_t mask;
    size_t n;
};

关于hmap的操作都在hamp.h/c 中(链表操作):
1.  快速插入具有哈希值为hash的 node (头插),不会进行扩容操作。
static inline void
hmap_insert_fast(struct hmap *hmap, struct hmap_node *node, size_t hash)
{
    struct hmap_node **bucket = &hmap->buckets[hash & hmap->mask];
    node->hash = hash;
    node->next = *bucket;
    *bucket = node;
    hmap->n++;
}

2.同上,但是会扩容,为了优化查询性能。
static inline void
hmap_insert(struct hmap *hmap, struct hmap_node *node, size_t hash){
    hmap_insert_fast(hmap, node, hash);
    if (hmap->n / 2 > hmap->mask) {
        hmap_expand(hmap);
    }
}
-->
void  hmap_expand(struct hmap *hmap){
    size_t new_mask = calc_mask(hmap->n);    //更新掩码,没看懂。
    if (new_mask > hmap->mask) {
        COVERAGE_INC(hmap_expand);
        resize(hmap, new_mask);
    }
}


3.移除某个结点
static inline void hmap_remove(struct hmap *hmap, struct hmap_node *node){
    struct hmap_node **bucket = &hmap->buckets[node->hash & hmap->mask];
    while (*bucket != node) {
        bucket = &(*bucket)->next;
    }
    *bucket = node->next;  //最终*bucket指向 node结点,怎么感觉和前面脱节了??
    hmap->n--;
}

4.并且由hmap衍生出的具体结构体也很多,比如字符串到无符号整型的映射
struct simap {
    struct hmap map;            /* Contains "struct simap_node"s. */
};

struct simap_node {
    struct hmap_node node;      /* In struct simap's 'map' hmap. */
    char *name;
    unsigned int data;
};












你可能感兴趣的:(OVS源码阅读)