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