struct hashmap_entry *iterate_list_head, *iterate_list_tail;
unsigned n_entries;
-
- bool from_pool;
};
#define BY_HASH(h) ((struct hashmap_entry**) ((uint8_t*) (h) + ALIGN(sizeof(Hashmap))))
-struct pool {
- struct pool *next;
- unsigned n_tiles;
- unsigned n_used;
-};
-
-static struct pool *first_hashmap_pool = NULL;
-static void *first_hashmap_tile = NULL;
-
-static struct pool *first_entry_pool = NULL;
-static void *first_entry_tile = NULL;
-
-static void* allocate_tile(struct pool **first_pool, void **first_tile, size_t tile_size) {
- unsigned i;
-
- if (*first_tile) {
- void *r;
-
- r = *first_tile;
- *first_tile = * (void**) (*first_tile);
- return r;
- }
-
- if (_unlikely_(!*first_pool) || _unlikely_((*first_pool)->n_used >= (*first_pool)->n_tiles)) {
- unsigned n;
- size_t size;
- struct pool *p;
-
- n = *first_pool ? (*first_pool)->n_tiles : 0;
- n = MAX(512U, n * 2);
- size = PAGE_ALIGN(ALIGN(sizeof(struct pool)) + n*tile_size);
- n = (size - ALIGN(sizeof(struct pool))) / tile_size;
-
- p = malloc(size);
- if (!p)
- return NULL;
-
- p->next = *first_pool;
- p->n_tiles = n;
- p->n_used = 0;
-
- *first_pool = p;
- }
-
- i = (*first_pool)->n_used++;
-
- return ((uint8_t*) (*first_pool)) + ALIGN(sizeof(struct pool)) + i*tile_size;
-}
-
-static void deallocate_tile(void **first_tile, void *p) {
- * (void**) p = *first_tile;
- *first_tile = p;
-}
-
-#ifndef __OPTIMIZE__
-
-static void drop_pool(struct pool *p) {
- while (p) {
- struct pool *n;
- n = p->next;
- free(p);
- p = n;
- }
-}
-
-__attribute__((destructor)) static void cleanup_pool(void) {
- /* Be nice to valgrind */
-
- drop_pool(first_hashmap_pool);
- drop_pool(first_entry_pool);
-}
-
-#endif
-
unsigned string_hash_func(const void *p) {
unsigned hash = 5381;
const signed char *c;
}
Hashmap *hashmap_new(hash_func_t hash_func, compare_func_t compare_func) {
- bool b;
Hashmap *h;
size_t size;
- b = is_main_thread();
-
size = ALIGN(sizeof(Hashmap)) + NBUCKETS * sizeof(struct hashmap_entry*);
- if (b) {
- h = allocate_tile(&first_hashmap_pool, &first_hashmap_tile, size);
- if (!h)
- return NULL;
+ h = malloc0(size);
- memset(h, 0, size);
- } else {
- h = malloc0(size);
-
- if (!h)
- return NULL;
- }
+ if (!h)
+ return NULL;
h->hash_func = hash_func ? hash_func : trivial_hash_func;
h->compare_func = compare_func ? compare_func : trivial_compare_func;
h->n_entries = 0;
h->iterate_list_head = h->iterate_list_tail = NULL;
- h->from_pool = b;
-
return h;
}
h->n_entries--;
}
-static void remove_entry(Hashmap *h, struct hashmap_entry *e) {
+static void remove_entry(Hashmap *h, struct hashmap_entry **ep) {
+ struct hashmap_entry *e = *ep;
unsigned hash;
assert(h);
unlink_entry(h, e, hash);
- if (h->from_pool)
- deallocate_tile(&first_entry_tile, e);
- else
- free(e);
+ free(e);
+ *ep = NULL;
}
void hashmap_free(Hashmap*h) {
hashmap_clear(h);
- if (h->from_pool)
- deallocate_tile(&first_hashmap_tile, h);
- else
- free(h);
+ free(h);
}
void hashmap_free_free(Hashmap *h) {
if (!h)
return;
- while (h->iterate_list_head)
- remove_entry(h, h->iterate_list_head);
+ while (h->iterate_list_head) {
+ struct hashmap_entry *e = h->iterate_list_head;
+ remove_entry(h, &e);
+ }
}
static struct hashmap_entry *hash_scan(Hashmap *h, unsigned hash, const void *key) {
return -EEXIST;
}
- if (h->from_pool)
- e = allocate_tile(&first_entry_pool, &first_entry_tile, sizeof(struct hashmap_entry));
- else
- e = new(struct hashmap_entry, 1);
+ e = new(struct hashmap_entry, 1);
if (!e)
return -ENOMEM;
return NULL;
data = e->value;
- remove_entry(h, e);
+ remove_entry(h, &e);
return data;
}
if ((k = hash_scan(h, new_hash, new_key)))
if (e != k)
- remove_entry(h, k);
+ remove_entry(h, &k);
unlink_entry(h, e, old_hash);
if (e->value != value)
return NULL;
- remove_entry(h, e);
+ remove_entry(h, &e);
return value;
}
}
void* hashmap_steal_first(Hashmap *h) {
+ struct hashmap_entry *e;
void *data;
if (!h)
if (!h->iterate_list_head)
return NULL;
- data = h->iterate_list_head->value;
- remove_entry(h, h->iterate_list_head);
+ e = h->iterate_list_head;
+ data = e->value;
+ remove_entry(h, &e);
return data;
}
void* hashmap_steal_first_key(Hashmap *h) {
+ struct hashmap_entry *e;
void *key;
if (!h)
if (!h->iterate_list_head)
return NULL;
- key = (void*) h->iterate_list_head->key;
- remove_entry(h, h->iterate_list_head);
+ e = h->iterate_list_head;
+ key = (void*) e->key;
+ remove_entry(h, &e);
return key;
}
return 0;
}
-Hashmap *hashmap_copy(Hashmap *h) {
- Hashmap *copy;
-
- assert(h);
-
- if (!(copy = hashmap_new(h->hash_func, h->compare_func)))
- return NULL;
-
- if (hashmap_merge(copy, h) < 0) {
- hashmap_free(copy);
- return NULL;
- }
-
- return copy;
-}
-
char **hashmap_get_strv(Hashmap *h) {
char **sv;
Iterator it;