Skip to content

Commit

Permalink
refactor(hash): add two fast-call functions
Browse files Browse the repository at this point in the history
  • Loading branch information
Water-Melon committed Feb 9, 2024
1 parent 9b46aaa commit 4aa804a
Show file tree
Hide file tree
Showing 8 changed files with 384 additions and 85 deletions.
50 changes: 32 additions & 18 deletions docs/Melon Developer Guide.txt
Original file line number Diff line number Diff line change
Expand Up @@ -207,8 +207,8 @@ Their definitions can be found in melon/include/mln_types.h.
hash_pool_free_handler pool_free;
hash_calc_handler hash;
hash_cmp_handler cmp;
hash_free_handler free_key;
hash_free_handler free_val;
hash_free_handler key_freer;
hash_free_handler val_freer;
mln_u64_t len_base;
mln_u32_t expandable:1;
mln_u32_t calc_prime:1;
Expand All @@ -229,56 +229,70 @@ Their definitions can be found in melon/include/mln_types.h.
pool_free -- the free function of 'pool'.
hash -- is used to calculate and return a hash value to be the hash table index.
cmp -- is used to compare with two hash elements' value.
free_key and free_val -- are used to free hash element's key and value. These two pointers can be NULL.
key_freer and val_freer -- are used to free hash element's key and value. These two pointers can be NULL.
len_base -- is an ideal value as a seed to be passed to a prime generator to calculate the real hash table
length if 'calc_prime' flag is set. Otherwise it only means the length of hash table.
expandable -- is a flag to indicate whether operations
expand hash table dynamically. 0 means no, otherwise yes.
calc_prime -- is a flag to indicate whether a prime number should be calculated. This prime number can be the
length or the threshold of hash table. This calculation will take maybe more than a hundred microseconds.

a) mln_hash_t *mln_hash_new(struct mln_hash_attr *attr);
a) int mln_hash_init(mln_hash_t *h, struct mln_hash_attr *attr);
Initialize a hash table.

b) void mln_hash_free(mln_hash_t *h, mln_hash_flag_t flg);
Destroy the hash table.
If people set 'free_key' and (or) 'free_value' and the 'flg' is not M_HASH_F_NONE, this function will free
b) int mln_hash_init_fast(mln_hash_t *h, hash_calc_handler hash, hash_cmp_handler cmp, hash_free_handler key_freer,
hash_free_handler val_freer, mln_u64_t base_len, mln_u32_t expandable, mln_u32_t calc_prime);
Initialize a hash table.

c) mln_hash_t *mln_hash_new(struct mln_hash_attr *attr);
Create and initialize a hash table.

d) mln_hash_t *mln_hash_new_fast(hash_calc_handler hash, hash_cmp_handler cmp, hash_free_handler key_freer,
hash_free_handler val_freer, mln_u64_t base_len, mln_u32_t expandable, mln_u32_t calc_prime);
Create and initialize a hash table.

e) void mln_hash_free(mln_hash_t *h, mln_hash_flag_t flg);
Destroy and free the hash table.
If people set 'key_freer' and (or) 'val_freerue' and the 'flg' is not M_HASH_F_NONE, this function will free
hash element's key and (or) value at the same time.

c) void *mln_hash_search(mln_hash_t *h, void *key);
f) void mln_hash_destroy(mln_hash_t *h, mln_hash_flag_t flg);
Destroy the hash table.

g) void *mln_hash_search(mln_hash_t *h, void *key);
This interface searches the value data according to the key.

d) void *mln_hash_search_iterator(mln_hash_t *h, void *key, int **ctx);
h) void *mln_hash_search_iterator(mln_hash_t *h, void *key, int **ctx);
The same as 'mln_hash_search()', and it can keep looking for the next one whose key is matched by 'key'.
'ctx' is just an int ** variable, the initial value of '*ctx' must be NULL. If the return value is the last
matched element in the hash table, '*ctx' will be NULL.

e) int mln_hash_insert(mln_hash_t *h, void *key, void *val);
i) int mln_hash_insert(mln_hash_t *h, void *key, void *val);
It inserts a key-value into the hash table.
If malloc() cannot allocate memory, -1 will be returned.

