commit 1fd66195d8f4195019304c61798f81a1ed6f1360
Author: Oswald Buddenhagen <[email protected]>
Date:   Sat Nov 29 19:15:50 2014 +0100

    change socket notifier design
    
    instead of keeping the structures in an opaque array (which was a shadow
    of the struct pollfd array if poll() was supported), make them directly
    addressable.
    
    this has the advantage that notifier-altering operations (mostly
    en-/disabling) don't need to look up the structure by file handle each
    time.
    on the downside, data locality in the main loop is worse.
    neither of these have any real effect on performance.
    
    note that the structures are not allocated separately, but embedded into
    the the parent structure (like sockets already were).

 src/common.h |   21 ++++++--
 src/socket.c |   20 ++++----
 src/socket.h |    2 +
 src/util.c   |  136 +++++++++++++++++++++++--------------------------
 4 files changed, 93 insertions(+), 86 deletions(-)

diff --git a/src/common.h b/src/common.h
index 468663d..eb021b8 100644
--- a/src/common.h
+++ b/src/common.h
@@ -127,6 +127,18 @@ uchar arc4_getbyte( void );
 
 int bucketsForSize( int size );
 
+typedef struct notifier {
+       struct notifier *next;
+       void (*cb)( int what, void *aux );
+       void *aux;
+#ifdef HAVE_SYS_POLL_H
+       int index;
+#else
+       int fd, events;
+#endif
+       int faked;
+} notifier_t;
+
 #ifdef HAVE_SYS_POLL_H
 # include <sys/poll.h>
 #else
@@ -135,10 +147,11 @@ int bucketsForSize( int size );
 # define POLLERR 8
 #endif
 
-void add_fd( int fd, void (*cb)( int events, void *aux ), void *aux );
-void conf_fd( int fd, int and_events, int or_events );
-void fake_fd( int fd, int events );
-void del_fd( int fd );
+void init_notifier( notifier_t *sn, int fd, void (*cb)( int, void * ), void 
*aux );
+void conf_notifier( notifier_t *sn, int and_events, int or_events );
+static INLINE void fake_notifier( notifier_t *sn, int events ) { sn->faked |= 
events; }
+void wipe_notifier( notifier_t *sn );
+
 void main_loop( void );
 
 #endif
diff --git a/src/socket.c b/src/socket.c
index 0ea4ae8..bfe4810 100644
--- a/src/socket.c
+++ b/src/socket.c
@@ -67,7 +67,7 @@ ssl_return( const char *func, conn_t *conn, int ret )
        case SSL_ERROR_NONE:
                return ret;
        case SSL_ERROR_WANT_WRITE:
-               conf_fd( conn->fd, POLLIN, POLLOUT );
+               conf_notifier( &conn->notify, POLLIN, POLLOUT );
                /* fallthrough */
        case SSL_ERROR_WANT_READ:
                return 0;
@@ -290,13 +290,13 @@ socket_open_internal( conn_t *sock, int fd )
 {
        sock->fd = fd;
        fcntl( fd, F_SETFL, O_NONBLOCK );
-       add_fd( fd, socket_fd_cb, sock );
+       init_notifier( &sock->notify, fd, socket_fd_cb, sock );
 }
 
 static void
 socket_close_internal( conn_t *sock )
 {
-       del_fd( sock->fd );
+       wipe_notifier( &sock->notify );
        close( sock->fd );
        sock->fd = -1;
 }
@@ -434,7 +434,7 @@ socket_connect_one( conn_t *sock )
                        socket_connect_failed( sock );
                        return;
                }
-               conf_fd( s, 0, POLLOUT );
+               conf_notifier( &sock->notify, 0, POLLOUT );
                sock->state = SCK_CONNECTING;
                info( "\v\n" );
                return;
@@ -464,7 +464,7 @@ socket_connected( conn_t *conn )
 #ifdef HAVE_IPV6
        freeaddrinfo( conn->addrs );
 #endif
-       conf_fd( conn->fd, 0, POLLIN );
+       conf_notifier( &conn->notify, 0, POLLIN );
        conn->state = SCK_READY;
        conn->callbacks.connect( 1, conn->callback_aux );
 }
@@ -517,7 +517,7 @@ socket_fill( conn_t *sock )
                if ((n = ssl_return( "read from", sock, SSL_read( sock->ssl, 
buf, len ) )) <= 0)
                        return;
                if (n == len && SSL_pending( sock->ssl ))
-                       fake_fd( sock->fd, POLLIN );
+                       fake_notifier( &sock->notify, POLLIN );
        } else
 #endif
        {
@@ -592,10 +592,10 @@ do_write( conn_t *sock, char *buf, int len )
                        socket_fail( sock );
                } else {
                        n = 0;
-                       conf_fd( sock->fd, POLLIN, POLLOUT );
+                       conf_notifier( &sock->notify, POLLIN, POLLOUT );
                }
        } else if (n != len) {
-               conf_fd( sock->fd, POLLIN, POLLOUT );
+               conf_notifier( &sock->notify, POLLIN, POLLOUT );
        }
        return n;
 }
