|
|
@ -27,7 +27,6 @@
|
|
|
|
#define CK_HT_IM
|
|
|
|
#define CK_HT_IM
|
|
|
|
#include <ck_ht.h>
|
|
|
|
#include <ck_ht.h>
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef CK_F_HT
|
|
|
|
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
* This implementation borrows several techniques from Josh Dybnis's
|
|
|
|
* This implementation borrows several techniques from Josh Dybnis's
|
|
|
|
* nbds library which can be found at http://code.google.com/p/nbds
|
|
|
|
* nbds library which can be found at http://code.google.com/p/nbds
|
|
|
@ -82,15 +81,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
struct ck_ht_map {
|
|
|
|
struct ck_ht_map {
|
|
|
|
unsigned int mode;
|
|
|
|
unsigned int mode;
|
|
|
|
uint64_t deletions;
|
|
|
|
CK_HT_TYPE deletions;
|
|
|
|
uint64_t probe_maximum;
|
|
|
|
CK_HT_TYPE probe_maximum;
|
|
|
|
uint64_t probe_length;
|
|
|
|
CK_HT_TYPE probe_length;
|
|
|
|
uint64_t probe_limit;
|
|
|
|
CK_HT_TYPE probe_limit;
|
|
|
|
uint64_t size;
|
|
|
|
CK_HT_TYPE size;
|
|
|
|
uint64_t n_entries;
|
|
|
|
CK_HT_TYPE n_entries;
|
|
|
|
uint64_t mask;
|
|
|
|
CK_HT_TYPE mask;
|
|
|
|
uint64_t capacity;
|
|
|
|
CK_HT_TYPE capacity;
|
|
|
|
uint64_t step;
|
|
|
|
CK_HT_TYPE step;
|
|
|
|
CK_HT_WORD *probe_bound;
|
|
|
|
CK_HT_WORD *probe_bound;
|
|
|
|
struct ck_ht_entry *entries;
|
|
|
|
struct ck_ht_entry *entries;
|
|
|
|
};
|
|
|
|
};
|
|
|
@ -134,15 +133,15 @@ ck_ht_hash_wrapper(struct ck_ht_hash *h,
|
|
|
|
uint64_t seed)
|
|
|
|
uint64_t seed)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
h->value = MurmurHash64A(key, length, seed);
|
|
|
|
h->value = (unsigned long)MurmurHash64A(key, length, seed);
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static struct ck_ht_map *
|
|
|
|
static struct ck_ht_map *
|
|
|
|
ck_ht_map_create(struct ck_ht *table, uint64_t entries)
|
|
|
|
ck_ht_map_create(struct ck_ht *table, CK_HT_TYPE entries)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
struct ck_ht_map *map;
|
|
|
|
struct ck_ht_map *map;
|
|
|
|
uint64_t size;
|
|
|
|
CK_HT_TYPE size;
|
|
|
|
uintptr_t prefix;
|
|
|
|
uintptr_t prefix;
|
|
|
|
uint32_t n_entries;
|
|
|
|
uint32_t n_entries;
|
|
|
|
|
|
|
|
|
|
|
@ -193,12 +192,12 @@ ck_ht_map_create(struct ck_ht *table, uint64_t entries)
|
|
|
|
static inline void
|
|
|
|
static inline void
|
|
|
|
ck_ht_map_bound_set(struct ck_ht_map *m,
|
|
|
|
ck_ht_map_bound_set(struct ck_ht_map *m,
|
|
|
|
struct ck_ht_hash h,
|
|
|
|
struct ck_ht_hash h,
|
|
|
|
uint64_t n_probes)
|
|
|
|
CK_HT_TYPE n_probes)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
uint64_t offset = h.value & m->mask;
|
|
|
|
CK_HT_TYPE offset = h.value & m->mask;
|
|
|
|
|
|
|
|
|
|
|
|
if (n_probes > m->probe_maximum)
|
|
|
|
if (n_probes > m->probe_maximum)
|
|
|
|
ck_pr_store_64(&m->probe_maximum, n_probes);
|
|
|
|
CK_HT_TYPE_STORE(&m->probe_maximum, n_probes);
|
|
|
|
|
|
|
|
|
|
|
|
if (m->probe_bound != NULL && m->probe_bound[offset] < n_probes) {
|
|
|
|
if (m->probe_bound != NULL && m->probe_bound[offset] < n_probes) {
|
|
|
|
if (n_probes >= CK_HT_WORD_MAX)
|
|
|
|
if (n_probes >= CK_HT_WORD_MAX)
|
|
|
@ -211,18 +210,18 @@ ck_ht_map_bound_set(struct ck_ht_map *m,
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static inline uint64_t
|
|
|
|
static inline CK_HT_TYPE
|
|
|
|
ck_ht_map_bound_get(struct ck_ht_map *m, struct ck_ht_hash h)
|
|
|
|
ck_ht_map_bound_get(struct ck_ht_map *m, struct ck_ht_hash h)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
uint64_t offset = h.value & m->mask;
|
|
|
|
CK_HT_TYPE offset = h.value & m->mask;
|
|
|
|
uint64_t r = CK_HT_WORD_MAX;
|
|
|
|
CK_HT_TYPE r = CK_HT_WORD_MAX;
|
|
|
|
|
|
|
|
|
|
|
|
if (m->probe_bound != NULL) {
|
|
|
|
if (m->probe_bound != NULL) {
|
|
|
|
r = CK_HT_LOAD(&m->probe_bound[offset]);
|
|
|
|
r = CK_HT_LOAD(&m->probe_bound[offset]);
|
|
|
|
if (r == CK_HT_WORD_MAX)
|
|
|
|
if (r == CK_HT_WORD_MAX)
|
|
|
|
r = ck_pr_load_64(&m->probe_maximum);
|
|
|
|
r = CK_HT_TYPE_LOAD(&m->probe_maximum);
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
r = ck_pr_load_64(&m->probe_maximum);
|
|
|
|
r = CK_HT_TYPE_LOAD(&m->probe_maximum);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return r;
|
|
|
|
return r;
|
|
|
@ -256,7 +255,7 @@ ck_ht_init(struct ck_ht *table,
|
|
|
|
unsigned int mode,
|
|
|
|
unsigned int mode,
|
|
|
|
ck_ht_hash_cb_t *h,
|
|
|
|
ck_ht_hash_cb_t *h,
|
|
|
|
struct ck_malloc *m,
|
|
|
|
struct ck_malloc *m,
|
|
|
|
uint64_t entries,
|
|
|
|
CK_HT_TYPE entries,
|
|
|
|
uint64_t seed)
|
|
|
|
uint64_t seed)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
@ -284,19 +283,19 @@ ck_ht_map_probe_wr(struct ck_ht_map *map,
|
|
|
|
ck_ht_entry_t **available,
|
|
|
|
ck_ht_entry_t **available,
|
|
|
|
const void *key,
|
|
|
|
const void *key,
|
|
|
|
uint16_t key_length,
|
|
|
|
uint16_t key_length,
|
|
|
|
uint64_t *probe_limit,
|
|
|
|
CK_HT_TYPE *probe_limit,
|
|
|
|
uint64_t *probe_wr)
|
|
|
|
CK_HT_TYPE *probe_wr)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
struct ck_ht_entry *bucket, *cursor;
|
|
|
|
struct ck_ht_entry *bucket, *cursor;
|
|
|
|
struct ck_ht_entry *first = NULL;
|
|
|
|
struct ck_ht_entry *first = NULL;
|
|
|
|
size_t offset, i, j;
|
|
|
|
size_t offset, i, j;
|
|
|
|
uint64_t probes = 0;
|
|
|
|
CK_HT_TYPE probes = 0;
|
|
|
|
uint64_t limit;
|
|
|
|
CK_HT_TYPE limit;
|
|
|
|
|
|
|
|
|
|
|
|
if (probe_limit == NULL) {
|
|
|
|
if (probe_limit == NULL) {
|
|
|
|
limit = ck_ht_map_bound_get(map, h);
|
|
|
|
limit = ck_ht_map_bound_get(map, h);
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
limit = UINT64_MAX;
|
|
|
|
limit = CK_HT_TYPE_MAX;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
offset = h.value & map->mask;
|
|
|
|
offset = h.value & map->mask;
|
|
|
@ -388,11 +387,11 @@ ck_ht_gc(struct ck_ht *ht, unsigned long cycles, unsigned long seed)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
CK_HT_WORD *bounds = NULL;
|
|
|
|
CK_HT_WORD *bounds = NULL;
|
|
|
|
struct ck_ht_map *map = ht->map;
|
|
|
|
struct ck_ht_map *map = ht->map;
|
|
|
|
uint64_t maximum, i;
|
|
|
|
CK_HT_TYPE maximum, i;
|
|
|
|
uint64_t size = 0;
|
|
|
|
CK_HT_TYPE size = 0;
|
|
|
|
|
|
|
|
|
|
|
|
if (map->n_entries == 0) {
|
|
|
|
if (map->n_entries == 0) {
|
|
|
|
ck_pr_store_64(&map->probe_maximum, 0);
|
|
|
|
CK_HT_TYPE_STORE(&map->probe_maximum, 0);
|
|
|
|
if (map->probe_bound != NULL)
|
|
|
|
if (map->probe_bound != NULL)
|
|
|
|
memset(map->probe_bound, 0, sizeof(CK_HT_WORD) * map->capacity);
|
|
|
|
memset(map->probe_bound, 0, sizeof(CK_HT_WORD) * map->capacity);
|
|
|
|
|
|
|
|
|
|
|
@ -417,8 +416,8 @@ ck_ht_gc(struct ck_ht *ht, unsigned long cycles, unsigned long seed)
|
|
|
|
for (i = 0; i < map->capacity; i++) {
|
|
|
|
for (i = 0; i < map->capacity; i++) {
|
|
|
|
struct ck_ht_entry *entry, *priority, snapshot;
|
|
|
|
struct ck_ht_entry *entry, *priority, snapshot;
|
|
|
|
struct ck_ht_hash h;
|
|
|
|
struct ck_ht_hash h;
|
|
|
|
uint64_t probes_wr;
|
|
|
|
CK_HT_TYPE probes_wr;
|
|
|
|
uint64_t offset;
|
|
|
|
CK_HT_TYPE offset;
|
|
|
|
|
|
|
|
|
|
|
|
entry = &map->entries[(i + seed) & map->mask];
|
|
|
|
entry = &map->entries[(i + seed) & map->mask];
|
|
|
|
if (entry->key == CK_HT_KEY_EMPTY ||
|
|
|
|
if (entry->key == CK_HT_KEY_EMPTY ||
|
|
|
@ -452,17 +451,17 @@ ck_ht_gc(struct ck_ht *ht, unsigned long cycles, unsigned long seed)
|
|
|
|
offset = h.value & map->mask;
|
|
|
|
offset = h.value & map->mask;
|
|
|
|
|
|
|
|
|
|
|
|
if (priority != NULL) {
|
|
|
|
if (priority != NULL) {
|
|
|
|
ck_pr_store_64(&map->deletions, map->deletions + 1);
|
|
|
|
CK_HT_TYPE_STORE(&map->deletions, map->deletions + 1);
|
|
|
|
ck_pr_fence_store();
|
|
|
|
ck_pr_fence_store();
|
|
|
|
#ifndef CK_HT_PP
|
|
|
|
#ifndef CK_HT_PP
|
|
|
|
ck_pr_store_64(&priority->key_length, entry->key_length);
|
|
|
|
CK_HT_TYPE_STORE(&priority->key_length, entry->key_length);
|
|
|
|
ck_pr_store_64(&priority->hash, entry->hash);
|
|
|
|
CK_HT_TYPE_STORE(&priority->hash, entry->hash);
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
ck_pr_store_ptr_unsafe(&priority->value, (void *)entry->value);
|
|
|
|
ck_pr_store_ptr_unsafe(&priority->value, (void *)entry->value);
|
|
|
|
ck_pr_fence_store();
|
|
|
|
ck_pr_fence_store();
|
|
|
|
ck_pr_store_ptr_unsafe(&priority->key, (void *)entry->key);
|
|
|
|
ck_pr_store_ptr_unsafe(&priority->key, (void *)entry->key);
|
|
|
|
ck_pr_fence_store();
|
|
|
|
ck_pr_fence_store();
|
|
|
|
ck_pr_store_64(&map->deletions, map->deletions + 1);
|
|
|
|
CK_HT_TYPE_STORE(&map->deletions, map->deletions + 1);
|
|
|
|
ck_pr_fence_store();
|
|
|
|
ck_pr_fence_store();
|
|
|
|
ck_pr_store_ptr_unsafe(&entry->key, (void *)CK_HT_KEY_TOMBSTONE);
|
|
|
|
ck_pr_store_ptr_unsafe(&entry->key, (void *)CK_HT_KEY_TOMBSTONE);
|
|
|
|
ck_pr_fence_store();
|
|
|
|
ck_pr_fence_store();
|
|
|
@ -482,7 +481,7 @@ ck_ht_gc(struct ck_ht *ht, unsigned long cycles, unsigned long seed)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (maximum != map->probe_maximum)
|
|
|
|
if (maximum != map->probe_maximum)
|
|
|
|
ck_pr_store_64(&map->probe_maximum, maximum);
|
|
|
|
CK_HT_TYPE_STORE(&map->probe_maximum, maximum);
|
|
|
|
|
|
|
|
|
|
|
|
if (bounds != NULL) {
|
|
|
|
if (bounds != NULL) {
|
|
|
|
for (i = 0; i < map->capacity; i++)
|
|
|
|
for (i = 0; i < map->capacity; i++)
|
|
|
@ -503,12 +502,12 @@ ck_ht_map_probe_rd(struct ck_ht_map *map,
|
|
|
|
{
|
|
|
|
{
|
|
|
|
struct ck_ht_entry *bucket, *cursor;
|
|
|
|
struct ck_ht_entry *bucket, *cursor;
|
|
|
|
size_t offset, i, j;
|
|
|
|
size_t offset, i, j;
|
|
|
|
uint64_t probes = 0;
|
|
|
|
CK_HT_TYPE probes = 0;
|
|
|
|
uint64_t probe_maximum;
|
|
|
|
CK_HT_TYPE probe_maximum;
|
|
|
|
|
|
|
|
|
|
|
|
#ifndef CK_HT_PP
|
|
|
|
#ifndef CK_HT_PP
|
|
|
|
uint64_t d = 0;
|
|
|
|
CK_HT_TYPE d = 0;
|
|
|
|
uint64_t d_prime = 0;
|
|
|
|
CK_HT_TYPE d_prime = 0;
|
|
|
|
retry:
|
|
|
|
retry:
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
@ -537,11 +536,11 @@ retry:
|
|
|
|
ck_pr_fence_load();
|
|
|
|
ck_pr_fence_load();
|
|
|
|
snapshot->value = (uintptr_t)ck_pr_load_ptr(&cursor->value);
|
|
|
|
snapshot->value = (uintptr_t)ck_pr_load_ptr(&cursor->value);
|
|
|
|
#else
|
|
|
|
#else
|
|
|
|
d = ck_pr_load_64(&map->deletions);
|
|
|
|
d = CK_HT_TYPE_LOAD(&map->deletions);
|
|
|
|
snapshot->key = (uintptr_t)ck_pr_load_ptr(&cursor->key);
|
|
|
|
snapshot->key = (uintptr_t)ck_pr_load_ptr(&cursor->key);
|
|
|
|
ck_pr_fence_load();
|
|
|
|
ck_pr_fence_load();
|
|
|
|
snapshot->key_length = ck_pr_load_64(&cursor->key_length);
|
|
|
|
snapshot->key_length = CK_HT_TYPE_LOAD(&cursor->key_length);
|
|
|
|
snapshot->hash = ck_pr_load_64(&cursor->hash);
|
|
|
|
snapshot->hash = CK_HT_TYPE_LOAD(&cursor->hash);
|
|
|
|
snapshot->value = (uintptr_t)ck_pr_load_ptr(&cursor->value);
|
|
|
|
snapshot->value = (uintptr_t)ck_pr_load_ptr(&cursor->value);
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
@ -576,7 +575,7 @@ retry:
|
|
|
|
if (snapshot->hash != h.value)
|
|
|
|
if (snapshot->hash != h.value)
|
|
|
|
continue;
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
|
|
d_prime = ck_pr_load_64(&map->deletions);
|
|
|
|
d_prime = CK_HT_TYPE_LOAD(&map->deletions);
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
* It is possible that the slot was
|
|
|
|
* It is possible that the slot was
|
|
|
@ -601,12 +600,12 @@ leave:
|
|
|
|
return cursor;
|
|
|
|
return cursor;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
uint64_t
|
|
|
|
CK_HT_TYPE
|
|
|
|
ck_ht_count(struct ck_ht *table)
|
|
|
|
ck_ht_count(struct ck_ht *table)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
struct ck_ht_map *map = ck_pr_load_ptr(&table->map);
|
|
|
|
struct ck_ht_map *map = ck_pr_load_ptr(&table->map);
|
|
|
|
|
|
|
|
|
|
|
|
return ck_pr_load_64(&map->n_entries);
|
|
|
|
return CK_HT_TYPE_LOAD(&map->n_entries);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
bool
|
|
|
@ -634,7 +633,7 @@ ck_ht_next(struct ck_ht *table,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
bool
|
|
|
|
ck_ht_reset_size_spmc(struct ck_ht *table, uint64_t size)
|
|
|
|
ck_ht_reset_size_spmc(struct ck_ht *table, CK_HT_TYPE size)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
struct ck_ht_map *map, *update;
|
|
|
|
struct ck_ht_map *map, *update;
|
|
|
|
|
|
|
|
|
|
|
@ -657,13 +656,13 @@ ck_ht_reset_spmc(struct ck_ht *table)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
bool
|
|
|
|
ck_ht_grow_spmc(struct ck_ht *table, uint64_t capacity)
|
|
|
|
ck_ht_grow_spmc(struct ck_ht *table, CK_HT_TYPE capacity)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
struct ck_ht_map *map, *update;
|
|
|
|
struct ck_ht_map *map, *update;
|
|
|
|
struct ck_ht_entry *bucket, *previous;
|
|
|
|
struct ck_ht_entry *bucket, *previous;
|
|
|
|
struct ck_ht_hash h;
|
|
|
|
struct ck_ht_hash h;
|
|
|
|
size_t k, i, j, offset;
|
|
|
|
size_t k, i, j, offset;
|
|
|
|
uint64_t probes;
|
|
|
|
CK_HT_TYPE probes;
|
|
|
|
|
|
|
|
|
|
|
|
restart:
|
|
|
|
restart:
|
|
|
|
map = table->map;
|
|
|
|
map = table->map;
|
|
|
@ -772,7 +771,7 @@ ck_ht_remove_spmc(struct ck_ht *table,
|
|
|
|
|
|
|
|
|
|
|
|
ck_pr_store_ptr_unsafe(&candidate->key, (void *)CK_HT_KEY_TOMBSTONE);
|
|
|
|
ck_pr_store_ptr_unsafe(&candidate->key, (void *)CK_HT_KEY_TOMBSTONE);
|
|
|
|
ck_pr_fence_store();
|
|
|
|
ck_pr_fence_store();
|
|
|
|
ck_pr_store_64(&map->n_entries, map->n_entries - 1);
|
|
|
|
CK_HT_TYPE_STORE(&map->n_entries, map->n_entries - 1);
|
|
|
|
return true;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -783,7 +782,7 @@ ck_ht_get_spmc(struct ck_ht *table,
|
|
|
|
{
|
|
|
|
{
|
|
|
|
struct ck_ht_entry *candidate, snapshot;
|
|
|
|
struct ck_ht_entry *candidate, snapshot;
|
|
|
|
struct ck_ht_map *map;
|
|
|
|
struct ck_ht_map *map;
|
|
|
|
uint64_t d, d_prime;
|
|
|
|
CK_HT_TYPE d, d_prime;
|
|
|
|
|
|
|
|
|
|
|
|
restart:
|
|
|
|
restart:
|
|
|
|
map = ck_pr_load_ptr(&table->map);
|
|
|
|
map = ck_pr_load_ptr(&table->map);
|
|
|
@ -792,7 +791,7 @@ restart:
|
|
|
|
* Platforms that cannot read key and key_length atomically must reprobe
|
|
|
|
* Platforms that cannot read key and key_length atomically must reprobe
|
|
|
|
* on the scan of any single entry.
|
|
|
|
* on the scan of any single entry.
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
d = ck_pr_load_64(&map->deletions);
|
|
|
|
d = CK_HT_TYPE_LOAD(&map->deletions);
|
|
|
|
|
|
|
|
|
|
|
|
if (table->mode & CK_HT_MODE_BYTESTRING) {
|
|
|
|
if (table->mode & CK_HT_MODE_BYTESTRING) {
|
|
|
|
candidate = ck_ht_map_probe_rd(map, h, &snapshot,
|
|
|
|
candidate = ck_ht_map_probe_rd(map, h, &snapshot,
|
|
|
@ -802,7 +801,7 @@ restart:
|
|
|
|
(void *)entry->key, sizeof(entry->key));
|
|
|
|
(void *)entry->key, sizeof(entry->key));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
d_prime = ck_pr_load_64(&map->deletions);
|
|
|
|
d_prime = CK_HT_TYPE_LOAD(&map->deletions);
|
|
|
|
if (d != d_prime) {
|
|
|
|
if (d != d_prime) {
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
* It is possible we have read (K, V'). Only valid states are
|
|
|
|
* It is possible we have read (K, V'). Only valid states are
|
|
|
@ -826,7 +825,7 @@ ck_ht_set_spmc(struct ck_ht *table,
|
|
|
|
{
|
|
|
|
{
|
|
|
|
struct ck_ht_entry snapshot, *candidate, *priority;
|
|
|
|
struct ck_ht_entry snapshot, *candidate, *priority;
|
|
|
|
struct ck_ht_map *map;
|
|
|
|
struct ck_ht_map *map;
|
|
|
|
uint64_t probes, probes_wr;
|
|
|
|
CK_HT_TYPE probes, probes_wr;
|
|
|
|
bool empty = false;
|
|
|
|
bool empty = false;
|
|
|
|
|
|
|
|
|
|
|
|
for (;;) {
|
|
|
|
for (;;) {
|
|
|
@ -873,8 +872,8 @@ ck_ht_set_spmc(struct ck_ht *table,
|
|
|
|
probes = probes_wr;
|
|
|
|
probes = probes_wr;
|
|
|
|
|
|
|
|
|
|
|
|
#ifndef CK_HT_PP
|
|
|
|
#ifndef CK_HT_PP
|
|
|
|
ck_pr_store_64(&priority->key_length, entry->key_length);
|
|
|
|
CK_HT_TYPE_STORE(&priority->key_length, entry->key_length);
|
|
|
|
ck_pr_store_64(&priority->hash, entry->hash);
|
|
|
|
CK_HT_TYPE_STORE(&priority->hash, entry->hash);
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
/*
|
|
|
@ -883,7 +882,7 @@ ck_ht_set_spmc(struct ck_ht *table,
|
|
|
|
* a tombstone.
|
|
|
|
* a tombstone.
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
if (priority->value == CK_HT_KEY_TOMBSTONE) {
|
|
|
|
if (priority->value == CK_HT_KEY_TOMBSTONE) {
|
|
|
|
ck_pr_store_64(&map->deletions, map->deletions + 1);
|
|
|
|
CK_HT_TYPE_STORE(&map->deletions, map->deletions + 1);
|
|
|
|
ck_pr_fence_store();
|
|
|
|
ck_pr_fence_store();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -896,7 +895,7 @@ ck_ht_set_spmc(struct ck_ht *table,
|
|
|
|
* Make sure that readers who observe the tombstone would
|
|
|
|
* Make sure that readers who observe the tombstone would
|
|
|
|
* also observe counter change.
|
|
|
|
* also observe counter change.
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
ck_pr_store_64(&map->deletions, map->deletions + 1);
|
|
|
|
CK_HT_TYPE_STORE(&map->deletions, map->deletions + 1);
|
|
|
|
ck_pr_fence_store();
|
|
|
|
ck_pr_fence_store();
|
|
|
|
|
|
|
|
|
|
|
|
ck_pr_store_ptr_unsafe(&candidate->key, (void *)CK_HT_KEY_TOMBSTONE);
|
|
|
|
ck_pr_store_ptr_unsafe(&candidate->key, (void *)CK_HT_KEY_TOMBSTONE);
|
|
|
@ -913,7 +912,7 @@ ck_ht_set_spmc(struct ck_ht *table,
|
|
|
|
|
|
|
|
|
|
|
|
if (priority != NULL) {
|
|
|
|
if (priority != NULL) {
|
|
|
|
if (priority->key == CK_HT_KEY_TOMBSTONE) {
|
|
|
|
if (priority->key == CK_HT_KEY_TOMBSTONE) {
|
|
|
|
ck_pr_store_64(&map->deletions, map->deletions + 1);
|
|
|
|
CK_HT_TYPE_STORE(&map->deletions, map->deletions + 1);
|
|
|
|
ck_pr_fence_store();
|
|
|
|
ck_pr_fence_store();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -926,8 +925,8 @@ ck_ht_set_spmc(struct ck_ht *table,
|
|
|
|
ck_pr_fence_store();
|
|
|
|
ck_pr_fence_store();
|
|
|
|
ck_pr_store_ptr_unsafe(&candidate->key, (void *)entry->key);
|
|
|
|
ck_pr_store_ptr_unsafe(&candidate->key, (void *)entry->key);
|
|
|
|
#else
|
|
|
|
#else
|
|
|
|
ck_pr_store_64(&candidate->key_length, entry->key_length);
|
|
|
|
CK_HT_TYPE_STORE(&candidate->key_length, entry->key_length);
|
|
|
|
ck_pr_store_64(&candidate->hash, entry->hash);
|
|
|
|
CK_HT_TYPE_STORE(&candidate->hash, entry->hash);
|
|
|
|
ck_pr_store_ptr_unsafe(&candidate->value, (void *)entry->value);
|
|
|
|
ck_pr_store_ptr_unsafe(&candidate->value, (void *)entry->value);
|
|
|
|
ck_pr_fence_store();
|
|
|
|
ck_pr_fence_store();
|
|
|
|
ck_pr_store_ptr_unsafe(&candidate->key, (void *)entry->key);
|
|
|
|
ck_pr_store_ptr_unsafe(&candidate->key, (void *)entry->key);
|
|
|
@ -938,7 +937,7 @@ ck_ht_set_spmc(struct ck_ht *table,
|
|
|
|
* of entries associated with map.
|
|
|
|
* of entries associated with map.
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
if (replace == false)
|
|
|
|
if (replace == false)
|
|
|
|
ck_pr_store_64(&map->n_entries, map->n_entries + 1);
|
|
|
|
CK_HT_TYPE_STORE(&map->n_entries, map->n_entries + 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ck_ht_map_bound_set(map, h, probes);
|
|
|
|
ck_ht_map_bound_set(map, h, probes);
|
|
|
@ -963,7 +962,7 @@ ck_ht_put_spmc(struct ck_ht *table,
|
|
|
|
{
|
|
|
|
{
|
|
|
|
struct ck_ht_entry snapshot, *candidate, *priority;
|
|
|
|
struct ck_ht_entry snapshot, *candidate, *priority;
|
|
|
|
struct ck_ht_map *map;
|
|
|
|
struct ck_ht_map *map;
|
|
|
|
uint64_t probes, probes_wr;
|
|
|
|
CK_HT_TYPE probes, probes_wr;
|
|
|
|
|
|
|
|
|
|
|
|
for (;;) {
|
|
|
|
for (;;) {
|
|
|
|
map = table->map;
|
|
|
|
map = table->map;
|
|
|
@ -989,7 +988,7 @@ ck_ht_put_spmc(struct ck_ht *table,
|
|
|
|
|
|
|
|
|
|
|
|
if (priority != NULL) {
|
|
|
|
if (priority != NULL) {
|
|
|
|
/* Version counter is updated before re-use. */
|
|
|
|
/* Version counter is updated before re-use. */
|
|
|
|
ck_pr_store_64(&map->deletions, map->deletions + 1);
|
|
|
|
CK_HT_TYPE_STORE(&map->deletions, map->deletions + 1);
|
|
|
|
ck_pr_fence_store();
|
|
|
|
ck_pr_fence_store();
|
|
|
|
|
|
|
|
|
|
|
|
/* Re-use tombstone if one was found. */
|
|
|
|
/* Re-use tombstone if one was found. */
|
|
|
@ -1012,14 +1011,14 @@ ck_ht_put_spmc(struct ck_ht *table,
|
|
|
|
ck_pr_fence_store();
|
|
|
|
ck_pr_fence_store();
|
|
|
|
ck_pr_store_ptr_unsafe(&candidate->key, (void *)entry->key);
|
|
|
|
ck_pr_store_ptr_unsafe(&candidate->key, (void *)entry->key);
|
|
|
|
#else
|
|
|
|
#else
|
|
|
|
ck_pr_store_64(&candidate->key_length, entry->key_length);
|
|
|
|
CK_HT_TYPE_STORE(&candidate->key_length, entry->key_length);
|
|
|
|
ck_pr_store_64(&candidate->hash, entry->hash);
|
|
|
|
CK_HT_TYPE_STORE(&candidate->hash, entry->hash);
|
|
|
|
ck_pr_store_ptr_unsafe(&candidate->value, (void *)entry->value);
|
|
|
|
ck_pr_store_ptr_unsafe(&candidate->value, (void *)entry->value);
|
|
|
|
ck_pr_fence_store();
|
|
|
|
ck_pr_fence_store();
|
|
|
|
ck_pr_store_ptr_unsafe(&candidate->key, (void *)entry->key);
|
|
|
|
ck_pr_store_ptr_unsafe(&candidate->key, (void *)entry->key);
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
ck_pr_store_64(&map->n_entries, map->n_entries + 1);
|
|
|
|
CK_HT_TYPE_STORE(&map->n_entries, map->n_entries + 1);
|
|
|
|
|
|
|
|
|
|
|
|
/* Enforce a load factor of 0.5. */
|
|
|
|
/* Enforce a load factor of 0.5. */
|
|
|
|
if (map->n_entries * 2 > map->capacity)
|
|
|
|
if (map->n_entries * 2 > map->capacity)
|
|
|
@ -1035,5 +1034,3 @@ ck_ht_destroy(struct ck_ht *table)
|
|
|
|
ck_ht_map_destroy(table->m, table->map, false);
|
|
|
|
ck_ht_map_destroy(table->m, table->map, false);
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endif /* CK_F_HT */
|
|
|
|
|
|
|
|