Use poll() instead of select()
authorSteven Barth <steven@midlink.org>
Sun, 8 Feb 2009 20:57:36 +0000 (20:57 +0000)
committerSteven Barth <steven@midlink.org>
Sun, 8 Feb 2009 20:57:36 +0000 (20:57 +0000)
Reintroduce nanosleep()

libs/nixio/Makefile
libs/nixio/src/nixio.c
libs/nixio/src/nixio.h
libs/nixio/src/poll.c [new file with mode: 0644]
libs/nixio/src/select.c [deleted file]

index a2ce5da..b6d9485 100644 (file)
@@ -5,7 +5,7 @@ include ../../build/gccconfig.mk
 %.o: %.c
        $(COMPILE) $(LUA_CFLAGS) $(FPIC) -c -o $@ $< 
 
-compile: src/nixio.o src/socket.o src/sockopt.o src/bind.o src/address.o src/select.o
+compile: src/nixio.o src/socket.o src/sockopt.o src/bind.o src/address.o src/poll.o
        $(LINK) $(SHLIB_FLAGS) -o src/nixio.so src/*.o
        mkdir -p dist$(LUA_LIBRARYDIR)
        cp src/nixio.so dist$(LUA_LIBRARYDIR)/nixio.so
index 1152f2c..6f3e079 100644 (file)
 #include <lua.h>
 #include <lualib.h>
 #include <lauxlib.h>
-#include <unistd.h>
-#include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
-#include <sys/socket.h>
 #include <errno.h>
 #include "nixio.h"
 
@@ -109,7 +106,7 @@ LUALIB_API int luaopen_nixio(lua_State *L) {
        nixio_open_sockopt(L);
        nixio_open_bind(L);
        nixio_open_address(L);
-       nixio_open_select(L);
+       nixio_open_poll(L);
 
        /* module version */
        lua_pushnumber(L, VERSION);
index ce79c9a..d39c31b 100644 (file)
@@ -24,7 +24,7 @@ void nixio_open_socket(lua_State *L);
 void nixio_open_sockopt(lua_State *L);
 void nixio_open_bind(lua_State *L);
 void nixio_open_address(lua_State *L);
-void nixio_open_select(lua_State *L);
+void nixio_open_poll(lua_State *L);
 
 /* Method functions */
 