@@ -632,7 +632,7 @@ do_queued_write( conn_t *conn )
        }
 #ifdef HAVE_LIBSSL
        if (conn->ssl && SSL_pending( conn->ssl ))
-               fake_fd( conn->fd, POLLIN );
+               fake_notifier( &conn->notify, POLLIN );
 #endif
        return conn->write_callback( conn->callback_aux );
 }
@@ -700,7 +700,7 @@ socket_fd_cb( int events, void *aux )
        }
 
        if (events & POLLOUT)
-               conf_fd( conn->fd, POLLIN, 0 );
+               conf_notifier( &conn->notify, POLLIN, 0 );
 
 #ifdef HAVE_LIBSSL
        if (conn->state == SCK_STARTTLS) {
diff --git a/src/socket.h b/src/socket.h
index e09a9e1..a641d8f 100644
--- a/src/socket.h
+++ b/src/socket.h
@@ -86,6 +86,8 @@ typedef struct {
        } callbacks;
        void *callback_aux;
 
+       notifier_t notify;
+
        /* writing */
        buff_chunk_t *write_buf, **write_buf_append; /* buffer head & tail */
        int write_offset; /* offset into buffer head */
diff --git a/src/util.c b/src/util.c
index 83b5ce1..b11b137 100644
--- a/src/util.c
+++ b/src/util.c
@@ -584,84 +584,73 @@ bucketsForSize( int size )
        }
 }
 
+static notifier_t *notifiers;
+static int changed;  /* Iterator may be invalid now. */
 #ifdef HAVE_SYS_POLL_H
 static struct pollfd *pollfds;
+static int npolls, rpolls;
 #else
 # ifdef HAVE_SYS_SELECT_H
 #  include <sys/select.h>
 # endif
-# define pollfds fdparms
 #endif
-static struct {
-       void (*cb)( int what, void *aux );
-       void *aux;
-#ifndef HAVE_SYS_POLL_H
-       int fd, events;
-#endif
-       int faked;
-} *fdparms;
-static int npolls, rpolls, changed;
-
-static int
-find_fd( int fd )
-{
-       int n;
-
-       for (n = 0; n < npolls; n++)
-               if (pollfds[n].fd == fd)
-                       return n;
-       return -1;
-}
 
 void
-add_fd( int fd, void (*cb)( int events, void *aux ), void *aux )
+init_notifier( notifier_t *sn, int fd, void (*cb)( int, void * ), void *aux )
 {
-       int n;
-
-       assert( find_fd( fd ) < 0 );
-       n = npolls++;
+#ifdef HAVE_SYS_POLL_H
+       int idx = npolls++;
        if (rpolls < npolls) {
                rpolls = npolls;
-#ifdef HAVE_SYS_POLL_H
-               pollfds = nfrealloc(pollfds, npolls * sizeof(*pollfds));
-#endif
-               fdparms = nfrealloc(fdparms, npolls * sizeof(*fdparms));
+               pollfds = nfrealloc( pollfds, npolls * sizeof(*pollfds) );
        }
-       pollfds[n].fd = fd;
-       pollfds[n].events = 0; /* POLLERR & POLLHUP implicit */
-       fdparms[n].faked = 0;
-       fdparms[n].cb = cb;
-       fdparms[n].aux = aux;
-       changed = 1;
-}
-
-void
-conf_fd( int fd, int and_events, int or_events )
-{
-       int n = find_fd( fd );
-       assert( n >= 0 );
-       pollfds[n].events = (pollfds[n].events & and_events) | or_events;
+       pollfds[idx].fd = fd;
+       pollfds[idx].events = 0; /* POLLERR & POLLHUP implicit */
+       sn->index = idx;
+#else
+       sn->fd = fd;
+       sn->events = 0;
+#endif
+       sn->cb = cb;
+       sn->aux = aux;
+       sn->faked = 0;
+       sn->next = notifiers;
+       notifiers = sn;
 }
 
 void
-fake_fd( int fd, int events )
+conf_notifier( notifier_t *sn, int and_events, int or_events )
 {
-       int n = find_fd( fd );
-       assert( n >= 0 );
-       fdparms[n].faked |= events;
+#ifdef HAVE_SYS_POLL_H
+       int idx = sn->index;
+       pollfds[idx].events = (pollfds[idx].events & and_events) | or_events;
+#else
+       sn->events = (sn->events & and_events) | or_events;
+#endif
 }
 
 void
