diff options
| author | Garrett D'Amore <garrett@damore.org> | 2017-07-13 18:31:40 -0700 |
|---|---|---|
| committer | Garrett D'Amore <garrett@damore.org> | 2017-07-13 18:31:40 -0700 |
| commit | 841048a806f7836bd1196f48c5ee3db5ca844b88 (patch) | |
| tree | 1582ba9008299801f130796df397c4d18b6a9673 /src/core | |
| parent | 14caa074a83fa2e659b3e490bf9bd31ff0b6b4b1 (diff) | |
| download | nng-841048a806f7836bd1196f48c5ee3db5ca844b88.tar.gz nng-841048a806f7836bd1196f48c5ee3db5ca844b88.tar.bz2 nng-841048a806f7836bd1196f48c5ee3db5ca844b88.zip | |
idhash has it's own lock now.
Diffstat (limited to 'src/core')
| -rw-r--r-- | src/core/idhash.c | 81 | ||||
| -rw-r--r-- | src/core/idhash.h | 11 |
2 files changed, 56 insertions, 36 deletions
diff --git a/src/core/idhash.c b/src/core/idhash.c index b3974983..b2158f91 100644 --- a/src/core/idhash.c +++ b/src/core/idhash.c @@ -29,15 +29,22 @@ struct nni_idhash { uint32_t ih_maxval; uint32_t ih_dynval; nni_idhash_entry *ih_entries; + nni_mtx ih_mtx; }; int nni_idhash_init(nni_idhash **hp) { nni_idhash *h; + int rv; + if ((h = NNI_ALLOC_STRUCT(h)) == NULL) { return (NNG_ENOMEM); } + if ((rv = nni_mtx_init(&h->ih_mtx)) != 0) { + NNI_FREE_STRUCT(h); + return (rv); + } h->ih_entries = NULL; h->ih_count = 0; h->ih_load = 0; @@ -63,6 +70,7 @@ nni_idhash_fini(nni_idhash *h) h->ih_cap = h->ih_count = 0; h->ih_load = h->ih_minload = h->ih_maxload = 0; } + nni_mtx_fini(&h->ih_mtx); NNI_FREE_STRUCT(h); } } @@ -70,6 +78,8 @@ nni_idhash_fini(nni_idhash *h) void nni_idhash_reclaim(nni_idhash *h) { + nni_mtx_lock(&h->ih_mtx); + // Reclaim the buffer if we want, but preserve the limits. if ((h->ih_count == 0) && (h->ih_cap != 0) && (h->ih_walkers == 0)) { NNI_FREE_STRUCTS(h->ih_entries, h->ih_cap); @@ -78,26 +88,29 @@ nni_idhash_reclaim(nni_idhash *h) h->ih_minload = 0; h->ih_maxload = 0; } + nni_mtx_unlock(&h->ih_mtx); } void nni_idhash_set_limits( nni_idhash *h, uint32_t minval, uint32_t maxval, uint32_t start) { + nni_mtx_lock(&h->ih_mtx); h->ih_minval = minval; h->ih_maxval = maxval; h->ih_dynval = start; NNI_ASSERT(minval < maxval); NNI_ASSERT(start >= minval); NNI_ASSERT(start <= maxval); + nni_mtx_unlock(&h->ih_mtx); } // Inspired by Python dict implementation. This probe will visit every // cell. We always hash consecutively assigned IDs. #define NNI_IDHASH_NEXTPROBE(h, j) ((((j) *5) + 1) & (h->ih_cap - 1)) -int -nni_idhash_find(nni_idhash *h, uint32_t id, void **valp) +static int +nni_hash_find(nni_idhash *h, uint32_t id, void **valp) { uint32_t index = id & (h->ih_cap - 1); @@ -118,6 +131,17 @@ nni_idhash_find(nni_idhash *h, uint32_t id, void **valp) } } +int +nni_idhash_find(nni_idhash *h, uint32_t id, void **valp) +{ + int rv; + + nni_mtx_lock(&h->ih_mtx); + rv = nni_hash_find(h, id, valp); + nni_mtx_unlock(&h->ih_mtx); + return (rv); +} + static int nni_hash_resize(nni_idhash *h) { @@ -191,10 +215,12 @@ nni_idhash_remove(nni_idhash *h, uint32_t id) void * val; uint32_t index; + nni_mtx_lock(&h->ih_mtx); // First check that it is in the table. This may double the // lookup time, but it means that if we get past this then we KNOW // we are going to delete an element. - if ((rv = nni_idhash_find(h, id, &val)) != 0) { + if ((rv = nni_hash_find(h, id, &val)) != 0) { + nni_mtx_unlock(&h->ih_mtx); return (rv); } @@ -222,12 +248,13 @@ nni_idhash_remove(nni_idhash *h, uint32_t id) // Shrink -- but it's ok if we can't. (void) nni_hash_resize(h); + nni_mtx_unlock(&h->ih_mtx); return (0); } -int -nni_idhash_insert(nni_idhash *h, uint32_t id, void *val) +static int +nni_hash_insert(nni_idhash *h, uint32_t id, void *val) { uint32_t index; @@ -267,14 +294,28 @@ nni_idhash_insert(nni_idhash *h, uint32_t id, void *val) } int +nni_idhash_insert(nni_idhash *h, uint32_t id, void *val) +{ + int rv; + + nni_mtx_lock(&h->ih_mtx); + rv = nni_hash_insert(h, id, val); + nni_mtx_unlock(&h->ih_mtx); + return (rv); +} + +int nni_idhash_alloc(nni_idhash *h, uint32_t *idp, void *val) { uint32_t id; void * scrap; int rv; + nni_mtx_lock(&h->ih_mtx); if (h->ih_count > (h->ih_maxval - h->ih_minval)) { // Really more like ENOSPC.. the table is filled to max. + nni_mtx_unlock(&h->ih_mtx); + return (NNG_ENOMEM); } @@ -285,39 +326,27 @@ nni_idhash_alloc(nni_idhash *h, uint32_t *idp, void *val) h->ih_dynval = h->ih_minval; } - if (nni_idhash_find(h, id, &scrap) == NNG_ENOENT) { + if (nni_hash_find(h, id, &scrap) == NNG_ENOENT) { break; } } - rv = nni_idhash_insert(h, id, val); + rv = nni_hash_insert(h, id, val); if (rv == 0) { *idp = id; } + nni_mtx_unlock(&h->ih_mtx); + return (rv); } size_t nni_idhash_count(nni_idhash *h) { - return (h->ih_count); -} - -int -nni_idhash_walk(nni_idhash *h, nni_idhash_walkfn fn, void *arg) -{ - uint32_t i, rv; + size_t num; + nni_mtx_lock(&h->ih_mtx); + num = h->ih_count; + nni_mtx_unlock(&h->ih_mtx); - for (i = 0; i < h->ih_cap; i++) { - nni_idhash_entry *ent = &h->ih_entries[i]; - - if (ent->ihe_val == NULL) { - continue; - } - rv = fn(arg, ent->ihe_key, ent->ihe_val); - if (rv != 0) { - return (rv); - } - } - return (0); + return (num); } diff --git a/src/core/idhash.h b/src/core/idhash.h index 018420bc..70740b39 100644 --- a/src/core/idhash.h +++ b/src/core/idhash.h @@ -21,19 +21,11 @@ // we use a better probe (taken from Python) to avoid hitting the same // positions. Our hash algorithm is just the low order bits, and we // use table sizes that are powers of two. Note that hash items -// must be non-NULL. The table is locked. +// must be non-NULL. The table is protected by an internal lock. typedef struct nni_idhash nni_idhash; typedef struct nni_idhash_entry nni_idhash_entry; -// nni_idhash_walkfn is called when walking a hash table. If the -// return value is non-zero, then nni_idhash_walk will terminate further -// process and return that return value. The function takes the generic -// opaque value for the walk as its first argument, and the next two -// arguments are the hash key and the opaque value stored with it. -// Note that the walkfn must not attempt to change the hash table. -// The user must provide any locking needed. -typedef int (*nni_idhash_walkfn)(void *, uint32_t, void *); extern int nni_idhash_init(nni_idhash **); extern void nni_idhash_fini(nni_idhash *); extern void nni_idhash_reclaim(nni_idhash *); @@ -45,6 +37,5 @@ extern int nni_idhash_remove(nni_idhash *, uint32_t); extern int nni_idhash_insert(nni_idhash *, uint32_t, void *); extern int nni_idhash_alloc(nni_idhash *, uint32_t *, void *); extern size_t nni_idhash_count(nni_idhash *); -extern int nni_idhash_walk(nni_idhash *, nni_idhash_walkfn, void *); #endif // CORE_IDHASH_H |
