diff options
| author | Garrett D'Amore <garrett@damore.org> | 2017-01-17 19:36:15 -0800 |
|---|---|---|
| committer | Garrett D'Amore <garrett@damore.org> | 2017-01-17 19:36:15 -0800 |
| commit | a00f1938497e629187ebc6035e03bb58d1017730 (patch) | |
| tree | 36f9694c9d1d94ef64f9686da3bf8cd971877f15 /src/core | |
| parent | eb3b131db73610274a41f04d8fd6b7cf879cc016 (diff) | |
| download | nng-a00f1938497e629187ebc6035e03bb58d1017730.tar.gz nng-a00f1938497e629187ebc6035e03bb58d1017730.tar.bz2 nng-a00f1938497e629187ebc6035e03bb58d1017730.zip | |
Pipe IDs are now tracked by hash table for performance.
This gives a better idea of pipe ID uniqueness, and is a step towards
conversion of the API to use IDs instead of pointers.
Diffstat (limited to 'src/core')
| -rw-r--r-- | src/core/pipe.c | 25 | ||||
| -rw-r--r-- | src/core/socket.c | 15 | ||||
| -rw-r--r-- | src/core/socket.h | 2 |
3 files changed, 26 insertions, 16 deletions
diff --git a/src/core/pipe.c b/src/core/pipe.c index 0633dea9..6cc93d98 100644 --- a/src/core/pipe.c +++ b/src/core/pipe.c @@ -121,6 +121,7 @@ nni_pipe_create(nni_pipe **pp, nni_ep *ep) p->p_tran_data = NULL; p->p_proto_data = NULL; p->p_active = 0; + p->p_id = 0; NNI_LIST_NODE_INIT(&p->p_node); // Make a copy of the transport ops. We can override entry points @@ -168,7 +169,6 @@ nni_pipe_start(nni_pipe *pipe) { int rv; int i; - int collide; nni_sock *sock = pipe->p_sock; nni_mtx_lock(&sock->s_mx); @@ -184,23 +184,16 @@ nni_pipe_start(nni_pipe *pipe) return (NNG_EPROTO); } - do { - // We generate a new pipe ID, but we make sure it does not - // collide with any we already have. This can only normally - // happen if we wrap -- i.e. we've had 4 billion or so pipes. - // XXX: consider making this a hash table!! - nni_pipe *check; - pipe->p_id = nni_random() & 0x7FFFFFFF; - collide = 0; - NNI_LIST_FOREACH (&sock->s_pipes, check) { - if ((pipe != check) && (check->p_id == pipe->p_id)) { - collide = 1; - break; - } - } - } while (collide); + rv = nni_idhash_alloc(sock->s_pipes_by_id, &pipe->p_id, pipe); + if (rv != 0) { + nni_pipe_bail(pipe); + nni_mtx_unlock(&sock->s_mx); + return (rv); + } if ((rv = sock->s_pipe_ops.pipe_add(pipe->p_proto_data)) != 0) { + nni_idhash_remove(sock->s_pipes_by_id, pipe->p_id); + pipe->p_id = 0; nni_pipe_bail(pipe); nni_mtx_unlock(&sock->s_mx); return (rv); diff --git a/src/core/socket.c b/src/core/socket.c index 1e9fe11f..e19485a5 100644 --- a/src/core/socket.c +++ b/src/core/socket.c @@ -47,6 +47,10 @@ nni_reaper(void *arg) nni_mtx_lock(&sock->s_mx); if ((pipe = nni_list_first(&sock->s_reaps)) != NULL) { nni_list_remove(&sock->s_reaps, pipe); + if (pipe->p_id != 0) { + nni_idhash_remove(sock->s_pipes_by_id, + pipe->p_id); + } if (((ep = pipe->p_ep) != NULL) && ((ep->ep_pipe == pipe))) { @@ -232,6 +236,15 @@ nni_sock_open(nni_sock **sockp, uint16_t pnum) goto fail; } + if ((rv = nni_idhash_create(&sock->s_pipes_by_id)) != 0) { + goto fail; + } + // Pipe IDs are always positive values with the upper bit clear. + // Start the IDs at a random place to minimize chances of PIPE ID + // reuse improperly. + nni_idhash_set_limits(sock->s_pipes_by_id, 1, 0x7FFFFFFF, + nni_random() & 0x7FFFFFFF); + rv = nni_ev_init(&sock->s_recv_ev, NNG_EV_CAN_RECV, sock); if (rv != 0) { goto fail; @@ -290,6 +303,7 @@ fail: nni_ev_fini(&sock->s_recv_ev); nni_msgq_fini(sock->s_urq); nni_msgq_fini(sock->s_uwq); + nni_idhash_destroy(sock->s_pipes_by_id); nni_cv_fini(&sock->s_notify_cv); nni_cv_fini(&sock->s_cv); nni_mtx_fini(&sock->s_notify_mx); @@ -428,6 +442,7 @@ nni_sock_close(nni_sock *sock) nni_msgq_fini(sock->s_uwq); nni_ev_fini(&sock->s_send_ev); nni_ev_fini(&sock->s_recv_ev); + nni_idhash_destroy(sock->s_pipes_by_id); nni_cv_fini(&sock->s_notify_cv); nni_cv_fini(&sock->s_cv); nni_mtx_fini(&sock->s_notify_mx); diff --git a/src/core/socket.h b/src/core/socket.h index 424b1321..2860ad46 100644 --- a/src/core/socket.h +++ b/src/core/socket.h @@ -42,6 +42,8 @@ struct nng_socket { nni_cv s_notify_cv; // wakes notify thread nni_mtx s_notify_mx; // protects s_notify list + nni_idhash * s_pipes_by_id; // pipes by id + nni_list s_reaps; // pipes to reap nni_thr s_reaper; nni_thr s_notifier; |