diff --git a/libs/nixio/src/poll.c b/libs/nixio/src/poll.c
new file mode 100644 (file)
index 0000000..7a397b9
--- /dev/null
@@ -0,0 +1,181 @@
+/*
+ * nixio - Linux I/O library for lua
+ *
+ *   Copyright (C) 2009 Steven Barth <steven@midlink.org>
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+#include <lua.h>
+#include <lualib.h>
+#include <lauxlib.h>
+#include <poll.h>
+#include <time.h>
+#include <errno.h>
+#include <stdlib.h>
+#include "nixio.h"
+
+
+/**
+ * nanosleep()
+ */
+static int nixio_nanosleep(lua_State *L) {
+       struct timespec req, rem;
+       req.tv_sec = luaL_optint(L, 1, 0);
+       req.tv_nsec = luaL_optint(L, 2, 0);
+
+       int status = nanosleep(&req, &rem);
+       if (!status) {
+               lua_pushboolean(L, 1);
+               return 1;
+       } else {
+               if (errno == EINTR) {
+                       lua_pushboolean(L, 0);
+                       lua_pushinteger(L, rem.tv_sec);
+                       lua_pushinteger(L, rem.tv_nsec);
+                       return 3;
+               } else {
+                       return nixio__perror(L);
+               }
+       }
+}
+
+/**
+ * Checks whether a flag is set in the table and translates it into a bitmap
+ */
+static void nixio_poll_flags__w(lua_State *L, int *map, int f, const char *t) {
+       lua_pushstring(L, t);
+       lua_rawget(L, -2);
+       if (lua_toboolean(L, -1)) {
+               *map |= f;
+       }
+       lua_pop(L, 1);
+}
+
+/**
+ * Checks whether a flag is set in the bitmap and sets the matching table value
+ */
+static void nixio_poll_flags__r(lua_State *L, int *map, int f, const char *t) {
+       lua_pushstring(L, t);
+       if (*map & f) {
+               lua_pushboolean(L, 1);
+       } else {
+               lua_pushnil(L);
+       }
+       lua_rawset(L, -3);
+}
+
+/**
+ * Translate integer to poll flags and vice versa
+ */
+static int nixio_poll_flags(lua_State *L) {
+       int flags;
+       if (lua_istable(L, 1)) {
+               lua_settop(L, 1);
+               flags = 0;
+               nixio_poll_flags__w(L, &flags, POLLIN, "in");
+               nixio_poll_flags__w(L, &flags, POLLPRI, "pri");
+               nixio_poll_flags__w(L, &flags, POLLOUT, "out");
+               nixio_poll_flags__w(L, &flags, POLLERR, "err");
+               nixio_poll_flags__w(L, &flags, POLLHUP, "hup");
+               nixio_poll_flags__w(L, &flags, POLLNVAL, "nval");
+               lua_pushinteger(L, flags);
+       } else {
+               flags = luaL_checkinteger(L, 1);
+               lua_newtable(L);
+               nixio_poll_flags__r(L, &flags, POLLIN, "in");
+               nixio_poll_flags__r(L, &flags, POLLPRI, "pri");
+               nixio_poll_flags__r(L, &flags, POLLOUT, "out");
+               nixio_poll_flags__r(L, &flags, POLLERR, "err");
+               nixio_poll_flags__r(L, &flags, POLLHUP, "hup");
+               nixio_poll_flags__r(L, &flags, POLLNVAL, "nval");
+       }
+       return 1;
+}
+
+/**
+ * poll({{fd = socket, events = FLAGS}, ...}, timeout)
+ */
+static int nixio_poll(lua_State *L) {
+       int len = lua_objlen(L, 1);
+       int i, fd;
+       int timeout = luaL_optint(L, 2, 0);
+       int status = -1;
+
+       /* we are being abused as sleep() replacement... */
+       if (lua_isnoneornil(L, 1) || len < 1) {
+               return nixio__pstatus(L, !poll(NULL, 0, timeout));
+       }
+
+       luaL_checktype(L, 1, LUA_TTABLE);
+       struct pollfd *fds = calloc(len, sizeof(struct pollfd));
+
+       for (i = 0; i < len; i++) {
+               lua_rawgeti(L, 1, i+1);
+               if (!lua_istable(L, -1)) {
+                       free(fds);
+                       return luaL_argerror(L, 1, "invalid datastructure");
+               }
+
+               lua_pushliteral(L, "fd");
+               lua_rawget(L, -2);
+               fd = nixio__tofd(L, -1);
+               if (fd == -1) {
+                       free(fds);
+                       return luaL_argerror(L, 1, "invalid fd in datastructure");
+               }
+               fds[i].fd = fd;
+
+               lua_pushliteral(L, "events");
+               lua_rawget(L, -3);
+               fds[i].events = (short)lua_tointeger(L, -1);
+
+               lua_pop(L, 3);
+       }
+
+       status = poll(fds, (nfds_t)len, timeout);
+
+       if (status < 1) {
+               free(fds);
+               return nixio__perror(L);
+       }
+
+       for (i = 0; i < len; i++) {
+               lua_rawgeti(L, 1, i+1);
+
+               lua_pushliteral(L, "revents");
+               lua_pushinteger(L, fds[i].revents);
+               lua_rawset(L, -3);
+
+               lua_pop(L, 1);
+       }
+
+       free(fds);
+
+       lua_pushinteger(L, status);
+       lua_pushvalue(L, 1);
+
+       return 2;
+}
+
+/* module table */
+static const luaL_reg R[] = {
+       {"nanosleep",   nixio_nanosleep},
+       {"poll",                nixio_poll},
+       {"poll_flags",  nixio_poll_flags},
+       {NULL,                  NULL}
+};
+
+void nixio_open_poll(lua_State *L) {
+       luaL_register(L, NULL, R);
+}
diff --git a/libs/nixio/src/select.c b/libs/nixio/src/select.c
deleted file mode 100644 (file)
index e88075c..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * nixio - Linux I/O library for lua
- *
- *   Copyright (C) 2009 Steven Barth <steven@midlink.org>
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- *  you may not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-
-#include <lua.h>
-#include <lualib.h>
-#include <lauxlib.h>
-#include <sys/select.h>
-#include "nixio.h"
-
-static int nixio_select(lua_State *L) {
-       int nfds = 0, tmpfd = -1, i = 0, j = 0, o = 0, k, tlen;
-       fd_set rfds, wfds, xfds;
-       fd_set *fdsets[3] = {&rfds, &wfds, &xfds};
-       FD_ZERO(fdsets[0]);
-       FD_ZERO(fdsets[1]);
-       FD_ZERO(fdsets[2]);
-
-       struct timeval timeout;
-       timeout.tv_sec = luaL_optinteger(L, 4, 0);
-       timeout.tv_usec = luaL_optinteger(L, 5, 0);
-
-       /* create fdsets */
-       for (i=0; i<3; i++) {
-               o = i + 1;
-               if (lua_isnoneornil(L, o)) {
-                       fdsets[i] = NULL;
-                       continue;
-               }
-
-               luaL_checktype(L, o, LUA_TTABLE);
-               tlen = lua_objlen(L, o);
-               luaL_argcheck(L, tlen <= FD_SETSIZE, o, "too many fds");
-
-               for (j=1; j<=tlen; j++) {
-                       lua_rawgeti(L, o, j);
-                       tmpfd = nixio__checkfd(L, -1);
-                       FD_SET(tmpfd, fdsets[i]);
-                       if (tmpfd >= nfds) {
-                               nfds = tmpfd + 1;
-                       }
-                       lua_pop(L, 1);
-               }
-       }
-
-       int stat = select(nfds, fdsets[0], fdsets[1], fdsets[2], &timeout);
-
-       if (stat < 0) {
-               return nixio__perror(L);
-       } else if (stat == 0) {
-               lua_pushinteger(L, stat);
-               for (i=1; i<=3; i++) {
-                       if (lua_isnoneornil(L, i)) {
-                               lua_pushnil(L);
-                       } else {
-                               lua_newtable(L);
-                       }
-               }
-       } else {
-               lua_pushinteger(L, stat);
-
-               /* create return tables */
-               for (i=0; i<3; i++) {
-                       o = i + 1;
-                       if (lua_isnoneornil(L, o)) {
-                               lua_pushnil(L);
-                               continue;
-                       }
-
-                       lua_newtable(L);
-                       tlen = lua_objlen(L, o);
-                       k = 1;
-
-                       for (j=1; j<=tlen; j++) {
-                               lua_rawgeti(L, o, j);
-                               tmpfd = nixio__tofd(L, -1);
-                               if (FD_ISSET(tmpfd, fdsets[i])) {
-                                       lua_rawseti(L, -2, k++);
-                               } else {
-                                       lua_pop(L, 1);
-                               }
-                       }
-               }
-       }
-       return 4;
-}
-
-/* module table */
-static const luaL_reg R[] = {
-       {"select",      nixio_select},
-       {NULL,                  NULL}
-};
-
-void nixio_open_select(lua_State *L) {
-       luaL_register(L, NULL, R);
-}