summaryrefslogtreecommitdiff
path: root/src/core/objhash.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/objhash.c')
-rw-r--r--src/core/objhash.c126
1 files changed, 59 insertions, 67 deletions
diff --git a/src/core/objhash.c b/src/core/objhash.c
index da4c6012..18c55f83 100644
--- a/src/core/objhash.c
+++ b/src/core/objhash.c
@@ -7,41 +7,41 @@
// found online at https://opensource.org/licenses/MIT.
//
-#include "core/nng_impl.h"
#include "core/objhash.h"
+#include "core/nng_impl.h"
#include <string.h>
// The details of the nni_objhash are "private".
struct nni_objhash {
- size_t oh_cap;
- size_t oh_count;
- size_t oh_load;
- size_t oh_minload; // considers placeholders
- size_t oh_maxload;
- uint32_t oh_minval;
- uint32_t oh_maxval;
- uint32_t oh_dynval;
- nni_mtx oh_lock;
- nni_cv oh_cv;
- nni_objhash_node * oh_nodes;
- nni_objhash_ctor oh_ctor;
- nni_objhash_dtor oh_dtor;
+ size_t oh_cap;
+ size_t oh_count;
+ size_t oh_load;
+ size_t oh_minload; // considers placeholders
+ size_t oh_maxload;
+ uint32_t oh_minval;
+ uint32_t oh_maxval;
+ uint32_t oh_dynval;
+ nni_mtx oh_lock;
+ nni_cv oh_cv;
+ nni_objhash_node *oh_nodes;
+ nni_objhash_ctor oh_ctor;
+ nni_objhash_dtor oh_dtor;
};
struct nni_objhash_node {
- uint32_t on_id; // the key
- uint32_t on_skips; // indicates
- uint32_t on_refcnt; // reference count
- void * on_val; // pointer to user data
+ uint32_t on_id; // the key
+ uint32_t on_skips; // indicates
+ uint32_t on_refcnt; // reference count
+ void * on_val; // pointer to user data
};
int
-nni_objhash_init(nni_objhash **ohp, nni_objhash_ctor ctor,
- nni_objhash_dtor dtor)
+nni_objhash_init(
+ nni_objhash **ohp, nni_objhash_ctor ctor, nni_objhash_dtor dtor)
{
nni_objhash *oh;
- int rv;
+ int rv;
if ((ctor == NULL) || (dtor == NULL)) {
return (NNG_EINVAL);
@@ -62,24 +62,23 @@ nni_objhash_init(nni_objhash **ohp, nni_objhash_ctor ctor,
return (rv);
}
- oh->oh_nodes = NULL;
- oh->oh_count = 0;
- oh->oh_load = 0;
- oh->oh_cap = 0;
+ oh->oh_nodes = NULL;
+ oh->oh_count = 0;
+ oh->oh_load = 0;
+ oh->oh_cap = 0;
oh->oh_maxload = 0;
oh->oh_minload = 0; // never shrink below this
- oh->oh_minval = 1;
- oh->oh_maxval = 0x7fffffff;
- oh->oh_dynval = nni_random() %
- (oh->oh_maxval - oh->oh_minval) + oh->oh_minval;
+ oh->oh_minval = 1;
+ oh->oh_maxval = 0x7fffffff;
+ oh->oh_dynval =
+ nni_random() % (oh->oh_maxval - oh->oh_minval) + oh->oh_minval;
oh->oh_ctor = ctor;
oh->oh_dtor = dtor;
- *ohp = oh;
+ *ohp = oh;
return (0);
}
-
void
nni_objhash_fini(nni_objhash *oh)
{
@@ -87,7 +86,7 @@ nni_objhash_fini(nni_objhash *oh)
return;
}
if (oh->oh_nodes != NULL) {
- nni_free(oh->oh_nodes, oh->oh_cap * sizeof (nni_objhash_node));
+ nni_free(oh->oh_nodes, oh->oh_cap * sizeof(nni_objhash_node));
oh->oh_nodes = NULL;
oh->oh_cap = oh->oh_count = 0;
oh->oh_load = oh->oh_minload = oh->oh_maxload = 0;
@@ -97,19 +96,16 @@ nni_objhash_fini(nni_objhash *oh)
NNI_FREE_STRUCT(oh);
}
-
// Inspired by Python dict implementation. This probe will visit every
// cell. We always hash consecutively assigned IDs.
-#define NNI_OBJHASH_NEXTPROBE(h, j) \
- ((((j) * 5) + 1)& (h->oh_cap - 1))
-
+#define NNI_OBJHASH_NEXTPROBE(h, j) ((((j) *5) + 1) & (h->oh_cap - 1))
// nni_objhash_find_node finds the object hash node associated with a given id.
// The object hash lock must be held by the caller.
static nni_objhash_node *
nni_objhash_find_node(nni_objhash *oh, uint32_t id)
{
- uint32_t index;
+ uint32_t index;
nni_objhash_node *node;
if (oh->oh_count == 0) {
@@ -131,14 +127,13 @@ nni_objhash_find_node(nni_objhash *oh, uint32_t id)
}
}
-
// nni_objhash_find looks up the object, and bumps the reference on it.
// The caller should drop the reference when done by calling nni_objhash_unref.
int
nni_objhash_find(nni_objhash *oh, uint32_t id, void **valp)
{
nni_objhash_node *node;
- int rv;
+ int rv;
nni_mtx_lock(&oh->oh_lock);
node = nni_objhash_find_node(oh, id);
@@ -156,18 +151,17 @@ nni_objhash_find(nni_objhash *oh, uint32_t id, void **valp)
return (rv);
}
-
// Resize the object hash. This is called internally with the lock
// for the object hash held. Grow indicates that this is being called
// from a function that intends to add data, so extra space is needed.
static int
nni_objhash_resize(nni_objhash *oh, int grow)
{
- size_t newsize;
- size_t oldsize;
+ size_t newsize;
+ size_t oldsize;
nni_objhash_node *newnodes;
nni_objhash_node *oldnodes;
- uint32_t i;
+ uint32_t i;
if ((!grow) && (oh->oh_count == 0) && (oh->oh_cap != 0)) {
// Table is empty, and we are unrefing. Lets reclaim the
@@ -175,15 +169,16 @@ nni_objhash_resize(nni_objhash *oh, int grow)
// fluctuate between one and zero are going to bang on the
// allocator a bit. Since such cases should not be very
// performance sensitive, this is probably okay.
- nni_free(oh->oh_nodes, oh->oh_cap * sizeof (nni_objhash_node));
- oh->oh_cap = 0;
- oh->oh_nodes = NULL;
+ nni_free(oh->oh_nodes, oh->oh_cap * sizeof(nni_objhash_node));
+ oh->oh_cap = 0;
+ oh->oh_nodes = NULL;
oh->oh_minload = 0;
oh->oh_maxload = 0;
return (0);
}
- if ((oh->oh_load < oh->oh_maxload) && (oh->oh_load >= oh->oh_minload)) {
+ if ((oh->oh_load < oh->oh_maxload) &&
+ (oh->oh_load >= oh->oh_minload)) {
// No resize needed.
return (0);
}
@@ -197,14 +192,14 @@ nni_objhash_resize(nni_objhash *oh, int grow)
}
oldnodes = oh->oh_nodes;
- newnodes = nni_alloc(sizeof (nni_objhash_node) * newsize);
+ newnodes = nni_alloc(sizeof(nni_objhash_node) * newsize);
if (newnodes == NULL) {
return (NNG_ENOMEM);
}
- memset(newnodes, 0, sizeof (nni_objhash_node) * newsize);
+ memset(newnodes, 0, sizeof(nni_objhash_node) * newsize);
oh->oh_nodes = newnodes;
- oh->oh_cap = newsize;
+ oh->oh_cap = newsize;
if (newsize > 8) {
oh->oh_minload = newsize / 8;
oh->oh_maxload = newsize * 2 / 3;
@@ -222,7 +217,7 @@ nni_objhash_resize(nni_objhash *oh, int grow)
if (newnodes[index].on_val == NULL) {
oh->oh_load++;
newnodes[index].on_val = oldnodes[i].on_val;
- newnodes[index].on_id = oldnodes[i].on_id;
+ newnodes[index].on_id = oldnodes[i].on_id;
newnodes[index].on_refcnt =
oldnodes[i].on_refcnt;
break;
@@ -232,19 +227,18 @@ nni_objhash_resize(nni_objhash *oh, int grow)
}
}
if (oldsize != 0) {
- nni_free(oldnodes, sizeof (nni_objhash_node) * oldsize);
+ nni_free(oldnodes, sizeof(nni_objhash_node) * oldsize);
}
return (0);
}
-
void
nni_objhash_unref(nni_objhash *oh, uint32_t id)
{
- void *val;
- uint32_t index;
+ void * val;
+ uint32_t index;
nni_objhash_node *node;
- nni_objhash_dtor dtor;
+ nni_objhash_dtor dtor;
nni_mtx_lock(&oh->oh_lock);
@@ -303,14 +297,13 @@ nni_objhash_unref(nni_objhash *oh, uint32_t id)
dtor(val);
}
-
void
nni_objhash_unref_wait(nni_objhash *oh, uint32_t id)
{
- void *val;
- uint32_t index;
+ void * val;
+ uint32_t index;
nni_objhash_node *node;
- nni_objhash_dtor dtor;
+ nni_objhash_dtor dtor;
nni_mtx_lock(&oh->oh_lock);
@@ -360,7 +353,6 @@ nni_objhash_unref_wait(nni_objhash *oh, uint32_t id)
dtor(val);
}
-
// Allocate a new object hash entry. Note that this will execute the
// constructor with the object hash lock held. Consequently, code that
// runs the constructor must not run for long periods of time, since that
@@ -368,8 +360,8 @@ nni_objhash_unref_wait(nni_objhash *oh, uint32_t id)
int
nni_objhash_alloc(nni_objhash *oh, uint32_t *idp, void **valp)
{
- uint32_t id;
- uint32_t index;
+ uint32_t id;
+ uint32_t index;
nni_objhash_node *node;
nni_mtx_lock(&oh->oh_lock);
@@ -418,7 +410,8 @@ nni_objhash_alloc(nni_objhash *oh, uint32_t *idp, void **valp)
node->on_val = oh->oh_ctor(id);
if (node->on_val == NULL) {
- // Constructor failed; walk *again* to undo the skip increments.
+ // Constructor failed; walk *again* to undo the skip
+ // increments.
node->on_refcnt--;
index = id & (oh->oh_cap - 1);
for (;;) {
@@ -433,7 +426,7 @@ nni_objhash_alloc(nni_objhash *oh, uint32_t *idp, void **valp)
}
nni_mtx_unlock(&oh->oh_lock);
- return (NNG_ENOMEM); // no other return from ctor
+ return (NNG_ENOMEM); // no other return from ctor
}
oh->oh_count++;
@@ -441,7 +434,7 @@ nni_objhash_alloc(nni_objhash *oh, uint32_t *idp, void **valp)
oh->oh_load++;
}
*valp = node->on_val;
- *idp = id;
+ *idp = id;
NNI_ASSERT(node->on_refcnt == 1);
@@ -449,7 +442,6 @@ nni_objhash_alloc(nni_objhash *oh, uint32_t *idp, void **valp)
return (0);
}
-
size_t
nni_objhash_count(nni_objhash *oh)
{