diff options
| author | Garrett D'Amore <garrett@damore.org> | 2021-12-06 21:09:55 -0500 |
|---|---|---|
| committer | Garrett D'Amore <garrett@damore.org> | 2021-12-06 21:09:55 -0500 |
| commit | 037d26a902a3cd5016052c76a6747e40c1a0df50 (patch) | |
| tree | f76ed1eabcffa862d93ffe6ee3d53c6a0ae472c4 /src/core/idhash.c | |
| parent | 21528dfe0998d056222191a4abe53d8d9f1286e3 (diff) | |
| download | nng-037d26a902a3cd5016052c76a6747e40c1a0df50.tar.gz nng-037d26a902a3cd5016052c76a6747e40c1a0df50.tar.bz2 nng-037d26a902a3cd5016052c76a6747e40c1a0df50.zip | |
ID map static initialization support.
This also arranges to clean up the maps at nng_fini time.
Diffstat (limited to 'src/core/idhash.c')
| -rw-r--r-- | src/core/idhash.c | 79 |
1 files changed, 74 insertions, 5 deletions
diff --git a/src/core/idhash.c b/src/core/idhash.c index c61850d2..3403b59e 100644 --- a/src/core/idhash.c +++ b/src/core/idhash.c @@ -1,5 +1,5 @@ // -// Copyright 2020 Staysail Systems, Inc. <info@staysail.tech> +// Copyright 2021 Staysail Systems, Inc. <info@staysail.tech> // Copyright 2018 Capitar IT Group BV <info@capitar.com> // // This software is supplied under the terms of the MIT License, a @@ -15,9 +15,14 @@ struct nni_id_entry { uint32_t key; uint32_t skips; - void * val; + void *val; }; +static int id_reg_len = 0; +static int id_reg_num = 0; +static nni_id_map **id_reg_map = NULL; +static nni_mtx id_reg_mtx = NNI_MTX_INITIALIZER; + void nni_id_map_init(nni_id_map *m, uint32_t lo, uint32_t hi, bool randomize) { @@ -33,15 +38,15 @@ nni_id_map_init(nni_id_map *m, uint32_t lo, uint32_t hi, bool randomize) m->id_count = 0; m->id_load = 0; m->id_cap = 0; + m->id_dyn_val = 0; m->id_max_load = 0; m->id_min_load = 0; // never shrink below this m->id_min_val = lo; m->id_max_val = hi; if (randomize) { - // NB: The range is inclusive. - m->id_dyn_val = nni_random() % ((hi - lo) + 1) + lo; + m->id_flags = NNI_ID_FLAG_RANDOM; } else { - m->id_dyn_val = lo; + m->id_flags = 0; } } @@ -103,6 +108,53 @@ nni_id_get(nni_id_map *m, uint32_t id) } static int +id_map_register(nni_id_map *m) +{ + if ((m->id_flags & (NNI_ID_FLAG_STATIC | NNI_ID_FLAG_REGISTER)) != + NNI_ID_FLAG_STATIC) { + return (0); + } + nni_mtx_lock(&id_reg_mtx); + if (id_reg_len <= id_reg_num) { + nni_id_map **mr; + int len = id_reg_len; + if (len < 10) { + len = 10; + } else { + len *= 2; + } + mr = nni_zalloc(sizeof(nni_id_map *) * len); + if (mr == NULL) { + nni_mtx_unlock(&id_reg_mtx); + return (NNG_ENOMEM); + } + id_reg_len = len; + memcpy(mr, id_reg_map, id_reg_num * sizeof(nni_id_map *)); + id_reg_map = mr; + } + id_reg_map[id_reg_num++] = m; + m->id_flags |= NNI_ID_FLAG_REGISTER; + nni_mtx_unlock(&id_reg_mtx); + return (0); +} + +void +nni_id_map_sys_fini(void) +{ + nni_mtx_lock(&id_reg_mtx); + for (int i = 0; i < id_reg_num; i++) { + if (id_reg_map[i] != NULL) { + nni_id_map_fini(id_reg_map[i]); + } + } + nni_free(id_reg_map, sizeof(nni_id_map *) * id_reg_len); + id_reg_map = NULL; + id_reg_len = 0; + id_reg_num = 0; + nni_mtx_unlock(&id_reg_mtx); +} + +static int id_resize(nni_id_map *m) { size_t new_cap; @@ -110,12 +162,19 @@ id_resize(nni_id_map *m) nni_id_entry *new_entries; nni_id_entry *old_entries; uint32_t i; + int rv; if ((m->id_load < m->id_max_load) && (m->id_load >= m->id_min_load)) { // No resize needed. return (0); } + // if it is a statically declared map, register it so that we + // will free it at finalization time + if ((rv = id_map_register(m)) != 0) { + return (rv); + } + old_cap = m->id_cap; new_cap = 8; while (new_cap < (m->id_count * 2)) { @@ -266,6 +325,16 @@ nni_id_alloc(nni_id_map *m, uint32_t *idp, void *val) // Really more like ENOSPC.. the table is filled to max. return (NNG_ENOMEM); } + if (m->id_dyn_val == 0) { + if (m->id_flags & NNI_ID_FLAG_RANDOM) { + // NB: The range is inclusive. + m->id_dyn_val = nni_random() % + (m->id_max_val - m->id_min_val + 1) + + m->id_min_val; + } else { + m->id_dyn_val = m->id_min_val; + } + } for (;;) { id = m->id_dyn_val; |
