summary
The core source code of freeswitch is developed based on apr library, which has good portability on different systems.
Hash table is widely used in development. The main scenario is the logic that requires high query efficiency. It is a typical data structure implementation of space for time.
Most of the underlying libraries have their own hash table implementation methods, so how to implement the hash table in the apr library, and what are the advantages and disadvantages?
Let's introduce the hash table implementation of apr library.
environment
centos: CentOS release 7.0 (Final) or above
freeswitch: v1.8.7
GCC: 4.8.5
Hash table data structure
The hash table source code file of apr library is in libs/apr directory.
libs\apr\include\apr_hash.h libs\apr\tables\apr_hash.c
The hash table structure is defined in apr_hash.c.
struct apr_hash_entry_t { apr_hash_entry_t *next; unsigned int hash; const void *key; apr_ssize_t klen; const void *val; }; struct apr_hash_index_t { apr_hash_t *ht; apr_hash_entry_t *this, *next; unsigned int index; }; struct apr_hash_t { apr_pool_t *pool; apr_hash_entry_t **array; apr_hash_index_t iterator; /* For apr_hash_first(NULL, ...) */ unsigned int count, max; apr_hashfunc_t hash_func; apr_hash_entry_t *free; /* List of recycled entries */ };
Common functions
View the source code header file libs\apr\include\apr_hash.h.
apr_hashfunc_default //Default hash function apr_hash_make //Create hash table apr_hash_make_custom //Create a hash table and customize the hash function apr_hash_copy //Copy hash table apr_hash_set //Insert a new key value pair into the hash table apr_hash_get //The hash table looks up the value corresponding to the key apr_hash_first //hash table traversal, first node apr_hash_next //hash table traversal, next node apr_hash_this //The hash table is traversed to obtain the content of the current node apr_hash_count //hash table key value pair count apr_hash_clear //Clear all key value pairs apr_hash_overlay //Merge two hash tables apr_hash_merge //Merge two hash tables and customize the conflict handling function
apr_hashfunc_default default hash function
The default hash function of the apr library hash table uses the times33 hash algorithm. The times33 algorithm is very simple, which is to multiply 33 continuously.
For string type key s, the times33 algorithm is easy to use, the calculation is fast, and the hash results are evenly distributed.
The core code is as follows:
if (*klen == APR_HASH_KEY_STRING) { for (p = key; *p; p++) { hash = hash * 33 + *p; } *klen = p - key; } else { for (p = key, i = *klen; i; i--, p++) { hash = hash * 33 + *p; } }
apr_hash_make create
The creation function of the apr library hash table.
- Allocate APR from memory pool_ hash_ T size of memory.
- Field initialization, including memory pool pointer assignment, free pointer is set to NULL, count is set to 0, and max is INITIAL_MAX (15), array pointer, array memory allocation, hash function uses apr_hashfunc_default.
apr_hash_set insert
apr library hash table, insert key value pairs.
- Find. Calculate the hash value according to the key, and find the key under the array [hash & HT - > Max] corresponding to the hash value. If the key already exists, return the current entry. If the key does not exist, get the entry from the free linked list first. Otherwise, create a new entry and return it.
- Check the obtained entry. If the incoming val value is empty, the entry will be deleted and added to the free linked list. If the incoming val value is normal, replace the val field in the entry.
- Check to expand the hash table when the count exceeds max.
- When expanding the hash table, create new_array, new_ The max size is (max * 2 + 1). Traverse the array and assign a value to new_array and switch the array.
apr_hash_get lookup
Logic of apr hash table lookup:
Calculate the hash value according to the key, and find the key under the array [hash & HT - > Max] corresponding to the hash value. If the key exists, return the val value in the current entry. NULL if the key does not exist.
apr_hash_clear clear
The logic of clearing the apr hash table:
Traverse the hash table and set the val in all entry nodes to NULL.
So, APR_ hash_ After clear, the hash table is not empty, but the val of all entry nodes is empty and the entry is placed in the free linked list.
summary
The hash table of the apr library is sufficient for most scenarios. However, there are some special scenarios to consider the possibility of problems.
The apr library hash table is not thread safe.
The hash table of apr library does not further deal with the conflict. When the length of the entry linked list under array[i] exceeds a certain threshold, some methods are used to reduce the conflict, such as capacity expansion, modifying the hash algorithm, using red black tree instead of linked list in entry, etc.
Empty as usual
Be true