heap.h 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. /*
  2. * Asterisk -- An open source telephony toolkit.
  3. *
  4. * Copyright (C) 2009, Digium, Inc.
  5. *
  6. * Russell Bryant <russell@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. /*!
  19. * \file
  20. * \brief Max Heap data structure
  21. * \author Russell Bryant <russell@digium.com>
  22. */
  23. #ifndef __AST_HEAP_H__
  24. #define __AST_HEAP_H__
  25. /*!
  26. * \brief A max heap.
  27. *
  28. * \note Thread-safety is left to the user of the API. The heap API provides
  29. * no locking of its own. If the heap will be accessed by multiple threads,
  30. * then a lock must be used to ensure that only a single operation is
  31. * done on the heap at a time. For the sake of convenience, a lock is
  32. * provided for the user of the API to use if another lock is not already
  33. * available to protect the heap.
  34. */
  35. struct ast_heap;
  36. /*!
  37. * \brief Function type for comparing nodes in a heap
  38. *
  39. * \param elm1 the first element
  40. * \param elm2 the second element
  41. *
  42. * \retval negative if elm1 < elm2
  43. * \retval 0 if elm1 == elm2
  44. * \retval positive if elm1 > elm2
  45. *
  46. * \note This implementation is of a max heap. However, if a min heap is
  47. * desired, simply swap the return values of this function.
  48. *
  49. * \since 1.6.1
  50. */
  51. typedef int (*ast_heap_cmp_fn)(void *elm1, void *elm2);
  52. /*!
  53. * \brief Create a max heap
  54. *
  55. * \param init_height The initial height of the heap to allocate space for.
  56. * To start out, there will be room for (2 ^ init_height) - 1 entries.
  57. * However, the heap will grow as needed.
  58. * \param cmp_fn The function that should be used to compare elements in the heap.
  59. * \param index_offset This parameter is optional, but must be provided to be able
  60. * to use ast_heap_remove(). This is the number of bytes into the element
  61. * where an ssize_t has been made available for the heap's internal
  62. * use. The heap will use this field to keep track of the element's current
  63. * position in the heap. The offsetof() macro is useful for providing a
  64. * proper value for this argument. If ast_heap_remove() will not be used,
  65. * then a negative value can be provided to indicate that no field for an
  66. * offset has been allocated.
  67. *
  68. * Example Usage:
  69. *
  70. * \code
  71. *
  72. * struct myobj {
  73. * int foo;
  74. * int bar;
  75. * char stuff[8];
  76. * char things[8];
  77. * ssize_t __heap_index;
  78. * };
  79. *
  80. * ...
  81. *
  82. * static int myobj_cmp(void *obj1, void *obj2);
  83. *
  84. * ...
  85. *
  86. * struct ast_heap *h;
  87. *
  88. * h = ast_heap_create(8, myobj_cmp, offsetof(struct myobj, __heap_index));
  89. *
  90. * \endcode
  91. *
  92. * \return An instance of a max heap
  93. * \since 1.6.1
  94. */
  95. #ifdef __AST_DEBUG_MALLOC
  96. struct ast_heap *_ast_heap_create(unsigned int init_height, ast_heap_cmp_fn cmp_fn,
  97. ssize_t index_offset, const char *file, int lineno, const char *func);
  98. #define ast_heap_create(a,b,c) _ast_heap_create(a,b,c,__FILE__,__LINE__,__PRETTY_FUNCTION__)
  99. #else
  100. struct ast_heap *ast_heap_create(unsigned int init_height, ast_heap_cmp_fn cmp_fn,
  101. ssize_t index_offset);
  102. #endif
  103. /*!
  104. * \brief Destroy a max heap
  105. *
  106. * \param h the heap to destroy
  107. *
  108. * \return NULL for convenience
  109. * \since 1.6.1
  110. */
  111. struct ast_heap *ast_heap_destroy(struct ast_heap *h);
  112. /*!
  113. * \brief Push an element on to a heap
  114. *
  115. * \param h the heap being added to
  116. * \param elm the element being put on the heap
  117. *
  118. * \retval 0 success
  119. * \retval non-zero failure
  120. * \since 1.6.1
  121. */
  122. #ifdef __AST_DEBUG_MALLOC
  123. int _ast_heap_push(struct ast_heap *h, void *elm, const char *file, int lineno, const char *func);
  124. #define ast_heap_push(a,b) _ast_heap_push(a,b,__FILE__,__LINE__,__PRETTY_FUNCTION__)
  125. #else
  126. int ast_heap_push(struct ast_heap *h, void *elm);
  127. #endif
  128. /*!
  129. * \brief Pop the max element off of the heap
  130. *
  131. * \param h the heap
  132. *
  133. * \return this will return the element on the top of the heap, which has the
  134. * largest value according to the element comparison function that was
  135. * provided when the heap was created. The element will be removed before
  136. * being returned.
  137. * \since 1.6.1
  138. */
  139. void *ast_heap_pop(struct ast_heap *h);
  140. /*!
  141. * \brief Remove a specific element from a heap
  142. *
  143. * \param h the heap to remove from
  144. * \param elm the element to remove
  145. *
  146. * \return elm, if the removal was successful, or NULL if it failed
  147. *
  148. * \note the index_offset parameter to ast_heap_create() is required to be able
  149. * to use this function.
  150. * \since 1.6.1
  151. */
  152. void *ast_heap_remove(struct ast_heap *h, void *elm);
  153. /*!
  154. * \brief Peek at an element on a heap
  155. *
  156. * \param h the heap
  157. * \param index index of the element to return. The first element is at index 1,
  158. * and the last element is at the index == the size of the heap.
  159. *
  160. * \return an element at the specified index on the heap. This element will \b not
  161. * be removed before being returned.
  162. *
  163. * \note If this function is being used in combination with ast_heap_size() for
  164. * purposes of traversing the heap, the heap must be locked for the entire
  165. * duration of the traversal.
  166. *
  167. * Example code for a traversal:
  168. * \code
  169. *
  170. * struct ast_heap *h;
  171. *
  172. * ...
  173. *
  174. * size_t size, i;
  175. * void *cur_obj;
  176. *
  177. * ast_heap_rdlock(h);
  178. *
  179. * size = ast_heap_size(h);
  180. *
  181. * for (i = 1; i <= size && (cur_obj = ast_heap_peek(h, i)); i++) {
  182. * ... Do stuff with cur_obj ...
  183. * }
  184. *
  185. * ast_heap_unlock(h);
  186. *
  187. * \endcode
  188. * \since 1.6.1
  189. */
  190. void *ast_heap_peek(struct ast_heap *h, unsigned int index);
  191. /*!
  192. * \brief Get the current size of a heap
  193. *
  194. * \param h the heap
  195. *
  196. * \return the number of elements currently in the heap
  197. * \since 1.6.1
  198. */
  199. size_t ast_heap_size(struct ast_heap *h);
  200. /*!
  201. * \brief Write-Lock a heap
  202. *
  203. * \param h the heap
  204. * \param file, func, line
  205. *
  206. * A lock is provided for convenience. It can be assumed that none of the
  207. * ast_heap API calls are thread safe. This lock does not have to be used
  208. * if another one is already available to protect the heap.
  209. *
  210. * \return see the documentation for pthread_rwlock_wrlock()
  211. * \since 1.6.1
  212. */
  213. int __ast_heap_wrlock(struct ast_heap *h, const char *file, const char *func, int line);
  214. /*!
  215. * \brief Read-Lock a heap
  216. *
  217. * \param h the heap
  218. * \param file, func, line
  219. *
  220. * A lock is provided for convenience. It can be assumed that none of the
  221. * ast_heap API calls are thread safe. This lock does not have to be used
  222. * if another one is already available to protect the heap.
  223. *
  224. * \return see the documentation for pthread_rwlock_rdlock()
  225. * \since 1.6.1
  226. */
  227. int __ast_heap_rdlock(struct ast_heap *h, const char *file, const char *func, int line);
  228. /*!
  229. * \brief Unlock a heap
  230. *
  231. * \param h the heap
  232. * \param file, func, line
  233. *
  234. * \return see the documentation for pthread_rwlock_unlock()
  235. * \since 1.6.1
  236. */
  237. int __ast_heap_unlock(struct ast_heap *h, const char *file, const char *func, int line);
  238. #define ast_heap_wrlock(h) __ast_heap_wrlock(h, __FILE__, __PRETTY_FUNCTION__, __LINE__)
  239. #define ast_heap_rdlock(h) __ast_heap_rdlock(h, __FILE__, __PRETTY_FUNCTION__, __LINE__)
  240. #define ast_heap_unlock(h) __ast_heap_unlock(h, __FILE__, __PRETTY_FUNCTION__, __LINE__)
  241. /*!
  242. * \brief Verify that a heap has been properly constructed
  243. *
  244. * \param h a heap
  245. *
  246. * \retval 0 success
  247. * \retval non-zero failure
  248. *
  249. * \note This function is mostly for debugging purposes. It traverses an existing
  250. * heap and verifies that every node is properly placed relative to its children.
  251. * \since 1.6.1
  252. */
  253. int ast_heap_verify(struct ast_heap *h);
  254. #endif /* __AST_HEAP_H__ */