2016-03-19 15:14:35 +00:00
|
|
|
#include "first.h"
|
|
|
|
|
2017-11-01 04:16:38 +00:00
|
|
|
#include "fdevent_impl.h"
|
2009-10-11 14:31:42 +00:00
|
|
|
#include "fdevent.h"
|
|
|
|
#include "buffer.h"
|
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
#include <sys/time.h>
|
|
|
|
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
2017-11-01 04:16:38 +00:00
|
|
|
#ifdef FDEVENT_USE_SELECT
|
2005-02-20 14:27:00 +00:00
|
|
|
|
2019-02-23 06:35:58 +00:00
|
|
|
__attribute_cold__
|
2005-02-20 14:27:00 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2019-02-23 06:35:58 +00:00
|
|
|
static int fdevent_select_event_del(fdevents *ev, fdnode *fdn) {
|
|
|
|
int fd = fdn->fd;
|
2005-02-20 14:27:00 +00:00
|
|
|
FD_CLR(fd, &(ev->select_set_read));
|
|
|
|
FD_CLR(fd, &(ev->select_set_write));
|
|
|
|
FD_CLR(fd, &(ev->select_set_error));
|
2019-02-23 06:35:58 +00:00
|
|
|
return 0;
|
2005-02-20 14:27:00 +00:00
|
|
|
}
|
|
|
|
|
2019-02-23 06:35:58 +00:00
|
|
|
static int fdevent_select_event_set(fdevents *ev, fdnode *fdn, int events) {
|
|
|
|
int fd = fdn->fde_ndx = fdn->fd;
|
2005-02-20 14:27:00 +00:00
|
|
|
|
2005-08-31 09:16:18 +00:00
|
|
|
/* we should be protected by max-fds, but you never know */
|
2014-02-16 13:08:20 +00:00
|
|
|
force_assert(fd < ((int)FD_SETSIZE));
|
2005-08-31 09:16:18 +00:00
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
if (events & FDEVENT_IN) {
|
|
|
|
FD_SET(fd, &(ev->select_set_read));
|
2010-08-17 09:54:42 +00:00
|
|
|
} else {
|
|
|
|
FD_CLR(fd, &(ev->select_set_read));
|
2005-02-20 14:27:00 +00:00
|
|
|
}
|
|
|
|
if (events & FDEVENT_OUT) {
|
|
|
|
FD_SET(fd, &(ev->select_set_write));
|
2010-08-17 09:54:42 +00:00
|
|
|
} else {
|
|
|
|
FD_CLR(fd, &(ev->select_set_write));
|
2005-02-20 14:27:00 +00:00
|
|
|
}
|
|
|
|
FD_SET(fd, &(ev->select_set_error));
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
if (fd > ev->select_max_fd) ev->select_max_fd = fd;
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2019-02-23 06:35:58 +00:00
|
|
|
return 0;
|
2005-02-20 14:27:00 +00:00
|
|
|
}
|
|
|
|
|
2019-12-10 03:13:44 +00:00
|
|
|
static int fdevent_select_event_get_revent(const fdevents *ev, int ndx) {
|
2005-02-20 14:27:00 +00:00
|
|
|
int revents = 0;
|
2019-02-23 06:35:58 +00:00
|
|
|
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;
|
2005-02-20 14:27:00 +00:00
|
|
|
return revents;
|
|
|
|
}
|
|
|
|
|
2019-02-14 02:34:59 +00:00
|
|
|
static int fdevent_select_event_next_fdndx(const fdevents *ev, int ndx) {
|
2019-02-23 06:35:58 +00:00
|
|
|
const int max_fd = ev->select_max_fd + 1;
|
|
|
|
for (int i = (ndx < 0) ? 0 : ndx + 1; i < max_fd; ++i) {
|
2010-08-06 21:57:15 +00:00
|
|
|
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;
|
2005-02-20 14:27:00 +00:00
|
|
|
}
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2010-08-06 21:57:15 +00:00
|
|
|
return -1;
|
2005-02-20 14:27:00 +00:00
|
|
|
}
|
|
|
|
|
2019-02-14 02:34:59 +00:00
|
|
|
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);
|
2019-02-16 09:52:49 +00:00
|
|
|
if (-1 == ndx) break;
|
2019-02-14 02:34:59 +00:00
|
|
|
fdn = ev->fdarray[ndx];
|
|
|
|
if (0 == ((uintptr_t)fdn & 0x3)) {
|
|
|
|
int revents = fdevent_select_event_get_revent(ev, ndx);
|
2019-12-21 03:03:51 +00:00
|
|
|
(*fdn->handler)(fdn->ctx, revents);
|
2019-02-14 02:34:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
|
2019-02-23 06:35:58 +00:00
|
|
|
__attribute_cold__
|
2005-02-20 14:27:00 +00:00
|
|
|
int fdevent_select_init(fdevents *ev) {
|
2019-02-23 06:35:58 +00:00
|
|
|
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;
|
2005-02-20 14:27:00 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|