阅读代码上瘾了么?又看到一份代码,觉得很符合自己的风格,就贴上来。
/* implementation of a simple hash table
* -- thread safe functions as *_safe()
* -- resolve collisions by chaining
* Direct comments, concerns, questions, bugs to:
* kulesh [squiggly] isis.poly.edu
*/
hash节点定义
struct hash_entry {
struct list_head list;
unsigned char *key;
unsigned int keylen;
};
/* a hash_table contains buckets full of hash_entries (See above).
* keycmp() is used to compare the keys of hash_entries
*/
struct hash_table {
struct hash_entry *table; //竖向的vector 容量为b
unsigned int buckets;
pthread_mutex_t *bucket_locks;//锁 容量为b
pthread_mutex_t lock;
keycmp_ptr keycmp;
/* private variables */
unsigned int __ht_i;
struct list_head *pos;
};
private域的作用是遍历用的。
锁对外界是不可见的,对于要上锁的话,库提供了__safe()函数来实现。例如insert函数
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/* insert_hash_table()
* @h: &struct hash_table hash table to insert hash_entry into
* @e: &struct hash_entry
* Description: inserts @e into @h using @e->key as key. not thread-safe.
*/
void hash_table_insert(struct hash_table *h,
struct hash_entry *e,
const unsigned char *key, unsigned int len);
/* insert_hash_table_safe()
* @h: &struct hash_table hash table to insert hash_entry into
* @e: &struct hash_entry
* @key: use key to insert the hash_entry
* @len: length of the key
* Description: inserts @e into @h using @e->key as key. thread-safe.
*/
void hash_table_insert_safe(struct hash_table *h,
struct hash_entry *e,
const unsigned char *key, unsigned int len);
请参看注释。下面代码不给出注释了。
重要接口函数如下
int hash_table_init(struct hash_table *h,
unsigned int b,
keycmp_ptr keycmp);
void hash_table_finit(struct hash_table *h);
int hash_entry_init(struct hash_entry *e,
const unsigned char *str,
unsigned int len);
void hash_entry_finit(struct hash_entry *e);
void hash_table_insert(struct hash_table *h,
struct hash_entry *e,
const unsigned char *key,
unsigned int len);
struct hash_entry *hash_table_lookup_key(const struct hash_table *h,
const unsigned char *str,
unsigned int len);
struct hash_entry *hash_table_del_key(struct hash_table *h,
const char *str,
unsigned int len);
类似于linux list实现的宏接口
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/**
* hash_entry - get the user data for this entry
* @ptr: the &struct hash_entry pointer
* @type: the type of the user data (e.g. struct my_data) embedded in this entry
* @member: the name of the hash_entry within the struct (e.g. entry)
*/
hash_entry(ptr, type, member);
/*
* @hentry: &struct hash_entry
* @htable: &struct hash_table
*/
#define hash_table_for_each(hentry, htable)
/*
* @hentry: &struct hash_entry
* @htable: &struct hash_table
* @pos: &struct list_head
* @hti: unsigned int
*/
hash_table_for_each_safe(hentry, htable, pos, hti)
个人觉得,还可以开放的接口(其实现添加了static inline),这个注释里面提到了,传递来的struct hash_entry,而不是str类型。当然传递的应该是一个有hash_entry_init生成的合法struct hash_entry。
/* same as hash_table_lookup_key() but this function takes a valid hash_entry as input.
* a valid hash_entry is the one that has key, len set appropriately. in other words, a
* hash_entry that is the output of hash_entry_init()
*/
struct hash_entry *hash_table_lookup_hash_entry(const struct hash_table *h,
const struct hash_entry *e)
源代码中给出了示例。与list实现数据域与节点域分离的原则,要引用hashtable,直接包含其即可,实现数据域与指针域的结合。
定义如下
struct myitem {
struct hash_entry entry;
unsigned char foo[32];
unsigned int bar;
};
注意作者这里为了方便,用foo保存了hash_entry中的key信息。
初始化hash_table
struct hash_table mytable;
/* initialize the hash table with 10 buckets */
hash_table_init(&mytable, 10, NULL);
tmp = (struct myitem *)malloc(sizeof(struct myitem));
/**一些初始化*/
hash_table_insert(&mytable, &tmp->entry, str, len);
遍历节点
hash_table_for_each(hentry, &mytable) {
tmp = hash_entry(hentry, struct myitem, entry);
fprintf(stdout, "key: %s[%d] (%d)\n", tmp->foo, tmp->bar,
hash_table_hash_code(&mytable, tmp->foo,
strlen(tmp->foo)));
}
别忘记了释放空间——其内部元素的分配都是malloc机制的。
/* finitialze the hash table */
hash_table_finit(&mytable);
下载代码 hashtable