apr HashTable源码阅读笔记

问题笔记

hash算法

源码里默认使用time33算法,在创建时可自定义算法。

array的结构

数组中每个元素都是一个指针,指向一个条目链表。以hash值和max与运算结果作为索引。当条目数量大于max时会对数组扩展,装填因子最大为1。

对源码主要的几个函数做注释笔记,其他略过了。

数据结构

struct apr_hash_t {
    apr_pool_t          *pool;//使用的内存池
    apr_hash_entry_t   **array;//条目数组
    apr_hash_index_t     iterator;  //迭代器
    unsigned int         count, max, seed;//count条目数量,max最大条目数量,seed种子。
    apr_hashfunc_t       hash_func;//自定义的hash计算方法
    apr_hash_entry_t    *free;//废弃的条目链表,创建条目时先从这个链表获取一个条目。
};
struct apr_hash_entry_t {
    apr_hash_entry_t *next;//下一个条目
    unsigned int      hash;//hash值
    const void       *key;//key首地址
    apr_ssize_t       klen;//key长度
    const void       *val;//value首地址
};
struct apr_hash_index_t {
    apr_hash_t         *ht;//遍历的hashtable
    apr_hash_entry_t   *this, *next;//this当前条目,next下一个条目。
    unsigned int        index;//当前的索引
};

find_entry

查找一个条目的实现

static apr_hash_entry_t **find_entry(apr_hash_t *ht,
                                     const void *key,
                                     apr_ssize_t klen,
                                     const void *val)
{
    apr_hash_entry_t **hep, *he;
    unsigned int hash;

    //计算hash值
    if (ht->hash_func)
        hash = ht->hash_func(key, &klen);
    else
        hash = hashfunc_default(key, &klen, ht->seed);

    //遍历ht查找hash,key,klen三值相等的条目。
    for (hep = &ht->array[hash & ht->max], he = *hep;
         he; hep = &he->next, he = *hep) {
        if (he->hash == hash
            && he->klen == klen
            && memcmp(he->key, key, klen) == 0)
            break;
    }

    //he!=NULL时找到满足的条目,val==null时表示查找。
    if (he || !val)
        return hep;

    //添加val!=null && he==null的条目。
    //先从free中获取实例,没有就从pool中申请内存。
    if ((he = ht->free) != NULL)
        ht->free = he->next;
    else
        he = apr_palloc(ht->pool, sizeof(*he));
    he->next = NULL;
    he->hash = hash;
    he->key  = key;
    he->klen = klen;
    he->val  = val;
    *hep = he;
    ht->count++;
    return hep;
}

Get

APR_DECLARE(void *) apr_hash_get(apr_hash_t *ht,
                                 const void *key,
                                 apr_ssize_t klen)
{
    apr_hash_entry_t *he;
    //val输入NULL表示查找
    he = *find_entry(ht, key, klen, NULL);
    if (he)
        return (void *)he->val;
    else
        return NULL;
}

Set

APR_DECLARE(void) apr_hash_set(apr_hash_t *ht,
                               const void *key,
                               apr_ssize_t klen,
                               const void *val)
{
    apr_hash_entry_t **hep;
    //查找条目,如果不存在则会添加一个。
    hep = find_entry(ht, key, klen, val);
    if (*hep) {
        //val为NULL删除条目
        if (!val) {
            apr_hash_entry_t *old = *hep;
            *hep = (*hep)->next;
            old->next = ht->free;
            ht->free = old;
            --ht->count;
        }
        else {
            //替换value的值
            (*hep)->val = val;
            //条目数量大于max则扩展hashtable大小
            if (ht->count > ht->max) {
                expand_array(ht);
            }
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值