# HG changeset patch # User jbe # Date 1428518298 -7200 # Node ID 8fce76ef321f1c4237b351571361372ea702999b # Parent 11d03470ef199b6cfcdc963e93ac012a770a6bb8 Added moonbridge_io.poll(...) diff -r 11d03470ef19 -r 8fce76ef321f moonbridge_io.c --- a/moonbridge_io.c Wed Apr 08 19:37:09 2015 +0200 +++ b/moonbridge_io.c Wed Apr 08 20:38:18 2015 +0200 @@ -591,6 +591,82 @@ return moonbr_io_tcpconnect_impl(L, 1); } +static int moonbr_io_poll(lua_State *L) { + moonbr_io_handle_t *handle; + int fd, isnum; + int nfds = 0; + fd_set readfds, writefds, exceptfds; + struct timeval timeout = {0, }; + int status; + FD_ZERO(&readfds); + FD_ZERO(&writefds); + FD_ZERO(&exceptfds); + if (!lua_isnoneornil(L, 1)) { + luaL_checktype(L, 1, LUA_TTABLE); + for (lua_pushnil(L); lua_next(L, 1); lua_pop(L, 1)) { + if (lua_toboolean(L, -1)) { + handle = luaL_testudata(L, -2, MOONBR_IO_HANDLE_MT_REGKEY); + if (handle) { + fd = handle->fd; + if (fd < 0) luaL_error(L, "Handle in illegal state"); + } else { + fd = lua_tointegerx(L, -2, &isnum); + if (!isnum) luaL_error(L, "File descriptor is not an integer"); + } + FD_SET(fd, &readfds); + if (fd+1 > nfds) nfds = fd+1; + } + } + } + if (!lua_isnoneornil(L, 2)) { + luaL_checktype(L, 2, LUA_TTABLE); + for (lua_pushnil(L); lua_next(L, 2); lua_pop(L, 1)) { + if (lua_toboolean(L, -1)) { + handle = luaL_testudata(L, -2, MOONBR_IO_HANDLE_MT_REGKEY); + if (handle) { + fd = handle->fd; + if (fd < 0) luaL_error(L, "Handle in illegal state"); + } else { + fd = lua_tointegerx(L, -2, &isnum); + if (!isnum) luaL_error(L, "File descriptor is not an integer"); + } + FD_SET(fd, &writefds); + if (fd+1 > nfds) nfds = fd+1; + } + } + } + if (!lua_isnoneornil(L, 3)) { + lua_Number n; + n = lua_tonumberx(L, 3, &isnum); + if (isnum && n>=0 && n<100000000) { + timeout.tv_sec = n; + timeout.tv_usec = 1e6 * (n - timeout.tv_sec); + } else { + luaL_argcheck(L, 0, 3, "not a valid timeout"); + } + status = select(nfds, &readfds, &writefds, &exceptfds, &timeout); + } else { + status = select(nfds, &readfds, &writefds, &exceptfds, NULL); + } + if (status == -1) { + if (errno == EINTR) { + lua_pushboolean(L, 0); + lua_pushliteral(L, "Signal received while polling file descriptors"); + return 2; + } else { + moonbr_io_errmsg(); + return luaL_error(L, "Unexpected error during \"select\" system call: %s", errmsg); + } + } else if (status == 0) { + lua_pushboolean(L, 0); + lua_pushliteral(L, "Timeout while polling file descriptors"); + return 2; + } else { + lua_pushboolean(L, 1); + return 1; + } +} + static const struct luaL_Reg moonbr_io_handle_methods[] = { {"read", moonbr_io_read}, {"read_nb", moonbr_io_read_nb}, @@ -616,6 +692,7 @@ static const struct luaL_Reg moonbr_io_module_funcs[] = { {"tcpconnect", moonbr_io_tcpconnect}, {"tcpconnect_nb", moonbr_io_tcpconnect_nb}, + {"poll", moonbr_io_poll}, {NULL, NULL} }; diff -r 11d03470ef19 -r 8fce76ef321f reference.txt --- a/reference.txt Wed Apr 08 19:37:09 2015 +0200 +++ b/reference.txt Wed Apr 08 20:38:18 2015 +0200 @@ -236,6 +236,19 @@ library to support blocking as well as nonblocking I/O operations. +### moonbridge_io.poll(input_set, output_set, timeout) + +This function waits for at least one of the given file descriptors and/or +I/O handles to be ready for input or output. The two sets of file descriptors +and/or handles must contain the file descriptor or handle as a key, and a value +which does evaluate to true. If a set is nil, it is treated as being empty. + +Returns true when at least one file descriptor or handle is ready for reading +or writing respectively. Returns false (as first return value) plus a status +message (as second return value) in case of timeout or when a signal was +received. + + ### moonbridge_io.tcpconnect(hostname, port) Tries to open a TCP connection with the given host and TCP port number. Returns