aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGarrett D'Amore <garrett@damore.org>2017-07-13 18:17:02 -0700
committerGarrett D'Amore <garrett@damore.org>2017-07-13 18:17:02 -0700
commit14caa074a83fa2e659b3e490bf9bd31ff0b6b4b1 (patch)
treea393024cc23b7540fa08009b221e3e40a195603d
parent722cd0deed891bfcb3f1e9866655cc5a41b2111e (diff)
downloadnng-14caa074a83fa2e659b3e490bf9bd31ff0b6b4b1.tar.gz
nng-14caa074a83fa2e659b3e490bf9bd31ff0b6b4b1.tar.bz2
nng-14caa074a83fa2e659b3e490bf9bd31ff0b6b4b1.zip
Make idhash non-inlined (so we can add a mutex.)
-rw-r--r--src/core/idhash.c44
-rw-r--r--src/core/idhash.h20
-rw-r--r--src/core/pipe.c1
-rw-r--r--src/protocol/reqrep/rep.c29
-rw-r--r--src/protocol/survey/respond.c29
-rw-r--r--tests/idhash.c229
6 files changed, 187 insertions, 165 deletions
diff --git a/src/core/idhash.c b/src/core/idhash.c
index 9f3b4b03..b3974983 100644
--- a/src/core/idhash.c
+++ b/src/core/idhash.c
@@ -1,5 +1,6 @@
//
-// Copyright 2016 Garrett D'Amore <garrett@damore.org>
+// Copyright 2017 Garrett D'Amore <garrett@damore.org>
+// Copyright 2017 Capitar IT Group BV <info@capitar.com>
//
// This software is supplied under the terms of the MIT License, a
// copy of which should be located in the distribution where this
@@ -17,9 +18,26 @@ struct nni_idhash_entry {
void * ihe_val;
};
+struct nni_idhash {
+ size_t ih_cap;
+ size_t ih_count;
+ size_t ih_load;
+ size_t ih_minload; // considers placeholders
+ size_t ih_maxload;
+ uint32_t ih_walkers;
+ uint32_t ih_minval;
+ uint32_t ih_maxval;
+ uint32_t ih_dynval;
+ nni_idhash_entry *ih_entries;
+};
+
int
-nni_idhash_init(nni_idhash *h)
+nni_idhash_init(nni_idhash **hp)
{
+ nni_idhash *h;
+ if ((h = NNI_ALLOC_STRUCT(h)) == NULL) {
+ return (NNG_ENOMEM);
+ }
h->ih_entries = NULL;
h->ih_count = 0;
h->ih_load = 0;
@@ -30,18 +48,22 @@ nni_idhash_init(nni_idhash *h)
h->ih_minval = 0;
h->ih_maxval = 0xffffffff;
h->ih_dynval = 0;
+ *hp = h;
return (0);
}
void
nni_idhash_fini(nni_idhash *h)
{
- NNI_ASSERT(h->ih_walkers == 0);
- if (h->ih_entries != NULL) {
- nni_free(h->ih_entries, h->ih_cap * sizeof(nni_idhash_entry));
- h->ih_entries = NULL;
- h->ih_cap = h->ih_count = 0;
- h->ih_load = h->ih_minload = h->ih_maxload = 0;
+ if (h != NULL) {
+ NNI_ASSERT(h->ih_walkers == 0);
+ if (h->ih_entries != NULL) {
+ NNI_FREE_STRUCTS(h->ih_entries, h->ih_cap);
+ h->ih_entries = NULL;
+ h->ih_cap = h->ih_count = 0;
+ h->ih_load = h->ih_minload = h->ih_maxload = 0;
+ }
+ NNI_FREE_STRUCT(h);
}
}
@@ -50,7 +72,7 @@ nni_idhash_reclaim(nni_idhash *h)
{
// 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(h->ih_entries, h->ih_cap * sizeof(nni_idhash_entry));
+ NNI_FREE_STRUCTS(h->ih_entries, h->ih_cap);
h->ih_cap = 0;
h->ih_entries = NULL;
h->ih_minload = 0;
@@ -124,7 +146,7 @@ nni_hash_resize(nni_idhash *h)
}
oldents = h->ih_entries;
- newents = nni_alloc(sizeof(nni_idhash_entry) * newsize);
+ newents = NNI_ALLOC_STRUCTS(newents, newsize);
if (newents == NULL) {
return (NNG_ENOMEM);
}
@@ -157,7 +179,7 @@ nni_hash_resize(nni_idhash *h)
}
}
if (oldsize != 0) {
- nni_free(oldents, sizeof(nni_idhash_entry) * oldsize);
+ NNI_FREE_STRUCTS(oldents, oldsize);
}
return (0);
}
diff --git a/src/core/idhash.h b/src/core/idhash.h
index bb3b1581..018420bc 100644
--- a/src/core/idhash.h
+++ b/src/core/idhash.h
@@ -1,5 +1,6 @@
//
-// Copyright 2016 Garrett D'Amore <garrett@damore.org>
+// Copyright 2017 Garrett D'Amore <garrett@damore.org>
+// Copyright 2017 Capitar IT Group BV <info@capitar.com>
//
// This software is supplied under the terms of the MIT License, a
// copy of which should be located in the distribution where this
@@ -25,21 +26,6 @@
typedef struct nni_idhash nni_idhash;
typedef struct nni_idhash_entry nni_idhash_entry;
-// The details of the nni_idhash are "private". But they let us inline
-// this into structures.
-struct nni_idhash {
- size_t ih_cap;
- size_t ih_count;
- size_t ih_load;
- size_t ih_minload; // considers placeholders
- size_t ih_maxload;
- uint32_t ih_walkers;
- uint32_t ih_minval;
- uint32_t ih_maxval;
- uint32_t ih_dynval;
- nni_idhash_entry *ih_entries;
-};
-
// 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
@@ -48,7 +34,7 @@ struct nni_idhash {
// 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 int nni_idhash_init(nni_idhash **);
extern void nni_idhash_fini(nni_idhash *);
extern void nni_idhash_reclaim(nni_idhash *);
extern void nni_idhash_set_limits(nni_idhash *, uint32_t, uint32_t, uint32_t);
diff --git a/src/core/pipe.c b/src/core/pipe.c
index 702e8eb1..91b78192 100644
--- a/src/core/pipe.c
+++ b/src/core/pipe.c
@@ -1,5 +1,6 @@
//
// Copyright 2017 Garrett D'Amore <garrett@damore.org>
+// Copyright 2017 Capitar IT Group BV <info@capitar.com>
//
// This software is supplied under the terms of the MIT License, a
// copy of which should be located in the distribution where this
diff --git a/src/protocol/reqrep/rep.c b/src/protocol/reqrep/rep.c
index cfc83a5b..d37ca691 100644
--- a/src/protocol/reqrep/rep.c
+++ b/src/protocol/reqrep/rep.c
@@ -1,5 +1,6 @@
//
// Copyright 2017 Garrett D'Amore <garrett@damore.org>
+// Copyright 2017 Capitar IT Group BV <info@capitar.com>
//
// This software is supplied under the terms of the MIT License, a
// copy of which should be located in the distribution where this
@@ -28,16 +29,16 @@ static void nni_rep_pipe_fini(void *);
// An nni_rep_sock is our per-socket protocol private structure.
struct nni_rep_sock {
- nni_sock * sock;
- nni_msgq * uwq;
- nni_msgq * urq;
- int raw;
- int ttl;
- nni_idhash pipes;
- char * btrace;
- size_t btrace_len;
- nni_aio aio_getq;
- nni_mtx mtx;
+ nni_sock * sock;
+ nni_msgq * uwq;
+ nni_msgq * urq;
+ int raw;
+ int ttl;
+ nni_idhash *pipes;
+ char * btrace;
+ size_t btrace_len;
+ nni_aio aio_getq;
+ nni_mtx mtx;
};
// An nni_rep_pipe is our per-pipe protocol private structure.
@@ -59,7 +60,7 @@ nni_rep_sock_fini(void *arg)
nni_rep_sock *rep = arg;
nni_aio_fini(&rep->aio_getq);
- nni_idhash_fini(&rep->pipes);
+ nni_idhash_fini(rep->pipes);
if (rep->btrace != NULL) {
nni_free(rep->btrace, rep->btrace_len);
}
@@ -183,7 +184,7 @@ nni_rep_pipe_start(void *arg)
rp->id = nni_pipe_id(rp->pipe);
nni_mtx_lock(&rep->mtx);
- rv = nni_idhash_insert(&rep->pipes, rp->id, rp);
+ rv = nni_idhash_insert(rep->pipes, rp->id, rp);
nni_mtx_unlock(&rep->mtx);
if (rv != 0) {
return (rv);
@@ -214,7 +215,7 @@ nni_rep_pipe_stop(void *arg)
if (id != 0) {
nni_mtx_lock(&rep->mtx);
- nni_idhash_remove(&rep->pipes, id);
+ nni_idhash_remove(rep->pipes, id);
nni_mtx_unlock(&rep->mtx);
}
}
@@ -260,7 +261,7 @@ nni_rep_sock_getq_cb(void *arg)
// (nonblocking) if we can. If we can't for any reason, then we
// free the message.
nni_mtx_lock(&rep->mtx);
- rv = nni_idhash_find(&rep->pipes, id, (void **) &rp);
+ rv = nni_idhash_find(rep->pipes, id, (void **) &rp);
nni_mtx_unlock(&rep->mtx);
if (rv == 0) {
rv = nni_msgq_tryput(rp->sendq, msg);
diff --git a/src/protocol/survey/respond.c b/src/protocol/survey/respond.c
index 6a784738..17018155 100644
--- a/src/protocol/survey/respond.c
+++ b/src/protocol/survey/respond.c
@@ -1,5 +1,6 @@
//
// Copyright 2017 Garrett D'Amore <garrett@damore.org>
+// Copyright 2017 Capitar IT Group BV <info@capitar.com>
//
// This software is supplied under the terms of the MIT License, a
// copy of which should be located in the distribution where this
@@ -28,16 +29,16 @@ static void nni_resp_pipe_fini(void *);
// An nni_resp_sock is our per-socket protocol private structure.
struct nni_resp_sock {
- nni_sock * nsock;
- nni_msgq * urq;
- nni_msgq * uwq;
- int raw;
- int ttl;
- nni_idhash pipes;
- char * btrace;
- size_t btrace_len;
- nni_aio aio_getq;
- nni_mtx mtx;
+ nni_sock * nsock;
+ nni_msgq * urq;
+ nni_msgq * uwq;
+ int raw;
+ int ttl;
+ nni_idhash *pipes;
+ char * btrace;
+ size_t btrace_len;
+ nni_aio aio_getq;
+ nni_mtx mtx;
};
// An nni_resp_pipe is our per-pipe protocol private structure.
@@ -59,7 +60,7 @@ nni_resp_sock_fini(void *arg)
if (psock != NULL) {
nni_aio_fini(&psock->aio_getq);
- nni_idhash_fini(&psock->pipes);
+ nni_idhash_fini(psock->pipes);
if (psock->btrace != NULL) {
nni_free(psock->btrace, psock->btrace_len);
}
@@ -180,7 +181,7 @@ nni_resp_pipe_start(void *arg)
ppipe->id = nni_pipe_id(ppipe->npipe);
nni_mtx_lock(&psock->mtx);
- rv = nni_idhash_insert(&psock->pipes, ppipe->id, ppipe);
+ rv = nni_idhash_insert(psock->pipes, ppipe->id, ppipe);
nni_mtx_unlock(&psock->mtx);
if (rv != 0) {
return (rv);
@@ -206,7 +207,7 @@ nni_resp_pipe_stop(void *arg)
nni_mtx_lock(&psock->mtx);
if (ppipe->id != 0) {
- nni_idhash_remove(&psock->pipes, ppipe->id);
+ nni_idhash_remove(psock->pipes, ppipe->id);
ppipe->id = 0;
}
nni_mtx_unlock(&psock->mtx);
@@ -246,7 +247,7 @@ nni_resp_sock_getq_cb(void *arg)
nni_msg_trim_header(msg, 4);
nni_mtx_lock(&psock->mtx);
- rv = nni_idhash_find(&psock->pipes, id, (void **) &ppipe);
+ rv = nni_idhash_find(psock->pipes, id, (void **) &ppipe);
if (rv != 0) {
nni_msg_free(msg);
diff --git a/tests/idhash.c b/tests/idhash.c
index a51db654..a30b0d0a 100644
--- a/tests/idhash.c
+++ b/tests/idhash.c
@@ -1,5 +1,6 @@
//
-// Copyright 2016 Garrett D'Amore <garrett@damore.org>
+// Copyright 2017 Garrett D'Amore <garrett@damore.org>
+// Copyright 2017 Capitar IT Group BV <info@capitar.com>
//
// This software is supplied under the terms of the MIT License, a
// copy of which should be located in the distribution where this
@@ -7,139 +8,149 @@
// found online at https://opensource.org/licenses/MIT.
//
-#include "convey.h"
#include "core/idhash.c"
+#include "convey.h"
Main({
- Test("General ID Hash", {
- int rv;
+ Test("General ID Hash",
+ {
+ int rv;
- Convey("Given an id hash", {
- nni_idhash h;
+ Convey("Given an id hash", {
+ nni_idhash *h = NULL;
- So(nni_idhash_init(&h) == 0);
- So(nni_idhash_count(&h) == 0);
+ So(nni_idhash_init(&h) == 0);
+ So(h != NULL);
+ So(nni_idhash_count(h) == 0);
- Reset({
- nni_idhash_fini(&h);
- })
+ Reset({ nni_idhash_fini(h); });
- Convey("We can insert an element", {
- char *five = "five";
- char *four = "four";
- rv = nni_idhash_insert(&h, 5, five);
- So(nni_idhash_count(&h) == 1);
- So(rv == 0);
+ Convey("We can insert an element", {
+ char *five = "five";
+ char *four = "four";
+ rv = nni_idhash_insert(h, 5, five);
+ So(nni_idhash_count(h) == 1);
+ So(rv == 0);
- Convey("And we can find it", {
- void *ptr;
- rv = nni_idhash_find(&h, 5, &ptr);
- So(rv == 0);
- So(ptr == five);
- })
- Convey("We can delete it", {
- void *ptr;
- rv = nni_idhash_remove(&h, 5);
- So(rv == 0);
- rv = nni_idhash_find(&h, 5, &ptr);
- So(rv == NNG_ENOENT);
- })
- Convey("We can change the value", {
- void *ptr;
- So(nni_idhash_insert(&h, 5, four) == 0);
- So(nni_idhash_count(&h) == 1);
- So(nni_idhash_find(&h, 5, &ptr) == 0);
- So(ptr == four);
- })
- Convey("We can insert a hash collision", {
- void *ptr;
- So(nni_idhash_insert(&h, 13, four) == 0);
- So(nni_idhash_count(&h) == 2);
- So(nni_idhash_find(&h, 5, &ptr) == 0);
- So(ptr == five);
- So(nni_idhash_find(&h, 13, &ptr) == 0);
- So(ptr == four);
- Convey("And delete the intermediate", {
- So(nni_idhash_remove(&h, 5) == 0);
- ptr = NULL;
- So(nni_idhash_find(&h, 13, &ptr) == 0);
- So(ptr == four);
- })
- })
+ Convey("And we can find it", {
+ void *ptr;
+ rv = nni_idhash_find(h, 5, &ptr);
+ So(rv == 0);
+ So(ptr == five);
+ });
+ Convey("We can delete it", {
+ void *ptr;
+ rv = nni_idhash_remove(h, 5);
+ So(rv == 0);
+ rv = nni_idhash_find(h, 5, &ptr);
+ So(rv == NNG_ENOENT);
+ });
+ Convey("We can change the value", {
+ void *ptr;
+ So(nni_idhash_insert(h, 5, four) ==
+ 0);
+ So(nni_idhash_count(h) == 1);
+ So(nni_idhash_find(h, 5, &ptr) ==
+ 0);
+ So(ptr == four);
+ });
+ Convey("We can insert a hash collision", {
+ void *ptr;
+ So(nni_idhash_insert(
+ h, 13, four) == 0);
+ So(nni_idhash_count(h) == 2);
+ So(nni_idhash_find(h, 5, &ptr) ==
+ 0);
+ So(ptr == five);
+ So(nni_idhash_find(h, 13, &ptr) ==
+ 0);
+ So(ptr == four);
+ Convey("And delete intermediate", {
+ So(nni_idhash_remove(
+ h, 5) == 0);
+ ptr = NULL;
+ So(nni_idhash_find(
+ h, 13, &ptr) == 0);
+ So(ptr == four);
+ });
+ });
- })
- Convey("We cannot find bogus values", {
- void *ptr = NULL;
- rv = nni_idhash_find(&h, 42, &ptr);
- So(rv == NNG_ENOENT);
- So(ptr == NULL);
- })
- })
- })
+ });
+ Convey("We cannot find bogus values", {
+ void *ptr;
+ ptr = NULL;
+ rv = nni_idhash_find(h, 42, &ptr);
+ So(rv == NNG_ENOENT);
+ So(ptr == NULL);
+ });
+ });
+ })
- Test("Resize ID Hash", {
- int expect[1024];
- int i;
+ Test("Resize ID Hash", {
+ int expect[1024];
+ int i;
- for (i = 0; i < 1024; i++) {
- expect[i] = i;
- }
- Convey("Given an id hash", {
- nni_idhash h;
+ for (i = 0; i < 1024; i++) {
+ expect[i] = i;
+ }
+ Convey("Given an id hash", {
+ nni_idhash *h;
- So(nni_idhash_init(&h) == 0);
- So(nni_idhash_count(&h) == 0);
+ So(nni_idhash_init(&h) == 0);
+ So(nni_idhash_count(h) == 0);
- Reset({
- nni_idhash_fini(&h);
- })
+ Reset({ nni_idhash_fini(h); });
- Convey("We can insert 1024 items", {
- for (i = 0; i < 1024; i++) {
- nni_idhash_insert(&h, i, &expect[i]);
- }
- So(nni_idhash_count(&h) == 1024);
+ Convey("We can insert 1024 items", {
+ for (i = 0; i < 1024; i++) {
+ nni_idhash_insert(
+ h, i, &expect[i]);
+ }
+ So(nni_idhash_count(h) == 1024);
- Convey("We can remove them", {
- for (i = 0; i < 1024; i++) {
- nni_idhash_remove(&h, i);
- }
- So(nni_idhash_count(&h) == 0);
- })
- })
- })
- })
+ Convey("We can remove them", {
+ for (i = 0; i < 1024; i++) {
+ nni_idhash_remove(h, i);
+ }
+ So(nni_idhash_count(h) == 0);
+ });
+ });
+ });
+ });
Test("Dynamic ID generation", {
Convey("Given a small ID hash", {
- nni_idhash h;
- int expect[5];
- uint32_t id;
- int i;
+ nni_idhash *h;
+ int expect[5];
+ uint32_t id;
+ int i;
So(nni_idhash_init(&h) == 0);
- Reset({
- nni_idhash_fini(&h);
- })
- nni_idhash_set_limits(&h, 10, 13, 10);
+ Reset({ nni_idhash_fini(h); });
+ nni_idhash_set_limits(h, 10, 13, 10);
So(1);
Convey("We can fill the table", {
for (i = 0; i < 4; i++) {
- So(nni_idhash_alloc(&h, &id, &expect[i]) == 0);
+ So(nni_idhash_alloc(
+ h, &id, &expect[i]) == 0);
So(id == (i + 10));
}
Convey("Adding another fails", {
- So(nni_idhash_alloc(&h, &id, &expect[5]) == NNG_ENOMEM);
- })
+ So(nni_idhash_alloc(h, &id,
+ &expect[5]) == NNG_ENOMEM);
+ });
Convey("Deleting one lets us reinsert", {
- nni_idhash_remove(&h, 11);
- So(nni_idhash_alloc(&h, &id, &expect[5]) == 0);
+ nni_idhash_remove(h, 11);
+ So(nni_idhash_alloc(
+ h, &id, &expect[5]) == 0);
So(id == 11);
- })
- })
+ });
+ });
Convey("We cannot insert bogus values", {
- So(nni_idhash_insert(&h, 1, &expect[0]) == NNG_EINVAL);
- So(nni_idhash_insert(&h, 100, &expect[0]) == NNG_EINVAL);
- })
- })
- })
-})
+ So(nni_idhash_insert(h, 1, &expect[0]) ==
+ NNG_EINVAL);
+ So(nni_idhash_insert(h, 100, &expect[0]) ==
+ NNG_EINVAL);
+ });
+ });
+ });
+});