moonbridge

changeset 77:38e7bd13200d

Use write instead of fwrite for non-blocking I/O
author jbe
date Sun Apr 05 01:17:06 2015 +0200 (2015-04-05)
parents d4265136ce88
children 0ec070d6f5d9
files moonbridge.c reference.txt
line diff
     1.1 --- a/moonbridge.c	Sun Apr 05 00:35:11 2015 +0200
     1.2 +++ b/moonbridge.c	Sun Apr 05 01:17:06 2015 +0200
     1.3 @@ -2484,38 +2484,36 @@
     1.4  
     1.5  /* New methods for Lua file objects: non-blocking writing */
     1.6  static int moonbr_io_write_nb_impl(lua_State *L) {
     1.7 -  luaL_Stream *stream;
     1.8 -  FILE *file;
     1.9 -  int argc, i;
    1.10 +  int fd, argc, i;
    1.11    const char *str;
    1.12    size_t strlen;
    1.13 -  size_t written;
    1.14 -  stream = luaL_checkudata(L, 1, LUA_FILEHANDLE);
    1.15 -  file = stream->f;
    1.16 +  ssize_t written;
    1.17 +  luaL_Buffer buf;
    1.18 +  fd = lua_tointeger(L, 1);
    1.19    argc = lua_gettop(L) - 1;
    1.20    for (i=0; i<argc; i++) {
    1.21      str = luaL_checklstring(L, 2+i, &strlen);
    1.22 -    written = fwrite(str, 1, strlen, file);
    1.23 -    if (written < strlen) {
    1.24 -      if (errno == EAGAIN) {
    1.25 -        luaL_Buffer buf;
    1.26 -        clearerr(file);
    1.27 -        luaL_buffinit(L, &buf);
    1.28 -        luaL_addlstring(&buf, str+written, strlen-written);
    1.29 -        for (i=i+1; i<argc; i++) {
    1.30 -          luaL_checkstring(L, 2+i);
    1.31 -          lua_pushvalue(L, 2+i);
    1.32 -          luaL_addvalue(&buf);
    1.33 -        }
    1.34 -        luaL_pushresult(&buf);
    1.35 -        return 1;
    1.36 -      } else {
    1.37 +    written = write(fd, str, strlen);
    1.38 +    if (written < 0) {
    1.39 +      if (errno != EAGAIN) {
    1.40          char errmsg[MOONBR_MAXSTRERRORLEN];
    1.41          strerror_r(errno, errmsg, MOONBR_MAXSTRERRORLEN);  /* use thread-safe call in case child created threads */
    1.42          lua_pushnil(L);
    1.43          lua_pushstring(L, errmsg);
    1.44          return 2;
    1.45        }
    1.46 +      written = 0;
    1.47 +    }
    1.48 +    if (written < strlen) {
    1.49 +      luaL_buffinit(L, &buf);
    1.50 +      luaL_addlstring(&buf, str+written, strlen-written);
    1.51 +      for (i=i+1; i<argc; i++) {
    1.52 +        luaL_checkstring(L, 2+i);
    1.53 +        lua_pushvalue(L, 2+i);
    1.54 +        luaL_addvalue(&buf);
    1.55 +      }
    1.56 +      luaL_pushresult(&buf);
    1.57 +      return 1;
    1.58      }
    1.59    }
    1.60    lua_pushliteral(L, "");
    1.61 @@ -2527,24 +2525,22 @@
    1.62    int fd, flags;
    1.63    stream = luaL_checkudata(L, 1, LUA_FILEHANDLE);
    1.64    if (!stream->closef) luaL_error(L, "attempt to use a closed file");
    1.65 +  file = stream->f;
    1.66 +  if (fflush(file)) goto moonbr_io_write_nb_error;
    1.67    lua_pushcfunction(L, moonbr_io_write_nb_impl);
    1.68 -  lua_insert(L, 1);
    1.69 -  file = stream->f;
    1.70 -  if (ferror(file)) {
    1.71 -    lua_pushnil(L);
    1.72 -    lua_pushliteral(L, "Previous error condition on file handle");
    1.73 -    return 2;
    1.74 -  }
    1.75 +  lua_insert(L, 2);
    1.76    fd = fileno(file);
    1.77 +  lua_pushinteger(L, fd);
    1.78 +  lua_insert(L, 3);
    1.79    flags = fcntl(fd, F_GETFL, 0);
    1.80    if (flags == -1) goto moonbr_io_write_nb_error;
    1.81    if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) goto moonbr_io_write_nb_error;
    1.82 -  if (lua_pcall(L, lua_gettop(L) - 1, LUA_MULTRET, 0)) {
    1.83 +  if (lua_pcall(L, lua_gettop(L) - 2, LUA_MULTRET, 0)) {
    1.84      fcntl(fd, F_SETFL, flags);
    1.85      return lua_error(L);
    1.86    }
    1.87    if (fcntl(fd, F_SETFL, flags) == -1) goto moonbr_io_write_nb_error;
    1.88 -  return lua_gettop(L);
    1.89 +  return lua_gettop(L) - 1;
    1.90    moonbr_io_write_nb_error:
    1.91    {
    1.92      char errmsg[MOONBR_MAXSTRERRORLEN];
     2.1 --- a/reference.txt	Sun Apr 05 00:35:11 2015 +0200
     2.2 +++ b/reference.txt	Sun Apr 05 01:17:06 2015 +0200
     2.3 @@ -57,7 +57,8 @@
     2.4  
     2.5  Alternatively to file descriptors, the tables may contain file handles, in
     2.6  which case the file descriptor is automatically extracted from the file handle
     2.7 -and the file handle's buffer is additionally tested for pending data.
     2.8 +and, in case of waiting for reading, the file handle's buffer is additionally
     2.9 +tested for pending data.
    2.10  
    2.11  Please note that support for non-blocking I/O operations is limited if you use
    2.12  ordinary file handles (as Moonbridge does). It is possible, however, to wait
    2.13 @@ -194,6 +195,11 @@
    2.14  In case of an I/O error, nil (as first result value) and an error message (as
    2.15  second result value) are returned.
    2.16  
    2.17 +Note: Using this method will automatically flush any unflushed data written
    2.18 +through previous socket.output:write(...) calls. Thus, if any data was
    2.19 +previously written in a blocking fashion and has not been flushed, then the
    2.20 +socket.output:write_nb(...) call may block.
    2.21 +
    2.22  This method is also available for any other Lua file handle.
    2.23  
    2.24  

Impressum / About Us