From b46aad6df449445a9fc4aa7b32bd40005438e3f7 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 13 Apr 2024 14:18:05 +0200 Subject: Adding upstream version 2.9.5. Signed-off-by: Daniel Baumann --- src/dict.c | 127 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 src/dict.c (limited to 'src/dict.c') diff --git a/src/dict.c b/src/dict.c new file mode 100644 index 0000000..a225081 --- /dev/null +++ b/src/dict.c @@ -0,0 +1,127 @@ +#include + +#include +#include +#include +#include + +struct dict *new_dict(const char *name) +{ + struct dict *dict; + + dict = malloc(sizeof *dict); + if (!dict) + return NULL; + + dict->name = name; + dict->values = EB_ROOT_UNIQUE; + HA_RWLOCK_INIT(&dict->rwlock); + + return dict; +} + +/* + * Allocate a new dictionary entry with as string value which is strdup()'ed. + * Returns the new allocated entry if succeeded, NULL if not. + */ +static struct dict_entry *new_dict_entry(char *s) +{ + struct dict_entry *de; + + de = calloc(1, sizeof *de); + if (!de) + return NULL; + + de->value.key = strdup(s); + if (!de->value.key) + goto err; + + de->len = strlen(s); + de->refcount = 1; + + return de; + + err: + ha_free(&de->value.key); + de->len = 0; + free(de); + return NULL; +} + +/* + * Release the memory allocated for dictionary entry. + */ +static void free_dict_entry(struct dict_entry *de) +{ + de->refcount = 0; + ha_free(&de->value.key); + free(de); +} + +/* + * Simple function to lookup dictionary entries with as value. + */ +static struct dict_entry *__dict_lookup(struct dict *d, const char *s) +{ + struct dict_entry *de; + struct ebpt_node *node; + + de = NULL; + node = ebis_lookup(&d->values, s); + if (node) + de = container_of(node, struct dict_entry, value); + + return de; +} + +/* + * Insert an entry in dictionary with as value. * + */ +struct dict_entry *dict_insert(struct dict *d, char *s) +{ + struct dict_entry *de; + struct ebpt_node *n; + + HA_RWLOCK_RDLOCK(DICT_LOCK, &d->rwlock); + de = __dict_lookup(d, s); + HA_RWLOCK_RDUNLOCK(DICT_LOCK, &d->rwlock); + if (de) { + HA_ATOMIC_INC(&de->refcount); + return de; + } + + de = new_dict_entry(s); + if (!de) + return NULL; + + HA_RWLOCK_WRLOCK(DICT_LOCK, &d->rwlock); + n = ebis_insert(&d->values, &de->value); + HA_RWLOCK_WRUNLOCK(DICT_LOCK, &d->rwlock); + if (n != &de->value) { + free_dict_entry(de); + de = container_of(n, struct dict_entry, value); + } + + return de; +} + + +/* + * Unreference a dict entry previously acquired with . + * If this is the last live reference to the entry, it is + * removed from the dictionary. + */ +void dict_entry_unref(struct dict *d, struct dict_entry *de) +{ + if (!de) + return; + + if (HA_ATOMIC_SUB_FETCH(&de->refcount, 1) != 0) + return; + + HA_RWLOCK_WRLOCK(DICT_LOCK, &d->rwlock); + ebpt_delete(&de->value); + HA_RWLOCK_WRUNLOCK(DICT_LOCK, &d->rwlock); + + free_dict_entry(de); +} -- cgit v1.2.3