-del_fd( int fd )
+wipe_notifier( notifier_t *sn )
 {
-       int n = find_fd( fd );
-       assert( n >= 0 );
-       npolls--;
+       notifier_t **snp;
 #ifdef HAVE_SYS_POLL_H
-       memmove(pollfds + n, pollfds + n + 1, (npolls - n) * sizeof(*pollfds));
+       int idx;
 #endif
-       memmove(fdparms + n, fdparms + n + 1, (npolls - n) * sizeof(*fdparms));
+
+       for (snp = &notifiers; *snp != sn; snp = &(*snp)->next)
+               assert( *snp );
+       *snp = sn->next;
+       sn->next = 0;
        changed = 1;
+
+#ifdef HAVE_SYS_POLL_H
+       idx = sn->index;
+       memmove( pollfds + idx, pollfds + idx + 1, (--npolls - idx) * 
sizeof(*pollfds) );
+       for (sn = notifiers; sn; sn = sn->next) {
+               if (sn->index > idx)
+                       sn->index--;
+       }
+#endif
 }
 
 #define shifted_bit(in, from, to) \
@@ -672,12 +661,13 @@ del_fd( int fd )
 static void
 event_wait( void )
 {
-       int m, n;
+       notifier_t *sn;
+       int m;
 
 #ifdef HAVE_SYS_POLL_H
        int timeout = -1;
-       for (n = 0; n < npolls; n++)
-               if (fdparms[n].faked) {
+       for (sn = notifiers; sn; sn = sn->next)
+               if (sn->faked) {
                        timeout = 0;
                        break;
                }
@@ -685,16 +675,18 @@ event_wait( void )
                perror( "poll() failed in event loop" );
                abort();
        }
-       for (n = 0; n < npolls; n++)
-               if ((m = pollfds[n].revents | fdparms[n].faked)) {
+       for (sn = notifiers; sn; sn = sn->next) {
+               int n = sn->index;
+               if ((m = pollfds[n].revents | sn->faked)) {
                        assert( !(m & POLLNVAL) );
-                       fdparms[n].faked = 0;
-                       fdparms[n].cb( m | shifted_bit( m, POLLHUP, POLLIN ), 
fdparms[n].aux );
+                       sn->faked = 0;
+                       sn->cb( m | shifted_bit( m, POLLHUP, POLLIN ), sn->aux 
);
                        if (changed) {
                                changed = 0;
                                break;
                        }
                }
+       }
 #else
        struct timeval *timeout = 0;
        static struct timeval null_tv;
@@ -705,13 +697,13 @@ event_wait( void )
        FD_ZERO( &wfds );
        FD_ZERO( &efds );
        m = -1;
-       for (n = 0; n < npolls; n++) {
-               if (fdparms[n].faked)
+       for (sn = notifiers; sn; sn = sn->next) {
+               if (sn->faked)
                        timeout = &null_tv;
-               fd = fdparms[n].fd;
-               if (fdparms[n].events & POLLIN)
+               fd = sn->fd;
+               if (sn->events & POLLIN)
                        FD_SET( fd, &rfds );
-               if (fdparms[n].events & POLLOUT)
+               if (sn->events & POLLOUT)
                        FD_SET( fd, &wfds );
                FD_SET( fd, &efds );
                if (fd > m)
@@ -721,9 +713,9 @@ event_wait( void )
                perror( "select() failed in event loop" );
                abort();
        }
-       for (n = 0; n < npolls; n++) {
-               fd = fdparms[n].fd;
-               m = fdparms[n].faked;
+       for (sn = notifiers; sn; sn = sn->next) {
+               fd = sn->fd;
+               m = sn->faked;
                if (FD_ISSET( fd, &rfds ))
                        m |= POLLIN;
                if (FD_ISSET( fd, &wfds ))
@@ -731,8 +723,8 @@ event_wait( void )
                if (FD_ISSET( fd, &efds ))
                        m |= POLLERR;
                if (m) {
-                       fdparms[n].faked = 0;
-                       fdparms[n].cb( m, fdparms[n].aux );
+                       sn->faked = 0;
+                       sn->cb( m, sn->aux );
                        if (changed) {
                                changed = 0;
                                break;
@@ -745,6 +737,6 @@ event_wait( void )
 void
 main_loop( void )
 {
-       while (npolls)
+       while (notifiers)
                event_wait();
 }

------------------------------------------------------------------------------
New Year. New Location. New Benefits. New Data Center in Ashburn, VA.
GigeNET is offering a free month of service with a new server in Ashburn.
Choose from 2 high performing configs, both with 100TB of bandwidth.
Higher redundancy.Lower latency.Increased capacity.Completely compliant.
http://p.sf.net/sfu/gigenet
_______________________________________________
isync-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/isync-devel

Reply via email to