hashmap.cpp 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. /*
  2. * Copyright (C) 2007 The Android Open Source Project
  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 <cutils/hashmap.h>
  17. #include <assert.h>
  18. #include <errno.h>
  19. #include <pthread.h>
  20. #include <stdlib.h>
  21. #include <string.h>
  22. #include <sys/types.h>
  23. typedef struct Entry Entry;
  24. struct Entry {
  25. void* key;
  26. int hash;
  27. void* value;
  28. Entry* next;
  29. };
  30. struct Hashmap {
  31. Entry** buckets;
  32. size_t bucketCount;
  33. int (*hash)(void* key);
  34. bool (*equals)(void* keyA, void* keyB);
  35. pthread_mutex_t lock;
  36. size_t size;
  37. };
  38. Hashmap* hashmapCreate(size_t initialCapacity,
  39. int (*hash)(void* key), bool (*equals)(void* keyA, void* keyB)) {
  40. assert(hash != NULL);
  41. assert(equals != NULL);
  42. Hashmap* map = static_cast<Hashmap*>(malloc(sizeof(Hashmap)));
  43. if (map == NULL) {
  44. return NULL;
  45. }
  46. // 0.75 load factor.
  47. size_t minimumBucketCount = initialCapacity * 4 / 3;
  48. map->bucketCount = 1;
  49. while (map->bucketCount <= minimumBucketCount) {
  50. // Bucket count must be power of 2.
  51. map->bucketCount <<= 1;
  52. }
  53. map->buckets = static_cast<Entry**>(calloc(map->bucketCount, sizeof(Entry*)));
  54. if (map->buckets == NULL) {
  55. free(map);
  56. return NULL;
  57. }
  58. map->size = 0;
  59. map->hash = hash;
  60. map->equals = equals;
  61. pthread_mutex_init(&map->lock, nullptr);
  62. return map;
  63. }
  64. /**
  65. * Hashes the given key.
  66. */
  67. #ifdef __clang__
  68. __attribute__((no_sanitize("integer")))
  69. #endif
  70. static inline int hashKey(Hashmap* map, void* key) {
  71. int h = map->hash(key);
  72. // We apply this secondary hashing discovered by Doug Lea to defend
  73. // against bad hashes.
  74. h += ~(h << 9);
  75. h ^= (((unsigned int) h) >> 14);
  76. h += (h << 4);
  77. h ^= (((unsigned int) h) >> 10);
  78. return h;
  79. }
  80. static inline size_t calculateIndex(size_t bucketCount, int hash) {
  81. return ((size_t) hash) & (bucketCount - 1);
  82. }
  83. static void expandIfNecessary(Hashmap* map) {
  84. // If the load factor exceeds 0.75...
  85. if (map->size > (map->bucketCount * 3 / 4)) {
  86. // Start off with a 0.33 load factor.
  87. size_t newBucketCount = map->bucketCount << 1;
  88. Entry** newBuckets = static_cast<Entry**>(calloc(newBucketCount, sizeof(Entry*)));
  89. if (newBuckets == NULL) {
  90. // Abort expansion.
  91. return;
  92. }
  93. // Move over existing entries.
  94. size_t i;
  95. for (i = 0; i < map->bucketCount; i++) {
  96. Entry* entry = map->buckets[i];
  97. while (entry != NULL) {
  98. Entry* next = entry->next;
  99. size_t index = calculateIndex(newBucketCount, entry->hash);
  100. entry->next = newBuckets[index];
  101. newBuckets[index] = entry;
  102. entry = next;
  103. }
  104. }
  105. // Copy over internals.
  106. free(map->buckets);
  107. map->buckets = newBuckets;
  108. map->bucketCount = newBucketCount;
  109. }
  110. }
  111. void hashmapLock(Hashmap* map) {
  112. pthread_mutex_lock(&map->lock);
  113. }
  114. void hashmapUnlock(Hashmap* map) {
  115. pthread_mutex_unlock(&map->lock);
  116. }
  117. void hashmapFree(Hashmap* map) {
  118. size_t i;
  119. for (i = 0; i < map->bucketCount; i++) {
  120. Entry* entry = map->buckets[i];
  121. while (entry != NULL) {
  122. Entry* next = entry->next;
  123. free(entry);
  124. entry = next;
  125. }
  126. }
  127. free(map->buckets);
  128. pthread_mutex_destroy(&map->lock);
  129. free(map);
  130. }
  131. #ifdef __clang__
  132. __attribute__((no_sanitize("integer")))
  133. #endif
  134. /* FIXME: relies on signed integer overflow, which is undefined behavior */
  135. int hashmapHash(void* key, size_t keySize) {
  136. int h = keySize;
  137. char* data = (char*) key;
  138. size_t i;
  139. for (i = 0; i < keySize; i++) {
  140. h = h * 31 + *data;
  141. data++;
  142. }
  143. return h;
  144. }
  145. static Entry* createEntry(void* key, int hash, void* value) {
  146. Entry* entry = static_cast<Entry*>(malloc(sizeof(Entry)));
  147. if (entry == NULL) {
  148. return NULL;
  149. }
  150. entry->key = key;
  151. entry->hash = hash;
  152. entry->value = value;
  153. entry->next = NULL;
  154. return entry;
  155. }
  156. static inline bool equalKeys(void* keyA, int hashA, void* keyB, int hashB,
  157. bool (*equals)(void*, void*)) {
  158. if (keyA == keyB) {
  159. return true;
  160. }
  161. if (hashA != hashB) {
  162. return false;
  163. }
  164. return equals(keyA, keyB);
  165. }
  166. void* hashmapPut(Hashmap* map, void* key, void* value) {
  167. int hash = hashKey(map, key);
  168. size_t index = calculateIndex(map->bucketCount, hash);
  169. Entry** p = &(map->buckets[index]);
  170. while (true) {
  171. Entry* current = *p;
  172. // Add a new entry.
  173. if (current == NULL) {
  174. *p = createEntry(key, hash, value);
  175. if (*p == NULL) {
  176. errno = ENOMEM;
  177. return NULL;
  178. }
  179. map->size++;
  180. expandIfNecessary(map);
  181. return NULL;
  182. }
  183. // Replace existing entry.
  184. if (equalKeys(current->key, current->hash, key, hash, map->equals)) {
  185. void* oldValue = current->value;
  186. current->value = value;
  187. return oldValue;
  188. }
  189. // Move to next entry.
  190. p = &current->next;
  191. }
  192. }
  193. void* hashmapGet(Hashmap* map, void* key) {
  194. int hash = hashKey(map, key);
  195. size_t index = calculateIndex(map->bucketCount, hash);
  196. Entry* entry = map->buckets[index];
  197. while (entry != NULL) {
  198. if (equalKeys(entry->key, entry->hash, key, hash, map->equals)) {
  199. return entry->value;
  200. }
  201. entry = entry->next;
  202. }
  203. return NULL;
  204. }
  205. void* hashmapRemove(Hashmap* map, void* key) {
  206. int hash = hashKey(map, key);
  207. size_t index = calculateIndex(map->bucketCount, hash);
  208. // Pointer to the current entry.
  209. Entry** p = &(map->buckets[index]);
  210. Entry* current;
  211. while ((current = *p) != NULL) {
  212. if (equalKeys(current->key, current->hash, key, hash, map->equals)) {
  213. void* value = current->value;
  214. *p = current->next;
  215. free(current);
  216. map->size--;
  217. return value;
  218. }
  219. p = &current->next;
  220. }
  221. return NULL;
  222. }
  223. void hashmapForEach(Hashmap* map, bool (*callback)(void* key, void* value, void* context),
  224. void* context) {
  225. size_t i;
  226. for (i = 0; i < map->bucketCount; i++) {
  227. Entry* entry = map->buckets[i];
  228. while (entry != NULL) {
  229. Entry *next = entry->next;
  230. if (!callback(entry->key, entry->value, context)) {
  231. return;
  232. }
  233. entry = next;
  234. }
  235. }
  236. }