wasm_hashmap.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. /*
  2. * Copyright (C) 2019 Intel Corporation. All rights reserved.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include "wasm_hashmap.h"
  17. #include "wasm_log.h"
  18. #include "wasm_thread.h"
  19. #include "wasm_memory.h"
  20. typedef struct HashMapElem {
  21. void *key;
  22. void *value;
  23. struct HashMapElem *next;
  24. } HashMapElem;
  25. struct HashMap {
  26. /* size of element array */
  27. uint32 size;
  28. /* lock for elements */
  29. korp_mutex *lock;
  30. /* hash function of key */
  31. HashFunc hash_func;
  32. /* key equal function */
  33. KeyEqualFunc key_equal_func;
  34. KeyDestroyFunc key_destroy_func;
  35. ValueDestroyFunc value_destroy_func;
  36. HashMapElem *elements[1];
  37. };
  38. HashMap*
  39. wasm_hash_map_create(uint32 size, bool use_lock,
  40. HashFunc hash_func,
  41. KeyEqualFunc key_equal_func,
  42. KeyDestroyFunc key_destroy_func,
  43. ValueDestroyFunc value_destroy_func)
  44. {
  45. HashMap *map;
  46. uint32 total_size;
  47. if (size > HASH_MAP_MAX_SIZE) {
  48. LOG_ERROR("HashMap create failed: size is too large.\n");
  49. return NULL;
  50. }
  51. if (!hash_func || !key_equal_func) {
  52. LOG_ERROR("HashMap create failed: hash function or key equal function "
  53. " is NULL.\n");
  54. return NULL;
  55. }
  56. total_size = offsetof(HashMap, elements) +
  57. sizeof(HashMapElem) * size +
  58. (use_lock ? sizeof(korp_mutex) : 0);
  59. if (!(map = wasm_malloc(total_size))) {
  60. LOG_ERROR("HashMap create failed: alloc memory failed.\n");
  61. return NULL;
  62. }
  63. memset(map, 0, total_size);
  64. if (use_lock) {
  65. map->lock = (korp_mutex*)
  66. ((uint8*)map + offsetof(HashMap, elements) + sizeof(HashMapElem) * size);
  67. if (ws_mutex_init(map->lock, false)) {
  68. LOG_ERROR("HashMap create failed: init map lock failed.\n");
  69. wasm_free(map);
  70. return NULL;
  71. }
  72. }
  73. map->size = size;
  74. map->hash_func = hash_func;
  75. map->key_equal_func = key_equal_func;
  76. map->key_destroy_func = key_destroy_func;
  77. map->value_destroy_func = value_destroy_func;
  78. return map;
  79. }
  80. bool
  81. wasm_hash_map_insert(HashMap *map, void *key, void *value)
  82. {
  83. uint32 index;
  84. HashMapElem *elem;
  85. if (!map || !key) {
  86. LOG_ERROR("HashMap insert elem failed: map or key is NULL.\n");
  87. return false;
  88. }
  89. if (map->lock) {
  90. ws_mutex_lock(map->lock);
  91. }
  92. index = map->hash_func(key) % map->size;
  93. elem = map->elements[index];
  94. while (elem) {
  95. if (map->key_equal_func(elem->key, key)) {
  96. LOG_ERROR("HashMap insert elem failed: duplicated key found.\n");
  97. goto fail;
  98. }
  99. elem = elem->next;
  100. }
  101. if (!(elem = wasm_malloc(sizeof(HashMapElem)))) {
  102. LOG_ERROR("HashMap insert elem failed: alloc memory failed.\n");
  103. goto fail;
  104. }
  105. elem->key = key;
  106. elem->value = value;
  107. elem->next = map->elements[index];
  108. map->elements[index] = elem;
  109. if (map->lock) {
  110. ws_mutex_unlock(map->lock);
  111. }
  112. return true;
  113. fail:
  114. if (map->lock) {
  115. ws_mutex_unlock(map->lock);
  116. }
  117. return false;
  118. }
  119. void*
  120. wasm_hash_map_find(HashMap *map, void *key)
  121. {
  122. uint32 index;
  123. HashMapElem *elem;
  124. void *value;
  125. if (!map || !key) {
  126. LOG_ERROR("HashMap find elem failed: map or key is NULL.\n");
  127. return NULL;
  128. }
  129. if (map->lock) {
  130. ws_mutex_lock(map->lock);
  131. }
  132. index = map->hash_func(key) % map->size;
  133. elem = map->elements[index];
  134. while (elem) {
  135. if (map->key_equal_func(elem->key, key)) {
  136. value = elem->value;
  137. if (map->lock) {
  138. ws_mutex_unlock(map->lock);
  139. }
  140. return value;
  141. }
  142. elem = elem->next;
  143. }
  144. if (map->lock) {
  145. ws_mutex_unlock(map->lock);
  146. }
  147. return NULL;
  148. }
  149. bool
  150. wasm_hash_map_update(HashMap *map, void *key, void *value,
  151. void **p_old_value)
  152. {
  153. uint32 index;
  154. HashMapElem *elem;
  155. if (!map || !key) {
  156. LOG_ERROR("HashMap update elem failed: map or key is NULL.\n");
  157. return false;
  158. }
  159. if (map->lock) {
  160. ws_mutex_lock(map->lock);
  161. }
  162. index = map->hash_func(key) % map->size;
  163. elem = map->elements[index];
  164. while (elem) {
  165. if (map->key_equal_func(elem->key, key)) {
  166. if (p_old_value)
  167. *p_old_value = elem->value;
  168. elem->value = value;
  169. if (map->lock) {
  170. ws_mutex_unlock(map->lock);
  171. }
  172. return true;
  173. }
  174. elem = elem->next;
  175. }
  176. if (map->lock) {
  177. ws_mutex_unlock(map->lock);
  178. }
  179. return false;
  180. }
  181. bool
  182. wasm_hash_map_remove(HashMap *map, void *key,
  183. void **p_old_key, void **p_old_value)
  184. {
  185. uint32 index;
  186. HashMapElem *elem, *prev;
  187. if (!map || !key) {
  188. LOG_ERROR("HashMap remove elem failed: map or key is NULL.\n");
  189. return false;
  190. }
  191. if (map->lock) {
  192. ws_mutex_lock(map->lock);
  193. }
  194. index = map->hash_func(key) % map->size;
  195. prev = elem = map->elements[index];
  196. while (elem) {
  197. if (map->key_equal_func(elem->key, key)) {
  198. if (p_old_key)
  199. *p_old_key = elem->key;
  200. if (p_old_value)
  201. *p_old_value = elem->value;
  202. if (elem == map->elements[index])
  203. map->elements[index] = elem->next;
  204. else
  205. prev->next = elem->next;
  206. wasm_free(elem);
  207. if (map->lock) {
  208. ws_mutex_unlock(map->lock);
  209. }
  210. return true;
  211. }
  212. prev = elem;
  213. elem = elem->next;
  214. }
  215. if (map->lock) {
  216. ws_mutex_unlock(map->lock);
  217. }
  218. return false;
  219. }
  220. bool
  221. wasm_hash_map_destroy(HashMap *map)
  222. {
  223. uint32 index;
  224. HashMapElem *elem, *next;
  225. if (!map) {
  226. LOG_ERROR("HashMap destroy failed: map is NULL.\n");
  227. return false;
  228. }
  229. if (map->lock) {
  230. ws_mutex_lock(map->lock);
  231. }
  232. for (index = 0; index < map->size; index++) {
  233. elem = map->elements[index];
  234. while (elem) {
  235. next = elem->next;
  236. if (map->key_destroy_func) {
  237. map->key_destroy_func(elem->key);
  238. }
  239. if (map->value_destroy_func) {
  240. map->value_destroy_func(elem->value);
  241. }
  242. wasm_free(elem);
  243. elem = next;
  244. }
  245. }
  246. if (map->lock) {
  247. ws_mutex_unlock(map->lock);
  248. ws_mutex_destroy(map->lock);
  249. }
  250. wasm_free(map);
  251. return true;
  252. }