bh_hashmap.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. /*
  2. * Copyright (C) 2019 Intel Corporation. All rights reserved.
  3. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. */
  5. #include "bh_hashmap.h"
  6. #include "bh_log.h"
  7. #include "bh_thread.h"
  8. typedef struct HashMapElem {
  9. void *key;
  10. void *value;
  11. struct HashMapElem *next;
  12. } HashMapElem;
  13. struct HashMap {
  14. /* size of element array */
  15. uint32 size;
  16. /* lock for elements */
  17. korp_mutex *lock;
  18. /* hash function of key */
  19. HashFunc hash_func;
  20. /* key equal function */
  21. KeyEqualFunc key_equal_func;
  22. KeyDestroyFunc key_destroy_func;
  23. ValueDestroyFunc value_destroy_func;
  24. HashMapElem *elements[1];
  25. };
  26. HashMap*
  27. bh_hash_map_create(uint32 size, bool use_lock,
  28. HashFunc hash_func,
  29. KeyEqualFunc key_equal_func,
  30. KeyDestroyFunc key_destroy_func,
  31. ValueDestroyFunc value_destroy_func)
  32. {
  33. HashMap *map;
  34. uint64 total_size;
  35. if (size > HASH_MAP_MAX_SIZE) {
  36. LOG_ERROR("HashMap create failed: size is too large.\n");
  37. return NULL;
  38. }
  39. if (!hash_func || !key_equal_func) {
  40. LOG_ERROR("HashMap create failed: hash function or key equal function "
  41. " is NULL.\n");
  42. return NULL;
  43. }
  44. total_size = offsetof(HashMap, elements) +
  45. sizeof(HashMapElem) * (uint64)size +
  46. (use_lock ? sizeof(korp_mutex) : 0);
  47. if (total_size >= UINT32_MAX
  48. || !(map = BH_MALLOC((uint32)total_size))) {
  49. LOG_ERROR("HashMap create failed: alloc memory failed.\n");
  50. return NULL;
  51. }
  52. memset(map, 0, (uint32)total_size);
  53. if (use_lock) {
  54. map->lock = (korp_mutex*)
  55. ((uint8*)map + offsetof(HashMap, elements)
  56. + sizeof(HashMapElem) * size);
  57. if (vm_mutex_init(map->lock)) {
  58. LOG_ERROR("HashMap create failed: init map lock failed.\n");
  59. BH_FREE(map);
  60. return NULL;
  61. }
  62. }
  63. map->size = size;
  64. map->hash_func = hash_func;
  65. map->key_equal_func = key_equal_func;
  66. map->key_destroy_func = key_destroy_func;
  67. map->value_destroy_func = value_destroy_func;
  68. return map;
  69. }
  70. bool
  71. bh_hash_map_insert(HashMap *map, void *key, void *value)
  72. {
  73. uint32 index;
  74. HashMapElem *elem;
  75. if (!map || !key) {
  76. LOG_ERROR("HashMap insert elem failed: map or key is NULL.\n");
  77. return false;
  78. }
  79. if (map->lock) {
  80. vm_mutex_lock(map->lock);
  81. }
  82. index = map->hash_func(key) % map->size;
  83. elem = map->elements[index];
  84. while (elem) {
  85. if (map->key_equal_func(elem->key, key)) {
  86. LOG_ERROR("HashMap insert elem failed: duplicated key found.\n");
  87. goto fail;
  88. }
  89. elem = elem->next;
  90. }
  91. if (!(elem = BH_MALLOC(sizeof(HashMapElem)))) {
  92. LOG_ERROR("HashMap insert elem failed: alloc memory failed.\n");
  93. goto fail;
  94. }
  95. elem->key = key;
  96. elem->value = value;
  97. elem->next = map->elements[index];
  98. map->elements[index] = elem;
  99. if (map->lock) {
  100. vm_mutex_unlock(map->lock);
  101. }
  102. return true;
  103. fail:
  104. if (map->lock) {
  105. vm_mutex_unlock(map->lock);
  106. }
  107. return false;
  108. }
  109. void*
  110. bh_hash_map_find(HashMap *map, void *key)
  111. {
  112. uint32 index;
  113. HashMapElem *elem;
  114. void *value;
  115. if (!map || !key) {
  116. LOG_ERROR("HashMap find elem failed: map or key is NULL.\n");
  117. return NULL;
  118. }
  119. if (map->lock) {
  120. vm_mutex_lock(map->lock);
  121. }
  122. index = map->hash_func(key) % map->size;
  123. elem = map->elements[index];
  124. while (elem) {
  125. if (map->key_equal_func(elem->key, key)) {
  126. value = elem->value;
  127. if (map->lock) {
  128. vm_mutex_unlock(map->lock);
  129. }
  130. return value;
  131. }
  132. elem = elem->next;
  133. }
  134. if (map->lock) {
  135. vm_mutex_unlock(map->lock);
  136. }
  137. return NULL;
  138. }
  139. bool
  140. bh_hash_map_update(HashMap *map, void *key, void *value,
  141. void **p_old_value)
  142. {
  143. uint32 index;
  144. HashMapElem *elem;
  145. if (!map || !key) {
  146. LOG_ERROR("HashMap update elem failed: map or key is NULL.\n");
  147. return false;
  148. }
  149. if (map->lock) {
  150. vm_mutex_lock(map->lock);
  151. }
  152. index = map->hash_func(key) % map->size;
  153. elem = map->elements[index];
  154. while (elem) {
  155. if (map->key_equal_func(elem->key, key)) {
  156. if (p_old_value)
  157. *p_old_value = elem->value;
  158. elem->value = value;
  159. if (map->lock) {
  160. vm_mutex_unlock(map->lock);
  161. }
  162. return true;
  163. }
  164. elem = elem->next;
  165. }
  166. if (map->lock) {
  167. vm_mutex_unlock(map->lock);
  168. }
  169. return false;
  170. }
  171. bool
  172. bh_hash_map_remove(HashMap *map, void *key,
  173. void **p_old_key, void **p_old_value)
  174. {
  175. uint32 index;
  176. HashMapElem *elem, *prev;
  177. if (!map || !key) {
  178. LOG_ERROR("HashMap remove elem failed: map or key is NULL.\n");
  179. return false;
  180. }
  181. if (map->lock) {
  182. vm_mutex_lock(map->lock);
  183. }
  184. index = map->hash_func(key) % map->size;
  185. prev = elem = map->elements[index];
  186. while (elem) {
  187. if (map->key_equal_func(elem->key, key)) {
  188. if (p_old_key)
  189. *p_old_key = elem->key;
  190. if (p_old_value)
  191. *p_old_value = elem->value;
  192. if (elem == map->elements[index])
  193. map->elements[index] = elem->next;
  194. else
  195. prev->next = elem->next;
  196. BH_FREE(elem);
  197. if (map->lock) {
  198. vm_mutex_unlock(map->lock);
  199. }
  200. return true;
  201. }
  202. prev = elem;
  203. elem = elem->next;
  204. }
  205. if (map->lock) {
  206. vm_mutex_unlock(map->lock);
  207. }
  208. return false;
  209. }
  210. bool
  211. bh_hash_map_destroy(HashMap *map)
  212. {
  213. uint32 index;
  214. HashMapElem *elem, *next;
  215. if (!map) {
  216. LOG_ERROR("HashMap destroy failed: map is NULL.\n");
  217. return false;
  218. }
  219. if (map->lock) {
  220. vm_mutex_lock(map->lock);
  221. }
  222. for (index = 0; index < map->size; index++) {
  223. elem = map->elements[index];
  224. while (elem) {
  225. next = elem->next;
  226. if (map->key_destroy_func) {
  227. map->key_destroy_func(elem->key);
  228. }
  229. if (map->value_destroy_func) {
  230. map->value_destroy_func(elem->value);
  231. }
  232. BH_FREE(elem);
  233. elem = next;
  234. }
  235. }
  236. if (map->lock) {
  237. vm_mutex_unlock(map->lock);
  238. vm_mutex_destroy(map->lock);
  239. }
  240. BH_FREE(map);
  241. return true;
  242. }