ck_ht: Add support for per-hash-table allocator.

Documentation and regressions tests have been updated to reflect this.
This functionality allows for individual hash tables use to different
allocation functions. Thanks to Wez Furlong for pointing out the necessary
documentation update for ck_ht.
ck_pring
Samy Al Bahra 13 years ago
parent af7b877414
commit 72a8adb599

@ -36,7 +36,7 @@ Concurrency Kit (libck, \-lck)
.Ft typedef void
.Fn ck_ht_hash_cb_t "ck_ht_hash_t *h" "const void *key" "size_t key_length" "uint64_t seed"
.Ft bool
.Fn ck_ht_init "ck_ht_t *ht" "enum ck_ht_mode mode" "ck_ht_hash_cb_t hash_function" "uint64_t capacity" "uint64_t seed"
.Fn ck_ht_init "ck_ht_t *ht" "enum ck_ht_mode mode" "ck_ht_hash_cb_t *hash_function" "struct ck_malloc *allocator" "uint64_t capacity" "uint64_t seed"
.Sh DESCRIPTION
The
.Fn ck_ht_init
@ -63,7 +63,8 @@ to be interacted with using the
.Xr ck_ht_entry_value 3 ,
and
.Xr ck_ht_entry_set 3
functions.
functions. Attempting a hash table operation with a key of value
NULL or (void *)UINTPTR_MAX will result in undefined behavior.
.It CK_HT_MODE_DIRECT
The hash table is meant to store key-value pointers where
the key is of fixed width field compatible with the
@ -76,7 +77,8 @@ with using the
.Xr ck_ht_entry_value_direct 3
and
.Xr ck_entry_set_direct 3
functions.
functions. Attempting a hash table operation with a key of value of 0 or
UINTPTR_MAX will result in undefined behavior.
.El
.Pp
The argument
@ -106,6 +108,15 @@ argument is the initial seed associated with the hash table.
This initial seed is specified by the user in
.Xr ck_ht_init 3 .
.Pp
The
.Fa allocator
argument is a pointer to a structure containing
.Fa malloc
and
.Fa free
function pointers which respectively define the memory allocation and
destruction functions to be used by the hash table being initialized.
.Pp
The argument
.Fa capacity
represents the initial number of key-value pairs the hash