f) void mln_hash_remove(mln_hash_t *h, void *key, mln_hash_flag_t flg);
j) void mln_hash_remove(mln_hash_t *h, void *key, mln_hash_flag_t flg);
It removes a key-value from the hash table.
If the 'free_key' and (or) 'free_value' are set and the 'flg' is not M_HASH_F_NONE, the element's key and (or)
If the 'key_freer' and (or) 'val_freerue' are set and the 'flg' is not M_HASH_F_NONE, the element's key and (or)
value will be freed at the same time.

g) int mln_hash_iterate(mln_hash_t *h, hash_iterate_handler handler, void *udata);
k) int mln_hash_iterate(mln_hash_t *h, hash_iterate_handler handler, void *udata);
This interface is used to visit the whole table and process every key-value by the handler.
The third argument of handler is the 'udata' provided by caller.

h) void *mln_hash_change_value(mln_hash_t *h, void *key, void *new_value);
l) void *mln_hash_change_value(mln_hash_t *h, void *key, void *new_value);
This interface is used to change the value that is indicated by 'key'.
The old value will be returned.

i) int mln_hash_key_exist(mln_hash_t *h, void *key);
m) int mln_hash_key_exist(mln_hash_t *h, void *key);
Test whether the 'key' is existent.

j) void mln_hash_reset(mln_hash_t *h, mln_hash_flag_t flg);
n) void mln_hash_reset(mln_hash_t *h, mln_hash_flag_t flg);
Reset hash table. It will clear all entries in 'h'.
If flg is not M_HASH_F_NONE and 'h->free_key' and (or) 'h->free_val' are (is) not NULL, all entries will free
If flg is not M_HASH_F_NONE and 'h->key_freer' and (or) 'h->val_freer' are (is) not NULL, all entries will free
their key and (or) value at the same time.

