lighttpd1.4/src/fdevent_select.c

110 lines
2.8 KiB
C
Raw Normal View History

#include "first.h"
#include "fdevent_impl.h"
#include "fdevent.h"
#include "buffer.h"
#include <sys/time.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#ifdef FDEVENT_USE_SELECT
__attribute_cold__
static int fdevent_select_reset(fdevents *ev) {
FD_ZERO(&(ev->select_set_read));
FD_ZERO(&(ev->select_set_write));
FD_ZERO(&(ev->select_set_error));
ev->select_max_fd = -1;
return 0;
}
static int fdevent_select_event_del(fdevents *ev, fdnode *fdn) {
int fd = fdn->fd;
FD_CLR(fd, &(ev->select_set_read));
FD_CLR(fd, &(ev->select_set_write));
FD_CLR(fd, &(ev->select_set_error));
return 0;
}
static int fdevent_select_event_set(fdevents *ev, fdnode *fdn, int events) {
int fd = fdn->fde_ndx = fdn->fd;
/* we should be protected by max-fds, but you never know */
force_assert(fd < ((int)FD_SETSIZE));
if (events & FDEVENT_IN) {
FD_SET(fd, &(ev->select_set_read));
} else {
FD_CLR(fd, &(ev->select_set_read));
}
if (events & FDEVENT_OUT) {
FD_SET(fd, &(ev->select_set_write));
} else {
FD_CLR(fd, &(ev->select_set_write));
}
FD_SET(fd, &(ev->select_set_error));
if (fd > ev->select_max_fd) ev->select_max_fd = fd;
return 0;
}
static int fdevent_select_event_get_revent(const fdevents *ev, int ndx) {
int revents = 0;
if (FD_ISSET(ndx, &ev->select_read)) revents |= FDEVENT_IN;
if (FD_ISSET(ndx, &ev->select_write)) revents |= FDEVENT_OUT;
if (FD_ISSET(ndx, &ev->select_error)) revents |= FDEVENT_ERR;
return revents;
}
static int fdevent_select_event_next_fdndx(const fdevents *ev, int ndx) {
const int max_fd = ev->select_max_fd + 1;
for (int i = (ndx < 0) ? 0 : ndx + 1; i < max_fd; ++i) {
if (FD_ISSET(i, &(ev->select_read))) return i;
if (FD_ISSET(i, &(ev->select_write))) return i;
if (FD_ISSET(i, &(ev->select_error))) return i;
}
return -1;
}
static int fdevent_select_poll(fdevents *ev, int timeout_ms) {
int n;
struct timeval tv;
tv.tv_sec = timeout_ms / 1000;
tv.tv_usec = (timeout_ms % 1000) * 1000;
ev->select_read = ev->select_set_read;
ev->select_write = ev->select_set_write;
ev->select_error = ev->select_set_error;
n = select(ev->select_max_fd + 1, &(ev->select_read), &(ev->select_write), &(ev->select_error), &tv);
for (int ndx = -1, i = 0; i < n; ++i) {
fdnode *fdn;
ndx = fdevent_select_event_next_fdndx(ev, ndx);
if (-1 == ndx) break;
fdn = ev->fdarray[ndx];
if (0 == ((uintptr_t)fdn & 0x3)) {
int revents = fdevent_select_event_get_revent(ev, ndx);
(*fdn->handler)(fdn->ctx, revents);
}
}
return n;
}
__attribute_cold__
int fdevent_select_init(fdevents *ev) {
ev->type = FDEVENT_HANDLER_SELECT;
ev->event_set = fdevent_select_event_set;
ev->event_del = fdevent_select_event_del;
ev->poll = fdevent_select_poll;
ev->reset = fdevent_select_reset;
return 0;
}
#endif