@ -78,6 +78,7 @@ typedef void ck_ht_hash_cb_t(ck_ht_hash_t *, const void *, size_t, uint64_t);
struct ck_ht_map;
struct ck_ht {
struct ck_malloc *m;
struct ck_ht_map *map;
enum ck_ht_mode mode;
uint64_t seed;
@ -219,7 +220,7 @@ bool ck_ht_next(ck_ht_t *, ck_ht_iterator_t *, ck_ht_entry_t **entry);
void ck_ht_hash(ck_ht_hash_t *, ck_ht_t *, const void *, uint16_t);
void ck_ht_hash_direct(ck_ht_hash_t *, ck_ht_t *, uintptr_t);
bool ck_ht_allocator_set(struct ck_malloc *);
bool ck_ht_init(ck_ht_t *, enum ck_ht_mode, ck_ht_hash_cb_t *, uint64_t, uint64_t);
bool ck_ht_init(ck_ht_t *, enum ck_ht_mode, ck_ht_hash_cb_t *, struct ck_malloc *, uint64_t, uint64_t);
void ck_ht_destroy(ck_ht_t *);
bool ck_ht_set_spmc(ck_ht_t *, ck_ht_hash_t, ck_ht_entry_t *);
bool ck_ht_put_spmc(ck_ht_t *, ck_ht_hash_t, ck_ht_entry_t *);

@ -126,8 +126,7 @@ table_init(void)
ck_epoch_init(&epoch_ht, 10);
ck_epoch_register(&epoch_ht, &epoch_wr);
srand48((long int)time(NULL));
ck_ht_allocator_set(&my_allocator);
if (ck_ht_init(&ht, CK_HT_MODE_BYTESTRING, NULL, 8, lrand48()) == false) {
if (ck_ht_init(&ht, CK_HT_MODE_BYTESTRING, NULL, &my_allocator, 8, lrand48()) == false) {
perror("ck_ht_init");
exit(EXIT_FAILURE);
}

@ -136,8 +136,7 @@ table_init(void)
ck_epoch_init(&epoch_ht, 10);
ck_epoch_register(&epoch_ht, &epoch_wr);
srand48((long int)time(NULL));
ck_ht_allocator_set(&my_allocator);
if (ck_ht_init(&ht, CK_HT_MODE_DIRECT, hash_function, 8, lrand48()) == false) {
if (ck_ht_init(&ht, CK_HT_MODE_DIRECT, hash_function, &my_allocator, 8, lrand48()) == false) {
perror("ck_ht_init");
exit(EXIT_FAILURE);
}

@ -73,8 +73,7 @@ table_init(void)
{
srand48((long int)time(NULL));
ck_ht_allocator_set(&my_allocator);
if (ck_ht_init(&ht, CK_HT_MODE_BYTESTRING, NULL, 8, lrand48()) == false) {
if (ck_ht_init(&ht, CK_HT_MODE_BYTESTRING, NULL, &my_allocator, 8, lrand48()) == false) {
perror("ck_ht_init");
exit(EXIT_FAILURE);
}

@ -77,8 +77,7 @@ main(void)
ck_ht_iterator_t iterator = CK_HT_ITERATOR_INITIALIZER;
ck_ht_entry_t *cursor;
ck_ht_allocator_set(&my_allocator);
if (ck_ht_init(&ht, CK_HT_MODE_BYTESTRING, NULL, 8, 6602834) == false) {
if (ck_ht_init(&ht, CK_HT_MODE_BYTESTRING, NULL, &my_allocator, 8, 6602834) == false) {
perror("ck_ht_init");
exit(EXIT_FAILURE);
}
@ -247,7 +246,7 @@ main(void)
}
ck_ht_destroy(&ht);
if (ck_ht_init(&ht, CK_HT_MODE_DIRECT, NULL, 8, 6602834) == false) {
if (ck_ht_init(&ht, CK_HT_MODE_DIRECT, NULL, &my_allocator, 8, 6602834) == false) {
perror("ck_ht_init");
exit(EXIT_FAILURE);
}

@ -74,8 +74,6 @@ struct ck_ht_map {
struct ck_ht_entry *entries;
};
static struct ck_malloc allocator;
void
ck_ht_hash(struct ck_ht_hash *h,
struct ck_ht *table,
@ -108,21 +106,8 @@ ck_ht_hash_wrapper(struct ck_ht_hash *h,
return;
}
bool
ck_ht_allocator_set(struct ck_malloc *m)
{
if (m->malloc == NULL || m->free == NULL)
return false;
allocator.malloc = m->malloc;
allocator.free = m->free;
return true;
}
static struct ck_ht_map *
ck_ht_map_create(enum ck_ht_mode mode, uint64_t entries)
ck_ht_map_create(struct ck_ht *table, uint64_t entries)
{
struct ck_ht_map *map;
uint64_t size, n_entries;
@ -131,11 +116,11 @@ ck_ht_map_create(enum ck_ht_mode mode, uint64_t entries)
size = sizeof(struct ck_ht_map) +
(sizeof(struct ck_ht_entry) * n_entries + CK_MD_CACHELINE - 1);
map = allocator.malloc(size);
map = table->m->malloc(size);
if (map == NULL)
return NULL;
map->mode = mode;
map->mode = table->mode;
map->size = size;
map->probe_limit = ck_internal_max_64(n_entries >>
(CK_HT_BUCKET_SHIFT + 2), CK_HT_PROBE_DEFAULT);
@ -150,7 +135,7 @@ ck_ht_map_create(enum ck_ht_mode mode, uint64_t entries)
CK_MD_CACHELINE - 1) & ~(CK_MD_CACHELINE - 1));
if (map->entries == NULL) {
allocator.free(map, size, false);
table->m->free(map, size, false);
return NULL;
}
@ -159,10 +144,10 @@ ck_ht_map_create(enum ck_ht_mode mode, uint64_t entries)
}
static void
ck_ht_map_destroy(struct ck_ht_map *map, bool defer)
ck_ht_map_destroy(struct ck_malloc *m, struct ck_ht_map *map, bool defer)
{
allocator.free(map, map->size, defer);
m->free(map, map->size, defer);
return;
}
@ -180,9 +165,18 @@ ck_ht_map_probe_next(struct ck_ht_map *map, size_t offset, ck_ht_hash_t h)
}
bool
ck_ht_init(ck_ht_t *table, enum ck_ht_mode mode, ck_ht_hash_cb_t *h, uint64_t entries, uint64_t seed)
ck_ht_init(ck_ht_t *table,
enum ck_ht_mode mode,
ck_ht_hash_cb_t *h,
struct ck_malloc *m,
uint64_t entries,
uint64_t seed)
{
if (m == NULL || m->malloc == NULL || m->free == NULL)
return false;
table->m = m;
table->mode = mode;
table->seed = seed;
@ -192,7 +186,7 @@ ck_ht_init(ck_ht_t *table, enum ck_ht_mode mode, ck_ht_hash_cb_t *h, uint64_t en
table->h = h;
}
table->map = ck_ht_map_create(mode, entries);
table->map = ck_ht_map_create(table, entries);
return table->map != NULL;
}
@ -369,12 +363,12 @@ ck_ht_reset_spmc(struct ck_ht *table)
struct ck_ht_map *map, *update;
map = table->map;
update = ck_ht_map_create(table->mode, map->capacity);
update = ck_ht_map_create(table, map->capacity);
if (update == NULL)
return false;
ck_pr_store_ptr(&table->map, update);
ck_ht_map_destroy(map, true);
ck_ht_map_destroy(table->m, map, true);
return true;
}
@ -393,7 +387,7 @@ restart:
if (map->capacity >= capacity)
return false;
update = ck_ht_map_create(table->mode, capacity);
update = ck_ht_map_create(table, capacity);
if (update == NULL)
return false;
@ -447,7 +441,7 @@ restart:
* We have hit the probe limit, the map needs to be even
* larger.
*/
ck_ht_map_destroy(update, false);
ck_ht_map_destroy(table->m, update, false);
capacity <<= 1;
goto restart;
}
@ -455,7 +449,7 @@ restart:
ck_pr_fence_store();
ck_pr_store_ptr(&table->map, update);
ck_ht_map_destroy(map, true);
ck_ht_map_destroy(table->m, map, true);
return true;
}
@ -720,7 +714,7 @@ void
ck_ht_destroy(struct ck_ht *table)
{
ck_ht_map_destroy(table->map, false);
ck_ht_map_destroy(table->m, table->map, false);
return;
}

Loading…
Cancel
Save