k) mln_hash_update(mln_hash_t *h, void *key, void *val);
o) mln_hash_update(mln_hash_t *h, void *key, void *val);
Replace the 'key' and 'val' to an exitent k-v entry which is located by 'key'. If k-v entry is not existent, a
new key-val entry will be created and insert into 'h'.
Note: The second and third arguments of this function are all second rank pointer variables. For getting rid
Expand Down
117 changes: 109 additions & 8 deletions docs/book/cn/hash.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ struct mln_hash_s {
hash_pool_free_handler pool_free;//内存池释放函数
hash_calc_handler hash;//计算所属桶的钩子函数
hash_cmp_handler cmp;//同一桶内链表节点比较函数
hash_free_handler free_key;//key释放函数
hash_free_handler free_val;//value释放函数
hash_free_handler key_freer;//key释放函数
hash_free_handler val_freer;//value释放函数
mln_hash_mgr_t *tbl;//桶
mln_u64_t len;//桶长
mln_u32_t nr_nodes;//表项数
Expand All @@ -44,6 +44,66 @@ struct mln_hash_s {



#### mln_hash_init

```c
int mln_hash_init(mln_hash_t *h, struct mln_hash_attr *attr);

struct mln_hash_attr {
void *pool; //内存池
hash_pool_alloc_handler pool_alloc;//内存池分配函数
hash_pool_free_handler pool_free;//内存池释放函数
hash_calc_handler hash; //计算所属桶的钩子函数
hash_cmp_handler cmp; //同一桶内链表节点比较函数
hash_free_handler key_freer; //key释放函数
hash_free_handler val_freer; //value释放函数
mln_u64_t len_base; //建议桶长
mln_u32_t expandable:1; //是否自动扩展桶长
mln_u32_t calc_prime:1; //是否计算素数桶长
};

typedef mln_u64_t (*hash_calc_handler)(mln_hash_t *, void *);
typedef int (*hash_cmp_handler) (mln_hash_t *, void *, void *);
typedef void (*hash_free_handler)(void *);
typedef void *(*hash_pool_alloc_handler)(void *, mln_size_t);
typedef void (*hash_pool_free_handler)(void *);
```
描述:
本函数用于初始化哈希表结构`h`。
参数`attr`的`pool`为可选项,如果希望从内存池分配,则赋值,否则置`NULL`由`malloc`分配。即,池结构由调用方给出。
`pool_alloc`与`pool_free`为池`pool`配套的内存分配与释放的函数指针。
`key_freer`与`val_freer`也为可选参数,如果需要在表项删除时或哈希表销毁时同时释放资源,则进行设置,否则置`NULL`。释放函数参数为`key`或`value`的结构。
`hash`返回值为一64位整型偏移,且该偏移不应大于等于桶长,故应在该函数内进行取模运算。
`cmp`返回值:`0`为不相同,`非0`为相同。
哈希表支持根据元素数量自动扩张桶长,但建议谨慎对待该选项,因为桶长扩张将伴随节点迁移,会产生相应计算和时间开销,因此慎用。
哈希表桶长建议为素数,因为对素数取模会相对均匀的将元素落入不同的桶中,避免部分桶链表过长。
返回值:若成功则返回`0`,否则返回`-1`
#### mln_hash_init_fast
```c
int mln_hash_init_fast(mln_hash_t *h, hash_calc_handler hash, hash_cmp_handler cmp, hash_free_handler key_freer,
hash_free_handler val_freer, mln_u64_t base_len, mln_u32_t expandable, mln_u32_t calc_prime);
```

描述:本函数用于初始化哈希表结构`h`。参数含义与`mln_hash_init`的一致,只是放在函数参数中直接传递。

返回值:若成功则返回`0`,否则返回`-1`



#### mln_hash_new

```c
Expand All @@ -55,8 +115,8 @@ struct mln_hash_attr {
hash_pool_free_handler pool_free;//内存池释放函数
hash_calc_handler hash; //计算所属桶的钩子函数
hash_cmp_handler cmp; //同一桶内链表节点比较函数
hash_free_handler free_key; //key释放函数
hash_free_handler free_val; //value释放函数
hash_free_handler key_freer; //key释放函数
hash_free_handler val_freer; //value释放函数
mln_u64_t len_base; //建议桶长
mln_u32_t expandable:1; //是否自动扩展桶长
mln_u32_t calc_prime:1; //是否计算素数桶长
Expand All @@ -77,7 +137,7 @@ typedef void (*hash_pool_free_handler)(void *);
`pool_alloc`与`pool_free`为池`pool`配套的内存分配与释放的函数指针。
`free_key`与`free_val`也为可选参数,如果需要在表项删除时或哈希表销毁时同时释放资源,则进行设置,否则置`NULL`。释放函数参数为`key`或`value`的结构。
`key_freer`与`val_freer`也为可选参数,如果需要在表项删除时或哈希表销毁时同时释放资源,则进行设置,否则置`NULL`。释放函数参数为`key`或`value`的结构。
`hash`返回值为一64位整型偏移,且该偏移不应大于等于桶长,故应在该函数内进行取模运算。
Expand All @@ -91,6 +151,47 @@ typedef void (*hash_pool_free_handler)(void *);
#### mln_hash_new_fast
```c
mln_hash_t *mln_hash_new_fast(hash_calc_handler hash, hash_cmp_handler cmp, hash_free_handler key_freer, hash_free_handler val_freer,
mln_u64_t base_len, mln_u32_t expandable, mln_u32_t calc_prime);
```

描述:本函数用于初始化哈希表结构。参数含义与`mln_hash_new`的一致,只是使用函数参数传递。

返回值:若成功则返回哈希表结构指针,否则为`NULL`



#### mln_hash_destroy

```c
void mln_hash_destroy(mln_hash_t *h, mln_hash_flag_t flg);

typedef enum mln_hash_flag {
M_HASH_F_NONE,
M_HASH_F_VAL,
M_HASH_F_KEY,
M_HASH_F_KV
} mln_hash_flag_t;
```
描述:
销毁哈希表。
参数`flg`用于指示哈希表释放时是否释放其内`key``value`所占资源,一共分为:
- 不需要释放
- 仅释放value资源
- 仅释放key资源
- 同时释放key与value资源
返回值:无
#### mln_hash_free
```c
Expand All @@ -106,7 +207,7 @@ typedef enum mln_hash_flag {

描述:

销毁哈希表
销毁并释放哈希表

参数`flg`用于指示哈希表释放时是否释放其内`key``value`所占资源,一共分为:

Expand Down Expand Up @@ -301,8 +402,8 @@ int main(int argc, char *argv[])
hattr.pool_free = NULL;
hattr.hash = calc_handler;
hattr.cmp = cmp_handler;
hattr.free_key = NULL;
hattr.free_val = free_handler;
hattr.key_freer = NULL;
hattr.val_freer = free_handler;
hattr.len_base = 97;
hattr.expandable = 0;
hattr.calc_prime = 0;
Expand Down
Loading

0 comments on commit 4aa804a

Please sign in to comment.