Some improvements.
This commit is contained in:
parent
a245afb8de
commit
fea6eae9a6
@ -47,7 +47,15 @@ int main()
|
|||||||
const clock_t now = clock();
|
const clock_t now = clock();
|
||||||
if ((now < last_update) || (now >= last_update + CLOCKS_PER_SEC))
|
if ((now < last_update) || (now >= last_update + CLOCKS_PER_SEC))
|
||||||
{
|
{
|
||||||
printf("%zu\n", hash_set_size(hash_set));
|
size_t capacity, valid, deleted, limit;
|
||||||
|
if (!hash_set_info(hash_set, &capacity, &valid, &deleted, &limit))
|
||||||
|
{
|
||||||
|
printf("%010zu, %010zu, %010zu, %010zu\n", capacity, valid, deleted, limit);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("%zu\n", hash_set_size(hash_set));
|
||||||
|
}
|
||||||
last_update = now;
|
last_update = now;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,6 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define HASHSET_OPT_FAILFAST UINT16_C(0x1)
|
#define HASHSET_OPT_FAILFAST UINT16_C(0x1)
|
||||||
#define HASHSET_ITERATOR_INIT ((size_t)0U)
|
|
||||||
|
|
||||||
struct _hash_set;
|
struct _hash_set;
|
||||||
typedef struct _hash_set hash_set_t;
|
typedef struct _hash_set hash_set_t;
|
||||||
@ -29,6 +28,7 @@ errno_t hash_set_contains(const hash_set_t *const instance, const uint64_t value
|
|||||||
errno_t hash_set_iterate(const hash_set_t *const instance, size_t *const offset, uint64_t *const value);
|
errno_t hash_set_iterate(const hash_set_t *const instance, size_t *const offset, uint64_t *const value);
|
||||||
|
|
||||||
size_t hash_set_size(hash_set_t *const instance);
|
size_t hash_set_size(hash_set_t *const instance);
|
||||||
|
errno_t hash_set_info(hash_set_t *const instance, size_t *const capacity, size_t *const valid, size_t *const deleted, size_t *const limit);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ struct _hash_set
|
|||||||
{
|
{
|
||||||
double load_factor;
|
double load_factor;
|
||||||
uint16_t options;
|
uint16_t options;
|
||||||
size_t count, deleted, limit;
|
size_t valid, deleted, limit;
|
||||||
struct _hash_set_data data;
|
struct _hash_set_data data;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -52,21 +52,36 @@ struct _hash_set
|
|||||||
/* Math */
|
/* Math */
|
||||||
/* ------------------------------------------------- */
|
/* ------------------------------------------------- */
|
||||||
|
|
||||||
static FORCE_INLINE size_t round_sz(double d)
|
|
||||||
{
|
|
||||||
return (d >= 0.0) ? ((d > ((double)SIZE_MAX)) ? SIZE_MAX : ((size_t)(d + 0.5))) : 0U;
|
|
||||||
}
|
|
||||||
|
|
||||||
static FORCE_INLINE size_t div_ceil(const size_t value, const size_t divisor)
|
static FORCE_INLINE size_t div_ceil(const size_t value, const size_t divisor)
|
||||||
{
|
{
|
||||||
return (value / divisor) + ((value % divisor != 0U) ? 1U : 0U);
|
return (value / divisor) + ((value % divisor != 0U) ? 1U : 0U);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static FORCE_INLINE size_t round_sz(double d)
|
||||||
|
{
|
||||||
|
return (d >= 0.0) ? ((d + 0.5 >= ((double)SIZE_MAX)) ? SIZE_MAX : ((size_t)(d + 0.5))) : 0U;
|
||||||
|
}
|
||||||
|
|
||||||
static FORCE_INLINE size_t safe_mult2(const size_t value)
|
static FORCE_INLINE size_t safe_mult2(const size_t value)
|
||||||
{
|
{
|
||||||
return (value < (SIZE_MAX >> 1)) ? (value << 1) : SIZE_MAX;
|
return (value < (SIZE_MAX >> 1)) ? (value << 1) : SIZE_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static FORCE_INLINE size_t safe_add(const size_t a, const size_t b)
|
||||||
|
{
|
||||||
|
return ((SIZE_MAX - a) > b) ? (a + b) : SIZE_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
static FORCE_INLINE size_t safe_incr(const size_t value)
|
||||||
|
{
|
||||||
|
return (value < SIZE_MAX) ? (value + 1U) : SIZE_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
static FORCE_INLINE size_t safe_decr(const size_t value)
|
||||||
|
{
|
||||||
|
return (value > 0U) ? (value - 1U) : 0U;
|
||||||
|
}
|
||||||
|
|
||||||
static FORCE_INLINE size_t next_pow2(const size_t minimum)
|
static FORCE_INLINE size_t next_pow2(const size_t minimum)
|
||||||
{
|
{
|
||||||
size_t result = sizeof(uint64_t);
|
size_t result = sizeof(uint64_t);
|
||||||
@ -308,11 +323,11 @@ errno_t hash_set_insert(hash_set_t *const instance, const uint64_t value)
|
|||||||
return EEXIST;
|
return EEXIST;
|
||||||
}
|
}
|
||||||
|
|
||||||
while ((instance->count >= instance->limit) || (instance->count >= instance->data.capacity))
|
while ((safe_add(instance->valid, instance->deleted) >= instance->limit) || (instance->valid >= instance->data.capacity))
|
||||||
{
|
{
|
||||||
if (instance->data.capacity == SIZE_MAX)
|
if (instance->data.capacity == SIZE_MAX)
|
||||||
{
|
{
|
||||||
if ((instance->options & HASHSET_OPT_FAILFAST) || (instance->count >= instance->data.capacity))
|
if ((instance->options & HASHSET_OPT_FAILFAST) || (instance->valid >= instance->data.capacity))
|
||||||
{
|
{
|
||||||
return ENOMEM; /*malloc has failed!*/
|
return ENOMEM; /*malloc has failed!*/
|
||||||
}
|
}
|
||||||
@ -324,7 +339,7 @@ errno_t hash_set_insert(hash_set_t *const instance, const uint64_t value)
|
|||||||
{
|
{
|
||||||
if (error == ENOMEM)
|
if (error == ENOMEM)
|
||||||
{
|
{
|
||||||
if ((instance->options & HASHSET_OPT_FAILFAST) || (instance->count >= instance->data.capacity))
|
if ((instance->options & HASHSET_OPT_FAILFAST) || (instance->valid >= instance->data.capacity))
|
||||||
{
|
{
|
||||||
return ENOMEM; /*malloc has failed!*/
|
return ENOMEM; /*malloc has failed!*/
|
||||||
}
|
}
|
||||||
@ -347,10 +362,10 @@ errno_t hash_set_insert(hash_set_t *const instance, const uint64_t value)
|
|||||||
|
|
||||||
if (!store_value(&instance->data, index, value))
|
if (!store_value(&instance->data, index, value))
|
||||||
{
|
{
|
||||||
--instance->deleted;
|
instance->deleted = safe_decr(instance->deleted);
|
||||||
}
|
}
|
||||||
|
|
||||||
++instance->count;
|
instance->valid = safe_incr(instance->valid);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -379,11 +394,12 @@ errno_t hash_set_remove(hash_set_t *const instance, const uint64_t value)
|
|||||||
}
|
}
|
||||||
|
|
||||||
set_flag(instance->data.deleted, index);
|
set_flag(instance->data.deleted, index);
|
||||||
--instance->count;
|
instance->deleted = safe_incr(instance->deleted);
|
||||||
|
instance->valid = safe_decr(instance->valid);
|
||||||
|
|
||||||
if (++instance->deleted > (instance->data.capacity >> 1))
|
if (instance->deleted > (instance->data.capacity >> 1))
|
||||||
{
|
{
|
||||||
const errno_t error = rebuild_set(instance, next_pow2(round_sz(instance->count / instance->load_factor)));
|
const errno_t error = rebuild_set(instance, next_pow2(round_sz(instance->valid / instance->load_factor)));
|
||||||
if (error && ((error != ENOMEM) || (instance->options & HASHSET_OPT_FAILFAST)))
|
if (error && ((error != ENOMEM) || (instance->options & HASHSET_OPT_FAILFAST)))
|
||||||
{
|
{
|
||||||
return error;
|
return error;
|
||||||
@ -421,5 +437,32 @@ errno_t hash_set_iterate(const hash_set_t *const instance, size_t *const offset,
|
|||||||
|
|
||||||
size_t hash_set_size(hash_set_t *const instance)
|
size_t hash_set_size(hash_set_t *const instance)
|
||||||
{
|
{
|
||||||
return instance ? instance->count : 0U;
|
return instance ? instance->valid : 0U;
|
||||||
|
}
|
||||||
|
|
||||||
|
errno_t hash_set_info(hash_set_t *const instance, size_t *const capacity, size_t *const valid, size_t *const deleted, size_t *const limit)
|
||||||
|
{
|
||||||
|
if ((!instance) || (!instance->data.values))
|
||||||
|
{
|
||||||
|
return EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (capacity)
|
||||||
|
{
|
||||||
|
*capacity = instance->data.capacity;
|
||||||
|
}
|
||||||
|
if (valid)
|
||||||
|
{
|
||||||
|
*valid = instance->valid;
|
||||||
|
}
|
||||||
|
if (deleted)
|
||||||
|
{
|
||||||
|
*deleted = instance->deleted;
|
||||||
|
}
|
||||||
|
if (limit)
|
||||||
|
{
|
||||||
|
*limit = instance->limit;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user