From 6800caf68a3f32672dc91ed094af1748d173c34a Mon Sep 17 00:00:00 2001 From: Stephen Seo Date: Thu, 7 Feb 2019 11:50:28 +0900 Subject: [PATCH] Change HM to use overflow and individual buckets --- src/UDPC_HashMap.c | 87 +++++++++++++++++++++++++++++++++++++--------- src/UDPC_HashMap.h | 5 ++- 2 files changed, 74 insertions(+), 18 deletions(-) diff --git a/src/UDPC_HashMap.c b/src/UDPC_HashMap.c index b191c5c..4fe007b 100644 --- a/src/UDPC_HashMap.c +++ b/src/UDPC_HashMap.c @@ -15,7 +15,8 @@ UDPC_HashMap* UDPC_HashMap_init(uint32_t capacity, uint32_t unitSize) m->size = 0; m->capacity = (capacity > 10 ? capacity : 10); m->unitSize = unitSize; - m->buckets = malloc(sizeof(UDPC_Deque) * m->capacity); + + m->buckets = malloc(sizeof(UDPC_Deque*) * m->capacity); if(!m->buckets) { free(m); @@ -26,14 +27,11 @@ UDPC_HashMap* UDPC_HashMap_init(uint32_t capacity, uint32_t unitSize) { if(fail != 0) { - (&m->buckets[x])->buf = NULL; + m->buckets[x] = NULL; continue; } - - UDPC_Deque_clear(m->buckets + x); - (m->buckets + x)->alloc_size = 8 * (sizeof(uint32_t) + unitSize); - (m->buckets + x)->buf = malloc(8 * (sizeof(uint32_t) + unitSize)); - if(!(m->buckets + x)->buf) + m->buckets[x] = UDPC_Deque_init(unitSize * UDPC_HASHMAP_BUCKET_SIZE); + if(!m->buckets[x]) { fail = 1; } @@ -43,9 +41,24 @@ UDPC_HashMap* UDPC_HashMap_init(uint32_t capacity, uint32_t unitSize) { for(int x = 0; x < m->capacity; ++x) { - if((m->buckets + x)->buf) + if(m->buckets[x]) { - free((m->buckets + x)->buf); + UDPC_Deque_destroy(m->buckets[x]); + } + } + free(m->buckets); + free(m); + return NULL; + } + + m->overflow = UDPC_Deque_init(unitSize * UDPC_HASHMAP_BUCKET_SIZE); + if(!m->overflow) + { + for(int x = 0; x < m->capacity; ++x) + { + if(m->buckets[x]) + { + UDPC_Deque_destroy(m->buckets[x]); } } free(m->buckets); @@ -60,7 +73,7 @@ void UDPC_HashMap_destroy(UDPC_HashMap *hashMap) { for(int x = 0; x < hashMap->capacity; ++x) { - free((hashMap->buckets + x)->buf); + UDPC_Deque_destroy(hashMap->buckets[x]); } free(hashMap->buckets); free(hashMap); @@ -74,7 +87,15 @@ void* UDPC_HashMap_insert(UDPC_HashMap *hm, uint32_t key, void *data) memcpy(temp, &key, sizeof(uint32_t)); memcpy(temp + sizeof(uint32_t), data, hm->unitSize); - if(UDPC_Deque_push_back(hm->buckets + hash, temp, sizeof(uint32_t) + hm->unitSize) == 0) + if(UDPC_Deque_get_available(hm->buckets[hash]) == 0) + { + if(UDPC_Deque_push_back(hm->overflow, temp, sizeof(uint32_t) + hm->unitSize) == 0) + { + free(temp); + return NULL; + } + } + else if(UDPC_Deque_push_back(hm->buckets[hash], temp, sizeof(uint32_t) + hm->unitSize) == 0) { free(temp); return NULL; @@ -82,7 +103,7 @@ void* UDPC_HashMap_insert(UDPC_HashMap *hm, uint32_t key, void *data) free(temp); ++hm->size; - temp = UDPC_Deque_get_back_ptr(hm->buckets + hash, sizeof(uint32_t) + hm->unitSize); + temp = UDPC_Deque_get_back_ptr(hm->buckets[hash], sizeof(uint32_t) + hm->unitSize); return temp + sizeof(uint32_t); } @@ -95,14 +116,34 @@ int UDPC_HashMap_remove(UDPC_HashMap *hm, uint32_t key) uint32_t hash = UDPC_HASH32(key) % hm->capacity; - for(int x = 0; x * (sizeof(uint32_t) + hm->unitSize) < (hm->buckets + hash)->size; ++x) + for(int x = 0; x * (sizeof(uint32_t) + hm->unitSize) < hm->buckets[hash]->size; ++x) { if(memcmp( - UDPC_Deque_index_ptr(hm->buckets + hash, sizeof(uint32_t) + hm->unitSize, x), + UDPC_Deque_index_ptr(hm->buckets[hash], sizeof(uint32_t) + hm->unitSize, x), &key, sizeof(uint32_t)) == 0) { - int result = UDPC_Deque_remove(hm->buckets + hash, sizeof(uint32_t) + hm->unitSize, x); + int result = UDPC_Deque_remove(hm->buckets[hash], sizeof(uint32_t) + hm->unitSize, x); + if(result != 0) + { + --hm->size; + return 1; + } + else + { + return 0; + } + } + } + + for(int x = 0; x * (sizeof(uint32_t) + hm->unitSize) < hm->overflow->size; ++x) + { + if(memcmp( + UDPC_Deque_index_ptr(hm->overflow, sizeof(uint32_t) + hm->unitSize, x), + &key, + sizeof(uint32_t)) == 0) + { + int result = UDPC_Deque_remove(hm->overflow, sizeof(uint32_t) + hm->unitSize, x); if(result != 0) { --hm->size; @@ -127,9 +168,21 @@ void* UDPC_HashMap_get(UDPC_HashMap *hm, uint32_t key) uint32_t hash = UDPC_HASH32(key) % hm->capacity; - for(int x = 0; x * (sizeof(uint32_t) + hm->unitSize) < (hm->buckets + hash)->size; ++x) + for(int x = 0; x * (sizeof(uint32_t) + hm->unitSize) < hm->buckets[hash]->size; ++x) { - char *ptr = UDPC_Deque_index_ptr(hm->buckets + hash, sizeof(uint32_t) + hm->unitSize, x); + char *ptr = UDPC_Deque_index_ptr(hm->buckets[hash], sizeof(uint32_t) + hm->unitSize, x); + if(memcmp( + ptr, + &key, + sizeof(uint32_t)) == 0) + { + return ptr + sizeof(uint32_t); + } + } + + for(int x = 0; x * (sizeof(uint32_t) + hm->unitSize) < hm->overflow->size; ++x) + { + char *ptr = UDPC_Deque_index_ptr(hm->overflow, sizeof(uint32_t) + hm->unitSize, x); if(memcmp( ptr, &key, diff --git a/src/UDPC_HashMap.h b/src/UDPC_HashMap.h index 46eebb3..5297e40 100644 --- a/src/UDPC_HashMap.h +++ b/src/UDPC_HashMap.h @@ -15,13 +15,16 @@ ) ^ 0x96969696 \ ) +#define UDPC_HASHMAP_BUCKET_SIZE 4 + #include "UDPC_Deque.h" typedef struct { uint32_t size; uint32_t capacity; uint32_t unitSize; - UDPC_Deque *buckets; + UDPC_Deque **buckets; + UDPC_Deque *overflow; } UDPC_HashMap; /*!