4 Star 5 Fork 4

Oxygen/SharedHashMap

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
hashmap.c 5.55 KB
一键复制 编辑 原始数据 按行查看 历史
Oxygen 提交于 2014-11-01 03:41 +08:00 . Added shared memory pool
#include "hashmap.h"
static uint32_t djb_hash(const char *s, uint32_t n)
{
register uint32_t x = 5381;
while (n--) x = (x << 5) + x + (*s++);
return x;
}
static item_t *allocate_item(hashmap_t *hashmap)
{
item_t *ptr = ptradd(hashmap, sizeof(hashmap_t) + sizeof(unit_t) * hashmap->capacity);
if (hashmap->items < hashmap->capacity)
{
for (int i = 0; i < hashmap->capacity; i++, ptr = ptradd(ptr, hashmap->stride))
{
if (!ptr->used)
{
ptr->used = F_USED;
return ptr;
}
}
}
return NULL;
}
static unit_t *find_bucket_unit(hashmap_t *hashmap, const void *key, uint32_t keySize)
{
unit_t *bucket = ptradd(hashmap, sizeof(hashmap_t));
return &bucket[djb_hash(key, keySize) % hashmap->capacity];
}
static char find_previous_item(hashmap_t *hashmap, unit_t *list, item_t **tail, const void *key, uint32_t keySize)
{
item_t *current = (item_t *)list;
item_t *nextItem = ptradd(hashmap, current->next);
while (nextItem && (nextItem->keySize != keySize || memcmp(ptradd(nextItem, sizeof(item_t)), key, keySize)))
{
current = nextItem;
nextItem = ptradd(hashmap, current->next);
}
*tail = current;
return nextItem != NULL;
}
long hashmap_ref(hashmap_t *hashmap)
{
return __sync_add_and_fetch(&(hashmap->ref), 1);
}
long hashmap_unref(hashmap_t *hashmap)
{
return __sync_sub_and_fetch(&(hashmap->ref), 1);
}
void hashmap_wipe(hashmap_t *hashmap)
{
while (__sync_lock_test_and_set(&(hashmap->lock), F_LOCKED));
hashmap->items = 0;
for (uint32_t i = 0; i < hashmap->capacity; i++)
{
((unit_t *)ptradd(hashmap, sizeof(hashmap_t) + sizeof(unit_t) * i))->count = 0;
((unit_t *)ptradd(hashmap, sizeof(hashmap_t) + sizeof(unit_t) * i))->offset = INVALID_OFFSET;
}
for (uint32_t i = 0; i < hashmap->capacity; i++)
{
((item_t *)ptradd(hashmap, sizeof(hashmap_t) + sizeof(unit_t) * hashmap->capacity + hashmap->stride * i))->used = 0;
((item_t *)ptradd(hashmap, sizeof(hashmap_t) + sizeof(unit_t) * hashmap->capacity + hashmap->stride * i))->next = INVALID_OFFSET;
}
__sync_lock_release(&(hashmap->lock));
}
void hashmap_init(hashmap_t *hashmap, uint32_t capacity, uint32_t itemSpace)
{
hashmap->ref = 0;
hashmap->lock = 0;
hashmap->items = 0;
hashmap->stride = sizeof(item_t) + itemSpace;
hashmap->capacity = capacity;
for (uint32_t i = 0; i < capacity; i++)
{
((unit_t *)ptradd(hashmap, sizeof(hashmap_t) + sizeof(unit_t) * i))->count = 0;
((unit_t *)ptradd(hashmap, sizeof(hashmap_t) + sizeof(unit_t) * i))->offset = INVALID_OFFSET;
}
for (uint32_t i = 0; i < capacity; i++)
{
((item_t *)ptradd(hashmap, sizeof(hashmap_t) + sizeof(unit_t) * capacity + hashmap->stride * i))->used = 0;
((item_t *)ptradd(hashmap, sizeof(hashmap_t) + sizeof(unit_t) * capacity + hashmap->stride * i))->next = INVALID_OFFSET;
}
}
int hashmap_enum(hashmap_t *hashmap, enumerator_t enumerator, void *context)
{
while (__sync_lock_test_and_set(&(hashmap->lock), F_LOCKED));
int count = 0;
unit_t *bucket = ptradd(hashmap, sizeof(hashmap_t));
for (int i = 0; i < hashmap->capacity; i++)
{
item_t *item = (item_t *)&bucket[i];
for (int j = 0; j < bucket[i].count; j++, count++)
{
item = ptradd(hashmap, item->next);
enumerator(ptradd(item, sizeof(item_t)), item->keySize, context);
}
}
__sync_lock_release(&(hashmap->lock));
return count;
}
int hashmap_find(hashmap_t *hashmap, const void *key, uint32_t keySize, enumerator_t enumerator, void *context)
{
while (__sync_lock_test_and_set(&(hashmap->lock), F_LOCKED));
item_t *item = NULL;
unit_t *unit = find_bucket_unit(hashmap, key, keySize);
if (!find_previous_item(hashmap, unit, &item, key, keySize))
{
__sync_lock_release(&(hashmap->lock));
return E_NO_ENTRY;
}
item_t *node = ptradd(hashmap, item->next);
if (enumerator != NULL)
enumerator(ptradd(node, sizeof(item_t) + node->keySize), node->valueSize, context);
__sync_lock_release(&(hashmap->lock));
return E_OK;
}
int hashmap_insert(hashmap_t *hashmap, const void *key, uint32_t keySize, const void *value, uint32_t valueSize)
{
if (keySize + valueSize > hashmap->stride - sizeof(item_t))
return E_TOO_LONG;
while (__sync_lock_test_and_set(&(hashmap->lock), F_LOCKED));
item_t *node = NULL;
unit_t *unit = find_bucket_unit(hashmap, key, keySize);
if (find_previous_item(hashmap, unit, &node, key, keySize))
{
item_t *next = ptradd(hashmap, node->next);
next->valueSize = valueSize;
memcpy(ptradd(next, sizeof(item_t) + next->keySize), value, valueSize);
}
else
{
item_t *item = allocate_item(hashmap);
if (item == NULL)
{
__sync_lock_release(&(hashmap->lock));
return E_MAP_FULL;
}
unit->count++;
hashmap->items++;
item->next = INVALID_OFFSET;
node->next = ptrsub(item, hashmap);
item->keySize = keySize;
item->valueSize = valueSize;
memcpy(ptradd(item, sizeof(item_t)), key, item->keySize);
memcpy(ptradd(item, sizeof(item_t) + item->keySize), value, item->valueSize);
}
__sync_lock_release(&(hashmap->lock));
return E_OK;
}
int hashmap_remove(hashmap_t *hashmap, const void *key, uint32_t keySize, enumerator_t enumerator, void *context)
{
while (__sync_lock_test_and_set(&(hashmap->lock), F_LOCKED));
item_t *item = NULL;
unit_t *unit = find_bucket_unit(hashmap, key, keySize);
if (!find_previous_item(hashmap, unit, &item, key, keySize))
{
__sync_lock_release(&(hashmap->lock));
return E_NO_ENTRY;
}
item_t *node = ptradd(hashmap, item->next);
if (enumerator != NULL)
enumerator(ptradd(node, sizeof(item_t) + node->keySize), node->valueSize, context);
unit->count--;
hashmap->items--;
node->used = 0;
item->next = node->next;
__sync_lock_release(&(hashmap->lock));
return E_OK;
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
C
1
https://gitee.com/Oxygen/SharedHashMap.git
git@gitee.com:Oxygen/SharedHashMap.git
Oxygen
SharedHashMap
SharedHashMap
master

搜索帮助