From 72a8adb5997a7f109c8e91b989f5c5d7f1503b76 Mon Sep 17 00:00:00 2001 From: Samy Al Bahra Date: Sun, 15 Jul 2012 16:44:11 -0400 Subject: [PATCH] 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. --- doc/ck_ht_init | 17 ++++-- include/ck_ht.h | 3 +- .../ck_ht/benchmark/parallel_bytestring.c | 3 +- regressions/ck_ht/benchmark/parallel_direct.c | 3 +- regressions/ck_ht/benchmark/serial.c | 3 +- regressions/ck_ht/validate/serial.c | 5 +- src/ck_ht.c | 52 ++++++++----------- 7 files changed, 44 insertions(+), 42 deletions(-) diff --git a/doc/ck_ht_init b/doc/ck_ht_init index e41ce12..4006f9b 100644 --- a/doc/ck_ht_init +++ b/doc/ck_ht_init @@ -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 diff --git a/include/ck_ht.h b/include/ck_ht.h index 7a7640b..ddd8f78 100644 --- a/include/ck_ht.h +++ b/include/ck_ht.h @@ -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 *); diff --git a/regressions/ck_ht/benchmark/parallel_bytestring.c b/regressions/ck_ht/benchmark/parallel_bytestring.c index 6d19b35..ef60fa5 100644 --- a/regressions/ck_ht/benchmark/parallel_bytestring.c +++ b/regressions/ck_ht/benchmark/parallel_bytestring.c @@ -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); } diff --git a/regressions/ck_ht/benchmark/parallel_direct.c b/regressions/ck_ht/benchmark/parallel_direct.c index 5f05a8e..0f1b3e9 100644 --- a/regressions/ck_ht/benchmark/parallel_direct.c +++ b/regressions/ck_ht/benchmark/parallel_direct.c @@ -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); } diff --git a/regressions/ck_ht/benchmark/serial.c b/regressions/ck_ht/benchmark/serial.c index 7d0d487..a50b328 100644 --- a/regressions/ck_ht/benchmark/serial.c +++ b/regressions/ck_ht/benchmark/serial.c @@ -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); } diff --git a/regressions/ck_ht/validate/serial.c b/regressions/ck_ht/validate/serial.c index f3d0ae5..200dbc3 100644 --- a/regressions/ck_ht/validate/serial.c +++ b/regressions/ck_ht/validate/serial.c @@ -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); } diff --git a/src/ck_ht.c b/src/ck_ht.c index cbcea08..8f71f42 100644 --- a/src/ck_ht.c +++ b/src/ck_ht.c @@ -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; }