From 9fe4d4ea9c054e539ab679ed2e9c076c35beb69d Mon Sep 17 00:00:00 2001 From: etobi Date: Tue, 3 Sep 2013 09:48:45 +0200 Subject: Imported Upstream version 1.1.1+rev1355 --- util/alevt/fdset.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 util/alevt/fdset.c (limited to 'util/alevt/fdset.c') diff --git a/util/alevt/fdset.c b/util/alevt/fdset.c new file mode 100644 index 0000000..99edac4 --- /dev/null +++ b/util/alevt/fdset.c @@ -0,0 +1,97 @@ +#include +#include +#include +#include "dllist.h" +#include "misc.h" +#include "fdset.h" + +struct fdset fds[1]; /* global fd list */ + + +int fdset_init(struct fdset *fds) +{ + dl_init(fds->list); + fds->del_count = 0; + return 0; +} + + +int fdset_add_fd(struct fdset *fds, int fd, void *handler, void *data) +{ + struct fdset_node *fn; + + if (fd < 0) + return -1; + if (handler == 0) + return -1; + + for (fn = PTR fds->list->first; fn->node->next; fn = PTR fn->node->next) + if (fn->fd == fd) + return -1; + + if (not(fn = malloc(sizeof(*fn)))) + return -1; + fn->fd = fd; + fn->handler = handler; + fn->data = data; + dl_insert_last(fds->list, fn->node); + return 0; +} + + +int fdset_del_fd(struct fdset *fds, int fd) +{ + struct fdset_node *fn; + + for (fn = PTR fds->list->first; fn->node->next; fn = PTR fn->node->next) + if (fn->fd == fd) + { + dl_remove(fn->node); + free(fn); + fds->del_count++; + return 0; + } + return -1; +} + + +int fdset_select(struct fdset *fds, int timeout) +{ + struct fdset_node *fn; + fd_set rfds[1]; + struct timeval tv[1], *tvp = 0; + int max_fd, x, del_count; + + FD_ZERO(rfds); + max_fd = 0; + for (fn = PTR fds->list->first; fn->node->next; fn = PTR fn->node->next) + { + FD_SET(fn->fd, rfds); + if (fn->fd >= max_fd) + max_fd = fn->fd + 1; + } + + if (timeout >= 0) + { + tv->tv_sec = timeout/1000; + tv->tv_usec = timeout%1000*1000; + tvp = tv; + } + + x = select(max_fd, rfds, 0, 0, tvp); + if (x <= 0) + return x; + + /* A little bit complicated. A called handler may modify the fdset... */ +restart: + del_count = fds->del_count; + for (fn = PTR fds->list->first; fn->node->next; fn = PTR fn->node->next) + if (FD_ISSET(fn->fd, rfds)) + { + FD_CLR(fn->fd, rfds); + fn->handler(fn->data, fn->fd); + if (fds->del_count != del_count) + goto restart; + } + return 1; +} -- cgit v1.2.3