moonbridge

diff moonbridge.c @ 66:3d1f23f1dbc6

Work on non-blocking I/O; Improved efficiency of :readuntil(...)
author jbe
date Sat Apr 04 05:10:05 2015 +0200 (2015-04-04)
parents 8090fe97518a
children c488f2ea29aa
line diff
     1.1 --- a/moonbridge.c	Sat Apr 04 03:22:06 2015 +0200
     1.2 +++ b/moonbridge.c	Sat Apr 04 05:10:05 2015 +0200
     1.3 @@ -2202,27 +2202,6 @@
     1.4    return 1;
     1.5  }
     1.6  
     1.7 -static int moonbr_lua_tonatural(lua_State *L, int idx) {
     1.8 -  int isnum;
     1.9 -  lua_Number n;
    1.10 -  n = lua_tonumberx(L, idx, &isnum);
    1.11 -  if (isnum && n>=0 && n<INT_MAX && (lua_Number)(int)n == n) return n;
    1.12 -  else return -1;
    1.13 -}
    1.14 -
    1.15 -static int moonbr_lua_totimeval(lua_State *L, int idx, struct timeval *value) {
    1.16 -  int isnum;
    1.17 -  lua_Number n;
    1.18 -  n = lua_tonumberx(L, idx, &isnum);
    1.19 -  if (isnum && n>=0 && n<=100000000) {
    1.20 -    value->tv_sec = n;
    1.21 -    value->tv_usec = 1e6 * (n - value->tv_sec);
    1.22 -    return 1;
    1.23 -  } else {
    1.24 -    return 0;
    1.25 -  }
    1.26 -}
    1.27 -
    1.28  /* Memory allocator that allows limiting memory consumption */
    1.29  static void *moonbr_alloc (void *ud, void *ptr, size_t osize, size_t nsize) {
    1.30    (void)ud;  /* not used */
    1.31 @@ -2257,11 +2236,33 @@
    1.32    return ptr;
    1.33  }
    1.34  
    1.35 +/* Helper function to convert a value at the given stack index to a natural number */
    1.36 +static int moonbr_lua_tonatural(lua_State *L, int idx) {
    1.37 +  int isnum;
    1.38 +  lua_Number n;
    1.39 +  n = lua_tonumberx(L, idx, &isnum);
    1.40 +  if (isnum && n>=0 && n<INT_MAX && (lua_Number)(int)n == n) return n;
    1.41 +  else return -1;
    1.42 +}
    1.43 +
    1.44 +/* Helper function to convert a value at the given stack index to a timeval struct */
    1.45 +static int moonbr_lua_totimeval(lua_State *L, int idx, struct timeval *value) {
    1.46 +  int isnum;
    1.47 +  lua_Number n;
    1.48 +  n = lua_tonumberx(L, idx, &isnum);
    1.49 +  if (isnum && n>=0 && n<=100000000) {
    1.50 +    value->tv_sec = n;
    1.51 +    value->tv_usec = 1e6 * (n - value->tv_sec);
    1.52 +    return 1;
    1.53 +  } else {
    1.54 +    return 0;
    1.55 +  }
    1.56 +}
    1.57 +
    1.58  /* New function io.poll(...) */
    1.59  static int moonbr_io_poll(lua_State *L) {
    1.60 -  int idx_tbl = 1;
    1.61 -  int idx_timeout = 0;
    1.62    int i;
    1.63 +  luaL_Stream *stream;
    1.64    int fd, isnum;
    1.65    int nfds = 0;
    1.66    fd_set readfds, writefds, exceptfds;
    1.67 @@ -2270,82 +2271,73 @@
    1.68    FD_ZERO(&readfds);
    1.69    FD_ZERO(&writefds);
    1.70    FD_ZERO(&exceptfds);
    1.71 -  if (lua_type(L, 1) == LUA_TNUMBER) {
    1.72 -    idx_timeout = 1;
    1.73 -    idx_tbl = 2;
    1.74 -  }
    1.75 -  luaL_checktype(L, idx_tbl, LUA_TTABLE);
    1.76 -  for (i=1; ; i++) {
    1.77 -#if LUA_VERSION_NUM >= 503
    1.78 -    if (lua_geti(L, idx_tbl, i) == LUA_TNIL) break;
    1.79 -#else
    1.80 -    lua_pushinteger(L, i);
    1.81 -    lua_gettable(L, idx_tbl);
    1.82 -    if (lua_isnil(L, -1)) break;
    1.83 -#endif
    1.84 -    fd = lua_tointegerx(L, -1, &isnum);
    1.85 -    if (!isnum) luaL_error(L, "File descriptor is not an integer");
    1.86 -    FD_SET(fd, &readfds);
    1.87 -    if (fd+1 > nfds) nfds = fd+1;
    1.88 -    lua_pop(L, 1);
    1.89 -  }
    1.90 -  if (!idx_timeout && lua_type(L, 2) == LUA_TNUMBER) {
    1.91 -    idx_timeout = 2;
    1.92 -    idx_tbl = 3;
    1.93 -  } else {
    1.94 -    idx_tbl = 2;
    1.95 -  }
    1.96 -  if (!lua_isnoneornil(L, idx_tbl)) {
    1.97 -    luaL_checktype(L, idx_tbl, LUA_TTABLE);
    1.98 +  if (!lua_isnoneornil(L, 1)) {
    1.99 +    luaL_checktype(L, 1, LUA_TTABLE);
   1.100      for (i=1; ; i++) {
   1.101  #if LUA_VERSION_NUM >= 503
   1.102 -      if (lua_geti(L, idx_tbl, i) == LUA_TNIL) break;
   1.103 +      if (lua_geti(L, 1, i) == LUA_TNIL) break;
   1.104  #else
   1.105        lua_pushinteger(L, i);
   1.106 -      lua_gettable(L, idx_tbl);
   1.107 +      lua_gettable(L, 1);
   1.108        if (lua_isnil(L, -1)) break;
   1.109  #endif
   1.110 -      fd = lua_tointegerx(L, -1, &isnum);
   1.111 -      if (!isnum) luaL_error(L, "File descriptor is not an integer");
   1.112 +      stream = luaL_testudata(L, -1, LUA_FILEHANDLE);
   1.113 +      if (stream) {
   1.114 +        fd = fileno(stream->f);
   1.115 +      } else {
   1.116 +        fd = lua_tointegerx(L, -1, &isnum);
   1.117 +        if (!isnum) luaL_error(L, "File descriptor is not an integer");
   1.118 +      }
   1.119 +      FD_SET(fd, &readfds);
   1.120 +      if (fd+1 > nfds) nfds = fd+1;
   1.121 +      lua_pop(L, 1);
   1.122 +    }
   1.123 +  }
   1.124 +  if (!lua_isnoneornil(L, 2)) {
   1.125 +    luaL_checktype(L, 2, LUA_TTABLE);
   1.126 +    for (i=1; ; i++) {
   1.127 +#if LUA_VERSION_NUM >= 503
   1.128 +      if (lua_geti(L, 2, i) == LUA_TNIL) break;
   1.129 +#else
   1.130 +      lua_pushinteger(L, i);
   1.131 +      lua_gettable(L, 2);
   1.132 +      if (lua_isnil(L, -1)) break;
   1.133 +#endif
   1.134 +      stream = luaL_testudata(L, -1, LUA_FILEHANDLE);
   1.135 +      if (stream) {
   1.136 +        fd = fileno(stream->f);
   1.137 +      } else {
   1.138 +        fd = lua_tointegerx(L, -1, &isnum);
   1.139 +        if (!isnum) luaL_error(L, "File descriptor is not an integer");
   1.140 +      }
   1.141        FD_SET(fd, &writefds);
   1.142        if (fd+1 > nfds) nfds = fd+1;
   1.143        lua_pop(L, 1);
   1.144      }
   1.145      lua_pop(L, 2);
   1.146 -    if (!idx_timeout && !lua_isnoneornil(L, 3)) idx_timeout = 3;
   1.147    }
   1.148 -  if (idx_timeout) {
   1.149 -    luaL_argcheck(
   1.150 -      L,
   1.151 -      moonbr_lua_totimeval(L, idx_timeout, &timeout),
   1.152 -      idx_timeout,
   1.153 -      "not a valid timeout"
   1.154 -    );
   1.155 +  if (!lua_isnoneornil(L, 3)) {
   1.156 +    luaL_argcheck(L, moonbr_lua_totimeval(L, 3, &timeout), 3, "not a valid timeout");
   1.157    }
   1.158    status = select(nfds, &readfds, &writefds, &exceptfds, &timeout);
   1.159    if (status == -1) {
   1.160      if (errno == EINTR) {
   1.161        lua_pushboolean(L, 0);
   1.162 +      lua_pushliteral(L, "Signal received while polling file descriptors");
   1.163 +      return 2;
   1.164      } else {
   1.165        char errmsg[MOONBR_MAXSTRERRORLEN];
   1.166        strerror_r(errno, errmsg, MOONBR_MAXSTRERRORLEN);  /* use thread-safe call in case child created threads */
   1.167 -      luaL_error(L, "Unexpected error during \"select\" system call: %s", errmsg);
   1.168 +      return luaL_error(L, "Unexpected error during \"select\" system call: %s", errmsg);
   1.169      }
   1.170    } else if (status == 0) {
   1.171      lua_pushboolean(L, 0);
   1.172 +    lua_pushliteral(L, "Timeout while polling file descriptors");
   1.173 +    return 2;
   1.174    } else {
   1.175      lua_pushboolean(L, 1);
   1.176 +    return 1;
   1.177    }
   1.178 -  return 1;
   1.179 -}
   1.180 -
   1.181 -/* New method for Lua file objects: get file descriptor */
   1.182 -static int moonbr_io_getfd(lua_State *L) {
   1.183 -  luaL_Stream *stream;
   1.184 -  stream = luaL_checkudata(L, 1, LUA_FILEHANDLE);
   1.185 -  if (!stream->closef) luaL_error(L, "attempt to use a closed file");
   1.186 -  lua_pushinteger(L, fileno(stream->f));
   1.187 -  return 1;
   1.188  }
   1.189  
   1.190  /* New method for Lua file objects: check if non-blocking reading is possible */
   1.191 @@ -2389,32 +2381,6 @@
   1.192    return 0;
   1.193  }
   1.194  
   1.195 -/* New method for Lua file objects: set blocking or non-blocking I/O */
   1.196 -static int moonbr_io_setblocking(lua_State *L) {
   1.197 -  luaL_Stream *stream;
   1.198 -  int blocking;
   1.199 -  int fd, flags;
   1.200 -  stream = luaL_checkudata(L, 1, LUA_FILEHANDLE);
   1.201 -  luaL_checktype(L, 2, LUA_TBOOLEAN);
   1.202 -  blocking = lua_toboolean(L, 2);
   1.203 -  if (!stream->closef) luaL_error(L, "attempt to use a closed file");
   1.204 -  fd = fileno_unlocked(stream->f);
   1.205 -  flags = fcntl(fd, F_GETFL, 0);
   1.206 -  if (flags == -1) goto moonbr_io_setblocking_error;
   1.207 -  if (blocking) flags &= ~ O_NONBLOCK;
   1.208 -  else flags |= O_NONBLOCK;
   1.209 -  if (fcntl(fd, F_SETFL, flags) == -1) goto moonbr_io_setblocking_error;
   1.210 -  lua_pushboolean(L, 1);
   1.211 -  return 1;
   1.212 -  moonbr_io_setblocking_error:
   1.213 -  {
   1.214 -    char errmsg[MOONBR_MAXSTRERRORLEN];
   1.215 -    strerror_r(errno, errmsg, MOONBR_MAXSTRERRORLEN);  /* use thread-safe call in case child created threads */
   1.216 -    luaL_error(L, "Unexpected error in method \"setblocking\" of FILE handle: %s", errmsg);
   1.217 -  }
   1.218 -  return 0;
   1.219 -}
   1.220 -
   1.221  /* New method for Lua file objects: read until terminator or length exceeded */
   1.222  static int moonbr_io_readuntil(lua_State *L) {
   1.223    luaL_Stream *stream;
   1.224 @@ -2434,12 +2400,14 @@
   1.225    luaL_buffinit(L, &buf);
   1.226    if (!maxlen) maxlen = -1;
   1.227    terminator = terminatorstr[0];
   1.228 +  flockfile(file);
   1.229    while (maxlen > 0 ? maxlen-- : maxlen) {
   1.230 -    byte = fgetc(file);
   1.231 +    byte = getc_unlocked(file);
   1.232      if (byte == EOF) {
   1.233        if (ferror(file)) {
   1.234          char errmsg[MOONBR_MAXSTRERRORLEN];
   1.235          strerror_r(errno, errmsg, MOONBR_MAXSTRERRORLEN);  /* use thread-safe call in case child created threads */
   1.236 +        funlockfile(file);
   1.237          lua_pushnil(L);
   1.238          lua_pushstring(L, errmsg);
   1.239          return 2;
   1.240 @@ -2450,6 +2418,7 @@
   1.241      luaL_addchar(&buf, byte);
   1.242      if (byte == terminator) break;
   1.243    }
   1.244 +  funlockfile(file);
   1.245    luaL_pushresult(&buf);
   1.246    if (!lua_rawlen(L, -1)) lua_pushnil(L);
   1.247    return 1;
   1.248 @@ -2931,12 +2900,8 @@
   1.249        moonbr_terminate_error();
   1.250      }
   1.251      lua_getfield(L, -1, "__index");
   1.252 -    lua_pushcfunction(L, moonbr_io_getfd);
   1.253 -    lua_setfield(L, -2, "getfd");
   1.254 -    lua_pushcfunction(L, moonbr_io_pending);
   1.255 +    eua_pushcfunction(L, moonbr_io_pending);
   1.256      lua_setfield(L, -2, "pending");
   1.257 -    lua_pushcfunction(L, moonbr_io_setblocking);
   1.258 -    lua_setfield(L, -2, "setblocking");
   1.259      lua_pushcfunction(L, moonbr_io_readuntil);
   1.260      lua_setfield(L, -2, "readuntil");
   1.261      lua_pop(L, 2);

Impressum / About Us