diff --git a/docs/Melon Developer Guide.txt b/docs/Melon Developer Guide.txt index b328684c..ba5020de 100644 --- a/docs/Melon Developer Guide.txt +++ b/docs/Melon Developer Guide.txt @@ -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; @@ -229,7 +229,7 @@ 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 @@ -237,48 +237,62 @@ Their definitions can be found in melon/include/mln_types.h. 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 diff --git a/docs/book/cn/hash.md b/docs/book/cn/hash.md index 2ce2c68f..4652a075 100644 --- a/docs/book/cn/hash.md +++ b/docs/book/cn/hash.md @@ -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;//表项数 @@ -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 @@ -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; //是否计算素数桶长 @@ -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位整型偏移,且该偏移不应大于等于桶长,故应在该函数内进行取模运算。 @@ -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 @@ -106,7 +207,7 @@ typedef enum mln_hash_flag { 描述: -销毁哈希表。 +销毁并释放哈希表。 参数`flg`用于指示哈希表释放时是否释放其内`key``value`所占资源,一共分为: @@ -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; diff --git a/docs/book/en/hash.md b/docs/book/en/hash.md index 5fe03b88..bc7b65fc 100644 --- a/docs/book/en/hash.md +++ b/docs/book/en/hash.md @@ -25,8 +25,8 @@ struct mln_hash_s { hash_pool_free_handler pool_free;//free function of memory pool hash_calc_handler hash;//callback to calculate the bucket index hash_cmp_handler cmp;//comparision function for comparing nodes in the same bucket - hash_free_handler free_key;//key free function - hash_free_handler free_val;//value free function + hash_free_handler key_freer;//key free function + hash_free_handler val_freer;//value free function mln_hash_mgr_t *tbl;//buckets mln_u64_t len;//bucket length mln_u32_t nr_nodes;//number of nodes @@ -44,22 +44,82 @@ Here, we mainly focus on `len`, because when calculating the belonging bucket, t +#### 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; + hash_free_handler val_freer; + 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 *); +``` + +Description: + +This function is used to initialize the hash table structure `h`. + +The `pool` of parameter `attr` is optional. If you want to allocate from the memory pool, assign a value, otherwise set `NULL` and allocate it by `malloc`. That is, the pool structure is given by the caller. + +`pool_alloc` and `pool_free` are function pointers for memory allocation and release of the pool `pool`. + +`key_freer` and `val_freer` are also optional parameters. If you need to release resources at the same time when the table entry is removed or the hash table is destroyed, set it, otherwise set it to `NULL`. Release the structure whose function parameter is `key` or `value`. + +The return value of `hash` is a 64-bit integer offset, and the offset should not be greater than or equal to the bucket length, so the modulo operation should be performed within this function. + +`cmp` return value: `0` means different, `non-0` means the same. + +The hash table supports automatic expansion of the bucket length based on the number of elements, but it is recommended to treat this option with caution, because the bucket length expansion will be accompanied by node migration, which will cause corresponding calculation and time overhead, so use it with caution. + +It is recommended that the hash table bucket length be a prime number, because taking the modulo of a prime number will relatively evenly place elements into different buckets, preventing some bucket linked lists from being too long. + +Return value: Returns `0` if successful, otherwise returns `-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); +``` + +Description: This function is used to initialize the hash table structure `h`. The meaning of the parameters is the same as that of `mln_hash_init`, but it is passed directly as the function parameters. + +Return value: Returns `0` if successful, otherwise returns `-1` + + + #### mln_hash_new ```c mln_hash_t *mln_hash_new(struct mln_hash_attr *attr); struct mln_hash_attr { - void *pool; //memory pool, it's an option, NULL means memory pool not activated - hash_pool_alloc_handler pool_alloc;//allocation function of memory pool - hash_pool_free_handler pool_free;//free function of memory pool - hash_calc_handler hash; //callback to calculate the bucket index - hash_cmp_handler cmp; //comparision function for comparing nodes in the same bucket - hash_free_handler free_key; //key free function - hash_free_handler free_val; //value free function - mln_u64_t len_base; //recommended bucket length - mln_u32_t expandable:1; //expansion flag - mln_u32_t calc_prime:1; //prime flag for calculating bucket length as a prime number + 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; + hash_free_handler val_freer; + 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 *); @@ -73,21 +133,62 @@ Description: This function is used to initialize the hash table structure. -The `pool` of the parameter `attr` is optional. If you want to allocate from the memory pool, assign a value, otherwise set `NULL` to allocate by `malloc`. That is, the pool structure is given by the caller. +The `pool` of parameter `attr` is optional. If you want to allocate from the memory pool, assign a value, otherwise set `NULL` and allocate it by `malloc`. That is, the pool structure is given by the caller. -`pool_alloc` and `pool_free` are the function pointers for the memory allocation and release of pool `pool`. +`pool_alloc` and `pool_free` are function pointers for memory allocation and release of the pool `pool`. -`free_key` and `free_val` are also optional parameters. If the resource needs to be released when the entry is deleted or the hash table is destroyed, set it, otherwise set it to `NULL`. Frees structures whose function arguments are `key` or `value`. +`key_freer` and `val_freer` are also optional parameters. If you need to release resources at the same time when the table entry is removed or the hash table is destroyed, set it, otherwise set it to `NULL`. Release the structure whose function parameter is `key` or `value`. -The return value of `hash` is a 64-bit integer offset, and the offset should not be greater than or equal to the bucket length, so the modulo operation should be performed in this function. +The return value of `hash` is a 64-bit integer offset, and the offset should not be greater than or equal to the bucket length, so the modulo operation should be performed within this function. -`cmp` return value: `0` is not the same, `non-zero` is the same. +`cmp` return value: `0` means different, `non-0` means the same. -The hash table supports automatic expansion of the bucket length according to the number of elements, but it is recommended to treat this option with caution, because the expansion of the bucket length will accompany the node migration, which will cause corresponding calculation and time overhead, so use it with caution. +The hash table supports automatic expansion of the bucket length based on the number of elements, but it is recommended to treat this option with caution, because the bucket length expansion will be accompanied by node migration, which will cause corresponding calculation and time overhead, so use it with caution. -The bucket length of the hash table is recommended to be a prime number, because taking the modulo of the prime number will relatively evenly drop the elements into different buckets, preventing some bucket lists from being too long. +It is recommended that the hash table bucket length be a prime number, because taking the modulo of a prime number will relatively evenly place elements into different buckets, preventing some bucket linked lists from being too long. -Return value: if successful, return the hash table structure pointer, otherwise `NULL` +Return value: If successful, returns the hash table structure pointer, otherwise `NULL` + + + +#### 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); +``` + +Description: This function is used to initialize the hash table structure. The meaning of the parameters is the same as that of `mln_hash_new`, except that it is passed as function parameters. + +Return value: If successful, returns the hash table structure pointer, otherwise `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; +``` + +Description: + +Destroy the hash table. + +The parameter `flg` is used to indicate whether to release the resources occupied by the `key`value` in the hash table when it is released. It is divided into: + +- No need to release +- Only release value resources +- Only release key resources +- Release key and value resources at the same time + +Return value: None @@ -106,16 +207,16 @@ typedef enum mln_hash_flag { Description: -Destroy the hash table. +Destroy and free the hash table. The parameter `flg` is used to indicate whether to release the resources occupied by the `key`value` in the hash table when it is released. It is divided into: -- no release required -- only release value resources -- only release key resources +- No need to release +- Only release value resources +- Only release key resources - Release key and value resources at the same time -Return value: none +Return value: None @@ -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; diff --git a/include/mln_hash.h b/include/mln_hash.h index e233dad5..522e5662 100644 --- a/include/mln_hash.h +++ b/include/mln_hash.h @@ -31,8 +31,8 @@ typedef enum mln_hash_flag { struct mln_hash_attr { 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; @@ -64,8 +64,8 @@ struct mln_hash_s { mln_u64_t len; 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_u32_t nr_nodes; mln_u32_t threshold; mln_u32_t expandable:1; @@ -80,9 +80,26 @@ struct mln_hash_s { extern int mln_hash_init(mln_hash_t *h, struct mln_hash_attr *attr) __NONNULL2(1,2); +extern 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); extern void mln_hash_destroy(mln_hash_t *h, mln_hash_flag_t flg); extern mln_hash_t * mln_hash_new(struct mln_hash_attr *attr) __NONNULL1(1); +extern 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); extern void mln_hash_free(mln_hash_t *h, mln_hash_flag_t flg); extern void * diff --git a/include/mln_parser_generator.h b/include/mln_parser_generator.h index 0f0b6971..c7dddc89 100644 --- a/include/mln_parser_generator.h +++ b/include/mln_parser_generator.h @@ -514,18 +514,13 @@ MLN_FUNC(SCOPE inline, int, PREFIX_NAME##_pg_process_token, \ \ MLN_FUNC(SCOPE, int, PREFIX_NAME##_preprocess, (struct PREFIX_NAME##_preprocess_attr *attr), (attr), {\ /*Init hash table*/\ - struct mln_hash_attr hattr;\ - hattr.pool = NULL;\ - hattr.pool_alloc = NULL;\ - hattr.pool_free = NULL;\ - hattr.hash = mln_pg_map_hash_calc;\ - hattr.cmp = mln_pg_map_hash_cmp;\ - hattr.free_key = mln_pg_map_hash_free;\ - hattr.free_val = mln_pg_map_hash_free;\ - hattr.len_base = M_PG_DFL_HASHLEN;\ - hattr.expandable = 1;\ - hattr.calc_prime = 0;\ - attr->map_tbl = mln_hash_new(&hattr);\ + attr->map_tbl = mln_hash_new_fast(mln_pg_map_hash_calc, \ + mln_pg_map_hash_cmp, \ + mln_pg_map_hash_free, \ + mln_pg_map_hash_free, \ + M_PG_DFL_HASHLEN, \ + 1, \ + 0);\ if (attr->map_tbl == NULL) {\ mln_log(error, "No memory.\n");\ return -1;\ diff --git a/src/mln_hash.c b/src/mln_hash.c index 8671020b..8a5adea9 100644 --- a/src/mln_hash.c +++ b/src/mln_hash.c @@ -33,8 +33,8 @@ MLN_FUNC(, int, mln_hash_init, (mln_hash_t *h, struct mln_hash_attr *attr), (h, h->pool_free = attr->pool_free; h->hash = attr->hash; h->cmp = attr->cmp; - h->free_key = attr->free_key; - h->free_val = attr->free_val; + h->key_freer = attr->key_freer; + h->val_freer = attr->val_freer; h->len = attr->calc_prime? mln_prime_generate(attr->len_base): attr->len_base; if (h->pool != NULL) { h->tbl = (mln_hash_mgr_t *)h->pool_alloc(h->pool, h->len*sizeof(mln_hash_mgr_t)); @@ -63,6 +63,41 @@ MLN_FUNC(, int, mln_hash_init, (mln_hash_t *h, struct mln_hash_attr *attr), (h, return 0; }) +MLN_FUNC(, 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, hash, cmp, key_freer, val_freer, base_len, expandable, calc_prime), \ +{ + h->pool = NULL; + h->pool_alloc = NULL; + h->pool_free = NULL; + h->hash = hash; + h->cmp = cmp; + h->key_freer = key_freer; + h->val_freer = val_freer; + h->len = calc_prime? mln_prime_generate(base_len): base_len; + h->tbl = (mln_hash_mgr_t *)calloc(h->len, sizeof(mln_hash_mgr_t)); + if (h->tbl == NULL) return -1; + + h->nr_nodes = 0; + h->threshold = calc_prime? mln_prime_generate(h->len << 1): h->len << 1; + h->expandable = expandable; + h->calc_prime = calc_prime; + if (h->len == 0 || \ + h->hash == NULL || \ + h->cmp == NULL) + { + if (h->pool != NULL) { + h->pool_free(h->tbl); + } else { + free(h->tbl); + } + return -1; + } + h->iter = h->iter_head = h->iter_tail = NULL; + return 0; +}) + MLN_FUNC(, mln_hash_t *, mln_hash_new, (struct mln_hash_attr *attr), (attr), { mln_hash_t *h; if (attr->pool != NULL) { @@ -77,8 +112,8 @@ MLN_FUNC(, mln_hash_t *, mln_hash_new, (struct mln_hash_attr *attr), (attr), { h->pool_free = attr->pool_free; h->hash = attr->hash; h->cmp = attr->cmp; - h->free_key = attr->free_key; - h->free_val = attr->free_val; + h->key_freer = attr->key_freer; + h->val_freer = attr->val_freer; h->len = attr->calc_prime? mln_prime_generate(attr->len_base): attr->len_base; if (h->pool != NULL) { h->tbl = (mln_hash_mgr_t *)h->pool_alloc(h->pool, h->len*sizeof(mln_hash_mgr_t)); @@ -112,6 +147,42 @@ MLN_FUNC(, mln_hash_t *, mln_hash_new, (struct mln_hash_attr *attr), (attr), { return h; }) +MLN_FUNC(, 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), \ + (hash, cmp, key_freer, val_freer, base_len, expandable, calc_prime), \ +{ + mln_hash_t *h; + + h = (mln_hash_t *)malloc(sizeof(mln_hash_t)); + if (h == NULL) return NULL; + + h->pool = NULL; + h->pool_alloc = NULL; + h->pool_free = NULL; + h->hash = hash; + h->cmp = cmp; + h->key_freer = key_freer; + h->val_freer = val_freer; + h->len = calc_prime? mln_prime_generate(base_len): base_len; + h->tbl = (mln_hash_mgr_t *)calloc(h->len, sizeof(mln_hash_mgr_t)); + if (h->tbl == NULL) { + free(h); + return NULL; + } + h->nr_nodes = 0; + h->threshold = calc_prime? mln_prime_generate(h->len << 1): h->len << 1; + h->expandable = expandable; + h->calc_prime = calc_prime; + if (h->len == 0 || h->hash == NULL || h->cmp == NULL) { + free(h->tbl); + free(h); + return NULL; + } + h->iter = h->iter_head = h->iter_tail = NULL; + return h; +}) + MLN_FUNC_VOID(, void, mln_hash_destroy, (mln_hash_t *h, mln_hash_flag_t flg), (h, flg), { if (h == NULL) return; @@ -369,18 +440,18 @@ MLN_FUNC_VOID(static inline, void, mln_hash_entry_free, \ if (he == NULL) return; switch (flg) { case M_HASH_F_VAL: - if (h->free_val != NULL) - h->free_val(he->val); + if (h->val_freer != NULL) + h->val_freer(he->val); break; case M_HASH_F_KEY: - if (h->free_key != NULL) - h->free_key(he->key); + if (h->key_freer != NULL) + h->key_freer(he->key); break; case M_HASH_F_KV: - if (h->free_val != NULL) - h->free_val(he->val); - if (h->free_key != NULL) - h->free_key(he->key); + if (h->val_freer != NULL) + h->val_freer(he->val); + if (h->key_freer != NULL) + h->key_freer(he->key); break; default: break; } diff --git a/src/mln_http.c b/src/mln_http.c index 4e89b398..0248da08 100644 --- a/src/mln_http.c +++ b/src/mln_http.c @@ -895,8 +895,8 @@ MLN_FUNC(, mln_http_t *, mln_http_init, \ hattr.pool_free = (hash_pool_free_handler)mln_alloc_free; hattr.hash = mln_http_hash_calc; hattr.cmp = mln_http_hash_cmp; - hattr.free_key = mln_http_hash_free; - hattr.free_val = mln_http_hash_free; + hattr.key_freer = mln_http_hash_free; + hattr.val_freer = mln_http_hash_free; hattr.len_base = M_HTTP_HASH_LEN; hattr.expandable = 0; hattr.calc_prime = 0; diff --git a/src/mln_websocket.c b/src/mln_websocket.c index e12a8536..e6b047ac 100644 --- a/src/mln_websocket.c +++ b/src/mln_websocket.c @@ -31,8 +31,8 @@ MLN_FUNC(, int, mln_websocket_init, (mln_websocket_t *ws, mln_http_t *http), (ws hattr.pool_free = (hash_pool_free_handler)mln_alloc_free; hattr.hash = mln_websocket_hash_calc; hattr.cmp = mln_websocket_hash_cmp; - hattr.free_key = mln_websocket_hash_free; - hattr.free_val = mln_websocket_hash_free; + hattr.key_freer = mln_websocket_hash_free; + hattr.val_freer = mln_websocket_hash_free; hattr.len_base = 37; hattr.expandable = 0; hattr.calc_prime = 0;