hashtab.h 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430
  1. /*
  2. * Asterisk -- An open source telephony toolkit.
  3. *
  4. * Copyright (C) 2006, Digium, Inc.
  5. *
  6. * Steve Murphy <murf@digium.com>
  7. *
  8. * See http://www.asterisk.org for more information about
  9. * the Asterisk project. Please do not directly contact
  10. * any of the maintainers of this project for assistance;
  11. * the project provides a web site, mailing lists and IRC
  12. * channels for your use.
  13. *
  14. * This program is free software, distributed under the terms of
  15. * the GNU General Public License Version 2. See the LICENSE file
  16. * at the top of the source tree.
  17. */
  18. #ifndef _ASTERISK_HASHTAB_H_
  19. #define _ASTERISK_HASHTAB_H_
  20. #define __USE_UNIX98 1 /* to get the MUTEX_RECURSIVE stuff */
  21. /*! \file
  22. * \brief Generic (perhaps overly so) hashtable implementation
  23. * \ref AstHash
  24. */
  25. #include "asterisk/lock.h"
  26. /*! \page AstHash Hash Table support in Asterisk
  27. A hash table is a structure that allows for an exact-match search
  28. in O(1) (or close to that) time.
  29. The method: given: a set of {key,val} pairs. (at a minimum).
  30. given: a hash function, which, given a key,
  31. will return an integer. Ideally, each key in the
  32. set will have its own unique associated hash value.
  33. This hash number will index into an array. "buckets"
  34. are what the elements of this array are called. To
  35. handle possible collisions in hash values, buckets can form a list.
  36. The key for a value must be contained in the value, or we won't
  37. be able to find it in the bucket list.
  38. This implementation is pretty generic, because:
  39. 1. The value and key are expected to be in a structure
  40. (along with other data, perhaps) and it's address is a "void *".
  41. 2. The pointer to a compare function must be passed in at the
  42. time of creation, and is stored in the hashtable.
  43. 3. The pointer to a resize function, which returns 1 if the
  44. hash table is to be grown. A default routine is provided
  45. if the pointer is NULL, and uses the java hashtable metric
  46. of a 75% load factor.
  47. 4. The pointer to a "new size" function, which returns a preferable
  48. new size for the hash table bucket array. By default, a function
  49. is supplied which roughly doubles the size of the array, is provided.
  50. This size should ideally be a prime number.
  51. 5. The hashing function pointer must also be supplied. This function
  52. must be written by the user to access the keys in the objects being
  53. stored. Some helper functions that use a simple "mult by prime, add
  54. the next char", sort of string hash, or a simple modulus of the hash
  55. table size for ints, is provided; the user can use these simple
  56. algorithms to generate a hash, or implement any other algorithms they
  57. wish.
  58. 6. Recently updated the hash routines to use Doubly-linked lists for buckets,
  59. and added a doubly-linked list that threads thru every bucket in the table.
  60. The list of all buckets is on the HashTab struct. The Traversal was modified
  61. to go thru this list instead of searching the bucket array for buckets.
  62. This also should make it safe to remove a bucket during the traversal.
  63. Removal and destruction routines will work faster.
  64. */
  65. struct ast_hashtab_bucket
  66. {
  67. const void *object; /*!< whatever it is we are storing in this table */
  68. struct ast_hashtab_bucket *next; /*!< a DLL of buckets in hash collision */
  69. struct ast_hashtab_bucket *prev; /*!< a DLL of buckets in hash collision */
  70. struct ast_hashtab_bucket *tnext; /*!< a DLL of all the hash buckets for traversal */
  71. struct ast_hashtab_bucket *tprev; /*!< a DLL of all the hash buckets for traversal */
  72. };
  73. struct ast_hashtab
  74. {
  75. struct ast_hashtab_bucket **array;
  76. struct ast_hashtab_bucket *tlist; /*!< the head of a DLList of all the hashbuckets in the table (for traversal). */
  77. int (*compare) (const void *a, const void *b); /*!< a ptr to func that returns int, and take two void* ptrs, compares them,
  78. rets -1 if a < b; rets 0 if a==b; rets 1 if a>b */
  79. int (*newsize) (struct ast_hashtab *tab); /*!< a ptr to func that returns int, a new size for hash tab, based on curr_size */
  80. int (*resize) (struct ast_hashtab *tab); /*!< a function to decide whether this hashtable should be resized now */
  81. unsigned int (*hash) (const void *obj); /*!< a hash func ptr for this table. Given a raw ptr to an obj,
  82. it calcs a hash.*/
  83. int hash_tab_size; /*!< the size of the bucket array */
  84. int hash_tab_elements; /*!< the number of objects currently stored in the table */
  85. int largest_bucket_size; /*!< a stat on the health of the table */
  86. int resize_count; /*!< a count of the number of times this table has been
  87. resized */
  88. int do_locking; /*!< if 1 use locks to guarantee safety of insertions/deletions */
  89. /* this spot reserved for the proper lock storage */
  90. ast_rwlock_t lock; /* is this as good as it sounds? */
  91. };
  92. /*! \brief an iterator for traversing the buckets */
  93. struct ast_hashtab_iter
  94. {
  95. struct ast_hashtab *tab;
  96. struct ast_hashtab_bucket *next;
  97. };
  98. /* some standard, default routines for general use */
  99. /*!
  100. * \brief Determines if the specified number is prime.
  101. *
  102. * \param num the number to test
  103. * \retval 0 if the number is not prime
  104. * \retval 1 if the number is prime
  105. */
  106. int ast_is_prime(int num);
  107. /*!
  108. * \brief Compares two strings for equality.
  109. *
  110. * \param a a character string
  111. * \param b a character string
  112. * \retval 0 if the strings match
  113. * \retval <0 if string a is less than string b
  114. * \retval >0 if string a is greather than string b
  115. */
  116. int ast_hashtab_compare_strings(const void *a, const void *b);
  117. /*!
  118. * \brief Compares two strings for equality, ignoring case.
  119. *
  120. * \param a a character string
  121. * \param b a character string
  122. * \retval 0 if the strings match
  123. * \retval <0 if string a is less than string b
  124. * \retval >0 if string a is greather than string b
  125. */
  126. int ast_hashtab_compare_strings_nocase(const void *a, const void *b);
  127. /*!
  128. * \brief Compares two integers for equality.
  129. *
  130. * \param a an integer pointer (int *)
  131. * \param b an integer pointer (int *)
  132. * \retval 0 if the integers pointed to are equal
  133. * \retval 1 if a is greater than b
  134. * \retval -1 if a is less than b
  135. */
  136. int ast_hashtab_compare_ints(const void *a, const void *b);
  137. /*!
  138. * \brief Compares two shorts for equality.
  139. *
  140. * \param a a short pointer (short *)
  141. * \param b a short pointer (short *)
  142. * \retval 0 if the shorts pointed to are equal
  143. * \retval 1 if a is greater than b
  144. * \retval -1 if a is less than b
  145. */
  146. int ast_hashtab_compare_shorts(const void *a, const void *b);
  147. /*!
  148. * \brief Determines if a table resize should occur using the Java algorithm
  149. * (if the table load factor is 75% or higher).
  150. *
  151. * \param tab the hash table to operate on
  152. * \retval 0 if the table load factor is less than or equal to 75%
  153. * \retval 1 if the table load factor is greater than 75%
  154. */
  155. int ast_hashtab_resize_java(struct ast_hashtab *tab);
  156. /*! \brief Causes a resize whenever the number of elements stored in the table
  157. * exceeds the number of buckets in the table.
  158. *
  159. * \param tab the hash table to operate on
  160. * \retval 0 if the number of elements in the table is less than or equal to
  161. * the number of buckets
  162. * \retval 1 if the number of elements in the table exceeds the number of
  163. * buckets
  164. */
  165. int ast_hashtab_resize_tight(struct ast_hashtab *tab);
  166. /*!
  167. * \brief Effectively disables resizing by always returning 0, regardless of
  168. * of load factor.
  169. *
  170. * \param tab the hash table to operate on
  171. * \return 0 is always returned
  172. */
  173. int ast_hashtab_resize_none(struct ast_hashtab *tab);
  174. /*! \brief Create a prime number roughly 2x the current table size */
  175. int ast_hashtab_newsize_java(struct ast_hashtab *tab);
  176. /* not yet specified, probably will return 1.5x the current table size */
  177. int ast_hashtab_newsize_tight(struct ast_hashtab *tab);
  178. /*! \brief always return current size -- no resizing */
  179. int ast_hashtab_newsize_none(struct ast_hashtab *tab);
  180. /*!
  181. * \brief Hashes a string to a number
  182. *
  183. * \param obj the string to hash
  184. * \return Integer hash of the specified string
  185. * \sa ast_hashtable_hash_string_nocase
  186. * \sa ast_hashtab_hash_string_sax
  187. * \note A modulus will be applied to the return value of this function
  188. */
  189. unsigned int ast_hashtab_hash_string(const void *obj);
  190. /*!
  191. * \brief Hashes a string to a number ignoring case
  192. *
  193. * \param obj the string to hash
  194. * \return Integer hash of the specified string
  195. * \sa ast_hashtable_hash_string
  196. * \sa ast_hashtab_hash_string_sax
  197. * \note A modulus will be applied to the return value of this function
  198. */
  199. unsigned int ast_hashtab_hash_string_nocase(const void *obj);
  200. /*!
  201. * \brief Hashes a string to a number using a modified Shift-And-XOR algorithm
  202. *
  203. * \param obj the string to hash
  204. * \return Integer has of the specified string
  205. * \sa ast_hastable_hash_string
  206. * \sa ast_hastable_hash_string_nocase
  207. */
  208. unsigned int ast_hashtab_hash_string_sax(const void *obj);
  209. unsigned int ast_hashtab_hash_int(const int num); /* right now, both these funcs are just result = num%modulus; */
  210. unsigned int ast_hashtab_hash_short(const short num);
  211. /*!
  212. * \brief Create the hashtable list
  213. * \param initial_buckets starting number of buckets
  214. * \param compare a func ptr to compare two elements in the hash -- cannot be null
  215. * \param resize a func ptr to decide if the table needs to be resized, a NULL ptr here will cause a default to be used
  216. * \param newsize a func ptr that returns a new size of the array. A NULL will cause a default to be used
  217. * \param hash a func ptr to do the hashing
  218. * \param do_locking use locks to guarantee safety of iterators/insertion/deletion -- real simpleminded right now
  219. */
  220. #ifdef __AST_DEBUG_MALLOC
  221. struct ast_hashtab * _ast_hashtab_create(int initial_buckets,
  222. int (*compare)(const void *a, const void *b),
  223. int (*resize)(struct ast_hashtab *),
  224. int (*newsize)(struct ast_hashtab *tab),
  225. unsigned int (*hash)(const void *obj),
  226. int do_locking, const char *file, int lineno, const char *function);
  227. #define ast_hashtab_create(a,b,c,d,e,f) _ast_hashtab_create(a,b,c,d,e,f,__FILE__,__LINE__,__PRETTY_FUNCTION__)
  228. #else
  229. struct ast_hashtab * ast_hashtab_create(int initial_buckets,
  230. int (*compare)(const void *a, const void *b),
  231. int (*resize)(struct ast_hashtab *),
  232. int (*newsize)(struct ast_hashtab *tab),
  233. unsigned int (*hash)(const void *obj),
  234. int do_locking );
  235. #endif
  236. /*!
  237. * \brief This func will free the hash table and all its memory.
  238. * \note It doesn't touch the objects stored in it, unless you
  239. * specify a destroy func; it will call that func for each
  240. * object in the hashtab, remove all the objects, and then
  241. * free the hashtab itself. If no destroyfunc is specified
  242. * then the routine will assume you will free it yourself.
  243. * \param tab
  244. * \param objdestroyfunc
  245. */
  246. void ast_hashtab_destroy( struct ast_hashtab *tab, void (*objdestroyfunc)(void *obj));
  247. /*!
  248. * \brief Insert without checking
  249. * \param tab
  250. * \param obj
  251. *
  252. * Normally, you'd insert "safely" by checking to see if the element is
  253. * already there; in this case, you must already have checked. If an element
  254. * is already in the hashtable, that matches this one, most likely this one
  255. * will be found first.
  256. * \note will force a resize if the resize func returns 1
  257. * \retval 1 on success
  258. * \retval 0 if there's a problem
  259. */
  260. #ifdef __AST_DEBUG_MALLOC
  261. int _ast_hashtab_insert_immediate(struct ast_hashtab *tab, const void *obj, const char *file, int lineno, const char *func);
  262. #define ast_hashtab_insert_immediate(a,b) _ast_hashtab_insert_immediate(a, b, __FILE__, __LINE__, __PRETTY_FUNCTION__)
  263. #else
  264. int ast_hashtab_insert_immediate(struct ast_hashtab *tab, const void *obj);
  265. #endif
  266. /*!
  267. * \brief Insert without checking, hashing or locking
  268. * \param tab
  269. * \param obj
  270. * \param h hashed index value
  271. *
  272. * \note Will force a resize if the resize func returns 1
  273. * \retval 1 on success
  274. * \retval 0 if there's a problem
  275. */
  276. #ifdef __AST_DEBUG_MALLOC
  277. int _ast_hashtab_insert_immediate_bucket(struct ast_hashtab *tab, const void *obj, unsigned int h, const char *file, int lineno, const char *func);
  278. #define ast_hashtab_insert_immediate_bucket(a,b,c) _ast_hashtab_insert_immediate_bucket(a, b, c, __FILE__, __LINE__, __PRETTY_FUNCTION__)
  279. #else
  280. int ast_hashtab_insert_immediate_bucket(struct ast_hashtab *tab, const void *obj, unsigned int h);
  281. #endif
  282. /*!
  283. * \brief Check and insert new object only if it is not there.
  284. * \note Will force a resize if the resize func returns 1
  285. * \retval 1 on success
  286. * \retval 0 if there's a problem, or it's already there.
  287. */
  288. #ifdef __AST_DEBUG_MALLOC
  289. int _ast_hashtab_insert_safe(struct ast_hashtab *tab, const void *obj, const char *file, int lineno, const char *func);
  290. #define ast_hashtab_insert_safe(a,b) _ast_hashtab_insert_safe(a,b,__FILE__, __LINE__, __PRETTY_FUNCTION__)
  291. #else
  292. int ast_hashtab_insert_safe(struct ast_hashtab *tab, const void *obj);
  293. #endif
  294. /*!
  295. * \brief Lookup this object in the hash table.
  296. * \param tab
  297. * \param obj
  298. * \retval a ptr if found
  299. * \retval NULL if not found
  300. */
  301. void * ast_hashtab_lookup(struct ast_hashtab *tab, const void *obj);
  302. /*!
  303. * \brief Use this if have the hash val for the object
  304. * \note This and avoid the recalc of the hash (the modulus (table_size) is not applied)
  305. */
  306. void * ast_hashtab_lookup_with_hash(struct ast_hashtab *tab, const void *obj, unsigned int hashval);
  307. /*!
  308. * \brief Similar to ast_hashtab_lookup but sets h to the key hash value if the lookup fails.
  309. * \note This has the modulus applied, and will not be useful for long term storage if the table is resizable.
  310. */
  311. void * ast_hashtab_lookup_bucket(struct ast_hashtab *tab, const void *obj, unsigned int *h);
  312. /*! \brief Returns key stats for the table */
  313. void ast_hashtab_get_stats( struct ast_hashtab *tab, int *biggest_bucket_size, int *resize_count, int *num_objects, int *num_buckets);
  314. /*! \brief Returns the number of elements stored in the hashtab */
  315. int ast_hashtab_size( struct ast_hashtab *tab);
  316. /*! \brief Returns the size of the bucket array in the hashtab */
  317. int ast_hashtab_capacity( struct ast_hashtab *tab);
  318. /*! \brief Return a copy of the hash table */
  319. #ifdef __AST_DEBUG_MALLOC
  320. struct ast_hashtab *_ast_hashtab_dup(struct ast_hashtab *tab, void *(*obj_dup_func)(const void *obj), const char *file, int lineno, const char *func);
  321. #define ast_hashtab_dup(a,b) _ast_hashtab_dup(a,b,__FILE__,__LINE__,__PRETTY_FUNCTION__)
  322. #else
  323. struct ast_hashtab *ast_hashtab_dup(struct ast_hashtab *tab, void *(*obj_dup_func)(const void *obj));
  324. #endif
  325. /*! \brief Gives an iterator to hastable */
  326. #ifdef __AST_DEBUG_MALLOC
  327. struct ast_hashtab_iter *_ast_hashtab_start_traversal(struct ast_hashtab *tab, const char *file, int lineno, const char *func);
  328. #define ast_hashtab_start_traversal(a) _ast_hashtab_start_traversal(a,__FILE__,__LINE__,__PRETTY_FUNCTION__)
  329. #else
  330. struct ast_hashtab_iter *ast_hashtab_start_traversal(struct ast_hashtab *tab);
  331. #endif
  332. /*! \brief end the traversal, free the iterator, unlock if necc. */
  333. void ast_hashtab_end_traversal(struct ast_hashtab_iter *it);
  334. /*! \brief Gets the next object in the list, advances iter one step returns null on end of traversal */
  335. void *ast_hashtab_next(struct ast_hashtab_iter *it);
  336. /*! \brief Looks up the object, removes the corresponding bucket */
  337. void *ast_hashtab_remove_object_via_lookup(struct ast_hashtab *tab, void *obj);
  338. /*! \brief Hash the object and then compare ptrs in bucket list instead of
  339. calling the compare routine, will remove the bucket */
  340. void *ast_hashtab_remove_this_object(struct ast_hashtab *tab, void *obj);
  341. /* ------------------ */
  342. /* for lock-enabled traversals with ability to remove an object during the traversal*/
  343. /* ------------------ */
  344. /*! \brief Gives an iterator to hastable */
  345. #ifdef __AST_DEBUG_MALLOC
  346. struct ast_hashtab_iter *_ast_hashtab_start_write_traversal(struct ast_hashtab *tab, const char *file, int lineno, const char *func);
  347. #define ast_hashtab_start_write_traversal(a) _ast_hashtab_start_write_traversal(a,__FILE__,__LINE__,__PRETTY_FUNCTION__)
  348. #else
  349. struct ast_hashtab_iter *ast_hashtab_start_write_traversal(struct ast_hashtab *tab);
  350. #endif
  351. /*! \brief Looks up the object, removes the corresponding bucket */
  352. void *ast_hashtab_remove_object_via_lookup_nolock(struct ast_hashtab *tab, void *obj);
  353. /*! \brief Hash the object and then compare ptrs in bucket list instead of
  354. calling the compare routine, will remove the bucket */
  355. void *ast_hashtab_remove_this_object_nolock(struct ast_hashtab *tab, void *obj);
  356. /* ------------------ */
  357. /* ------------------ */
  358. /* user-controlled hashtab locking. Create a hashtab without locking, then call the
  359. following locking routines yourself to lock the table between threads. */
  360. /*! \brief Call this after you create the table to init the lock */
  361. void ast_hashtab_initlock(struct ast_hashtab *tab);
  362. /*! \brief Request a write-lock on the table. */
  363. void ast_hashtab_wrlock(struct ast_hashtab *tab);
  364. /*! \brief Request a read-lock on the table -- don't change anything! */
  365. void ast_hashtab_rdlock(struct ast_hashtab *tab);
  366. /*! \brief release a read- or write- lock. */
  367. void ast_hashtab_unlock(struct ast_hashtab *tab);
  368. /*! \brief Call this before you destroy the table. */
  369. void ast_hashtab_destroylock(struct ast_hashtab *tab);
  370. #endif