mirror of
https://github.com/justinethier/cyclone.git
synced 2025-05-23 20:15:05 +02:00
Integrate simple hashset
This commit is contained in:
parent
dc8c13abd3
commit
c9f4d8243c
2 changed files with 247 additions and 1 deletions
178
ck-polyfill.c
178
ck-polyfill.c
|
@ -191,3 +191,181 @@ ck_pr_load_8(const uint8_t *target)
|
|||
pthread_mutex_unlock(&glock);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// Simple hashset
|
||||
|
||||
static const size_t prime_1 = 73;
|
||||
static const size_t prime_2 = 5009;
|
||||
|
||||
struct simple_hashset_item_st {
|
||||
size_t hash;
|
||||
char* item;
|
||||
};
|
||||
|
||||
struct simple_hashset_st {
|
||||
size_t nbits;
|
||||
size_t mask;
|
||||
|
||||
size_t capacity;
|
||||
struct simple_hashset_item_st *items;
|
||||
size_t nitems;
|
||||
size_t n_deleted_items;
|
||||
|
||||
hash_func_t hash_func;
|
||||
};
|
||||
|
||||
size_t hash_function(char* p, size_t len)
|
||||
{
|
||||
size_t hash = 0;
|
||||
for (; *p; ++p)
|
||||
hash ^= *p + 0x9e3779b9 + (hash << 6) + (hash >> 2);
|
||||
return hash;
|
||||
}
|
||||
|
||||
simple_hashset_t simple_hashset_create()
|
||||
{
|
||||
simple_hashset_t set = (simple_hashset_t)calloc(1, sizeof(struct simple_hashset_st));
|
||||
|
||||
if (set == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
set->hash_func = hash_function;
|
||||
set->nbits = 3;
|
||||
set->capacity = (size_t)(1 << set->nbits);
|
||||
set->mask = set->capacity - 1;
|
||||
set->items = (struct simple_hashset_item_st*)calloc(set->capacity, sizeof(struct simple_hashset_item_st));
|
||||
if (set->items == NULL) {
|
||||
simple_hashset_destroy(set);
|
||||
return NULL;
|
||||
}
|
||||
set->nitems = 0;
|
||||
set->n_deleted_items = 0;
|
||||
return set;
|
||||
}
|
||||
|
||||
void simple_hashset_clean(simple_hashset_t set)
|
||||
{
|
||||
set->nitems = 0;
|
||||
set->n_deleted_items = 0;
|
||||
|
||||
size_t i = 0;
|
||||
while(i != set->capacity)
|
||||
set->items[i++].hash = 0;
|
||||
}
|
||||
|
||||
size_t simple_hashset_num_items(simple_hashset_t set)
|
||||
{
|
||||
return set->nitems;
|
||||
}
|
||||
|
||||
void simple_hashset_destroy(simple_hashset_t set)
|
||||
{
|
||||
if (set) {
|
||||
free(set->items);
|
||||
}
|
||||
free(set);
|
||||
}
|
||||
|
||||
void simple_hashset_set_hash_function(simple_hashset_t set, hash_func_t func)
|
||||
{
|
||||
set->hash_func = func;
|
||||
}
|
||||
|
||||
static int simple_hashset_add_member(simple_hashset_t set, char* key, size_t hash)
|
||||
{
|
||||
size_t index;
|
||||
|
||||
if (hash < 2) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
index = set->mask & (prime_1 * hash);
|
||||
|
||||
while (set->items[index].hash != 0 && set->items[index].hash != 1) {
|
||||
if (set->items[index].hash == hash) {
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
/* search free slot */
|
||||
index = set->mask & (index + prime_2);
|
||||
}
|
||||
}
|
||||
|
||||
++set->nitems;
|
||||
if (set->items[index].hash == 1) {
|
||||
--set->n_deleted_items;
|
||||
}
|
||||
|
||||
set->items[index].hash = hash;
|
||||
set->items[index].item = key;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void set_maybe_rehash(simple_hashset_t set)
|
||||
{
|
||||
struct simple_hashset_item_st *old_items;
|
||||
size_t old_capacity, index;
|
||||
|
||||
|
||||
if (set->nitems + set->n_deleted_items >= (double)set->capacity * 0.85) {
|
||||
old_items = set->items;
|
||||
old_capacity = set->capacity;
|
||||
++set->nbits;
|
||||
set->capacity = (size_t)(1 << set->nbits);
|
||||
set->mask = set->capacity - 1;
|
||||
set->items = (struct simple_hashset_item_st*)calloc(set->capacity, sizeof(struct simple_hashset_item_st));
|
||||
set->nitems = 0;
|
||||
set->n_deleted_items = 0;
|
||||
//assert(set->items);
|
||||
for (index = 0; index < old_capacity; ++index) {
|
||||
simple_hashset_add_member(set, old_items[index].item, old_items[index].hash);
|
||||
}
|
||||
free(old_items);
|
||||
}
|
||||
}
|
||||
|
||||
int simple_hashset_add(simple_hashset_t set, char* key, size_t key_len)
|
||||
{
|
||||
size_t hash = set->hash_func(key, key_len);
|
||||
int rv = simple_hashset_add_member(set, key, hash);
|
||||
set_maybe_rehash(set);
|
||||
return rv;
|
||||
}
|
||||
|
||||
int simple_hashset_remove(simple_hashset_t set, char* key, size_t key_len)
|
||||
{
|
||||
size_t hash = set->hash_func(key, key_len);
|
||||
size_t index = set->mask & (prime_1 * hash);
|
||||
|
||||
while (set->items[index].hash != 0) {
|
||||
if (set->items[index].hash == hash) {
|
||||
set->items[index].hash = 1;
|
||||
--set->nitems;
|
||||
++set->n_deleted_items;
|
||||
return 1;
|
||||
} else {
|
||||
index = set->mask & (index + prime_2);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int simple_hashset_is_member(simple_hashset_t set, char* key, size_t key_len)
|
||||
{
|
||||
size_t hash = set->hash_func(key, key_len);
|
||||
size_t index = set->mask & (prime_1 * hash);
|
||||
|
||||
while (set->items[index].hash != 0) {
|
||||
if (set->items[index].hash == hash) {
|
||||
return 1;
|
||||
} else {
|
||||
index = set->mask & (index + prime_2);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -8,6 +8,59 @@
|
|||
|
||||
void ck_polyfill_init();
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Simple hashset (hashset with string support)
|
||||
/* hash function */
|
||||
typedef size_t(*hash_func_t)(char*, size_t);
|
||||
|
||||
struct simple_hashset_st;
|
||||
typedef struct simple_hashset_st *simple_hashset_t;
|
||||
|
||||
struct hashmap_st;
|
||||
typedef struct hashmap_st *hashmap_t;
|
||||
|
||||
/*
|
||||
* HASHSET FUNCTIONS
|
||||
*/
|
||||
|
||||
/* create hashset instance */
|
||||
simple_hashset_t simple_hashset_create(void);
|
||||
|
||||
/* destroy hashset instance */
|
||||
void simple_hashset_destroy(simple_hashset_t set);
|
||||
|
||||
/* set hash function */
|
||||
void simple_hashset_set_hash_function(simple_hashset_t set, hash_func_t func);
|
||||
|
||||
/* Just clear data but do not create anything*/
|
||||
void simple_hashset_clean(simple_hashset_t set);
|
||||
|
||||
/* total items count */
|
||||
size_t simple_hashset_num_items(simple_hashset_t set);
|
||||
|
||||
/* add item into the hashset.
|
||||
*
|
||||
* @note 0 and 1 is special values, meaning nil and deleted items. the
|
||||
* function will return -1 indicating error.
|
||||
*
|
||||
* returns zero if the item already in the set and non-zero otherwise
|
||||
*/
|
||||
int simple_hashset_add(simple_hashset_t set, char* key, size_t key_len);
|
||||
|
||||
/* remove item from the hashset
|
||||
*
|
||||
* returns non-zero if the item was removed and zero if the item wasn't
|
||||
* exist
|
||||
*/
|
||||
int simple_hashset_remove(simple_hashset_t set, char *key, size_t key_len);
|
||||
|
||||
/* check if existence of the item
|
||||
*
|
||||
* returns non-zero if the item exists and zero otherwise
|
||||
*/
|
||||
int simple_hashset_is_member(simple_hashset_t set, char* key, size_t key_len);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// CK Hashset section
|
||||
|
||||
#define CK_HS_MODE_OBJECT 0
|
||||
|
@ -16,8 +69,20 @@ void ck_polyfill_init();
|
|||
struct ck_hs {
|
||||
// TODO
|
||||
};
|
||||
|
||||
typedef struct ck_hs ck_hs_t;
|
||||
|
||||
/*
|
||||
* Hash callback function.
|
||||
*/
|
||||
typedef unsigned long ck_hs_hash_cb_t(const void *, unsigned long);
|
||||
|
||||
/*
|
||||
* Returns pointer to object if objects are equivalent.
|
||||
*/
|
||||
typedef bool ck_hs_compare_cb_t(const void *, const void *);
|
||||
|
||||
/*
|
||||
CK_HS_HASH(hs, hs_hash, value);
|
||||
|
||||
bool ck_hs_init(ck_hs_t *, unsigned int, ck_hs_hash_cb_t *,
|
||||
|
@ -25,6 +90,7 @@ bool ck_hs_init(ck_hs_t *, unsigned int, ck_hs_hash_cb_t *,
|
|||
|
||||
void *ck_hs_get(ck_hs_t *, unsigned long, const void *);
|
||||
bool ck_hs_put(ck_hs_t *, unsigned long, const void *);
|
||||
*/
|
||||
|
||||
/*
|
||||
struct ck_hs {
|
||||
|
@ -40,6 +106,7 @@ typedef struct ck_hs ck_hs_t;
|
|||
|
||||
*/
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// CK Array section
|
||||
struct ck_array {
|
||||
pthread_mutex_t lock;
|
||||
|
@ -136,7 +203,8 @@ ck_array_commit(ck_array_t *array);
|
|||
_ck_i < tmpc; \
|
||||
_ck_i++, (*b) = tmp[_ck_i])
|
||||
|
||||
// CAS section
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// CK PR section
|
||||
bool
|
||||
ck_pr_cas_ptr(void *target, void *old_value, void *new_value);
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue