mirror of
https://github.com/justinethier/cyclone.git
synced 2025-05-24 04:25:06 +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);
|
pthread_mutex_unlock(&glock);
|
||||||
return result;
|
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();
|
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
|
// CK Hashset section
|
||||||
|
|
||||||
#define CK_HS_MODE_OBJECT 0
|
#define CK_HS_MODE_OBJECT 0
|
||||||
|
@ -16,8 +69,20 @@ void ck_polyfill_init();
|
||||||
struct ck_hs {
|
struct ck_hs {
|
||||||
// TODO
|
// TODO
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct ck_hs ck_hs_t;
|
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);
|
CK_HS_HASH(hs, hs_hash, value);
|
||||||
|
|
||||||
bool ck_hs_init(ck_hs_t *, unsigned int, ck_hs_hash_cb_t *,
|
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 *);
|
void *ck_hs_get(ck_hs_t *, unsigned long, const void *);
|
||||||
bool ck_hs_put(ck_hs_t *, unsigned long, const void *);
|
bool ck_hs_put(ck_hs_t *, unsigned long, const void *);
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
struct ck_hs {
|
struct ck_hs {
|
||||||
|
@ -40,6 +106,7 @@ typedef struct ck_hs ck_hs_t;
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// CK Array section
|
// CK Array section
|
||||||
struct ck_array {
|
struct ck_array {
|
||||||
pthread_mutex_t lock;
|
pthread_mutex_t lock;
|
||||||
|
@ -136,7 +203,8 @@ ck_array_commit(ck_array_t *array);
|
||||||
_ck_i < tmpc; \
|
_ck_i < tmpc; \
|
||||||
_ck_i++, (*b) = tmp[_ck_i])
|
_ck_i++, (*b) = tmp[_ck_i])
|
||||||
|
|
||||||
// CAS section
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// CK PR section
|
||||||
bool
|
bool
|
||||||
ck_pr_cas_ptr(void *target, void *old_value, void *new_value);
|
ck_pr_cas_ptr(void *target, void *old_value, void *new_value);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue