moonbridge

changeset 80:1a0346580e6d

Blocking :write(...) and :flush(...) methods in I/O library
author jbe
date Mon Apr 06 01:35:23 2015 +0200 (2015-04-06)
parents 22dbb9d09f02
children e1aec772a6ab
files moonbridge_io.c moonbridge_io.h
line diff
     1.1 --- a/moonbridge_io.c	Sun Apr 05 18:01:31 2015 +0200
     1.2 +++ b/moonbridge_io.c	Mon Apr 06 01:35:23 2015 +0200
     1.3 @@ -14,20 +14,128 @@
     1.4  #include <lauxlib.h>
     1.5  #include <lualib.h>
     1.6  
     1.7 +#define MOONBR_IO_MAXSTRERRORLEN 80
     1.8 +#define MOONBR_IO_WRITEBUFLEN 4096
     1.9 +
    1.10 +#define moonbr_io_errmsg() \
    1.11 +  char errmsg[MOONBR_IO_MAXSTRERRORLEN]; \
    1.12 +  strerror_r(errno, errmsg, MOONBR_IO_MAXSTRERRORLEN)
    1.13 +
    1.14 +
    1.15  #define MOONBR_IO_HANDLE_MT_REGKEY "moonbridge_io_handle"
    1.16  #define MOONBR_IO_HANDLE_PUBLIC_MT_REGKEY "moonbridge_io_handle_public"
    1.17  
    1.18  typedef struct {
    1.19    int fd;
    1.20 +  int writecnt;
    1.21 +  char writebuf[MOONBR_IO_WRITEBUFLEN];
    1.22  } moonbr_io_handle_t;
    1.23  
    1.24 -void moonbr_io_pushhandle(lua_State *L, int fd) {
    1.25 +static int moonbr_io_close(lua_State *L) {
    1.26 +  moonbr_io_handle_t *handle;
    1.27 +  handle = luaL_checkudata(L, 1, MOONBR_IO_HANDLE_MT_REGKEY);
    1.28 +  if (handle->fd < 0) luaL_error(L, "Attempt to close a closed I/O handle");
    1.29 +  if (close(handle->fd)) {
    1.30 +    handle->fd = -1;
    1.31 +    moonbr_io_errmsg();
    1.32 +    lua_pushnil(L);
    1.33 +    lua_pushstring(L, errmsg);
    1.34 +    return 2;
    1.35 +  }
    1.36 +  handle->fd = -1;
    1.37 +  lua_pushboolean(L, 1);
    1.38 +  return 1;
    1.39 +}
    1.40 +
    1.41 +static int moonbr_io_write(lua_State *L) {
    1.42 +  moonbr_io_handle_t *handle;
    1.43 +  int i, top;
    1.44 +  const char *str;
    1.45 +  size_t strlen;
    1.46 +  size_t written;
    1.47 +  ssize_t result;
    1.48 +  handle = luaL_checkudata(L, 1, MOONBR_IO_HANDLE_MT_REGKEY);
    1.49 +  if (handle->writecnt < 0) {
    1.50 +    lua_pushnil(L);
    1.51 +    lua_pushliteral(L, "Previous write error");
    1.52 +    return 2;
    1.53 +  }
    1.54 +  top = lua_gettop(L);
    1.55 +  for (i=2; i<=top; i++) {
    1.56 +    str = luaL_checklstring(L, i, &strlen);
    1.57 +    while (strlen) {
    1.58 +      if (strlen < MOONBR_IO_WRITEBUFLEN - handle->writecnt) {
    1.59 +        memcpy(handle->writebuf + handle->writecnt, str, strlen);
    1.60 +        handle->writecnt += strlen;
    1.61 +        break;
    1.62 +      } else {
    1.63 +        written = 0;
    1.64 +        memcpy(handle->writebuf + handle->writecnt, str, MOONBR_IO_WRITEBUFLEN - handle->writecnt);
    1.65 +        while (written < MOONBR_IO_WRITEBUFLEN) {
    1.66 +          result = write(handle->fd, handle->writebuf + written, MOONBR_IO_WRITEBUFLEN - written);
    1.67 +          if (result < 0) {
    1.68 +            if (errno != EINTR) {
    1.69 +              moonbr_io_errmsg();
    1.70 +              handle->writecnt = -1;
    1.71 +              lua_pushnil(L);
    1.72 +              lua_pushstring(L, errmsg);
    1.73 +              return 2;
    1.74 +            }
    1.75 +          } else {
    1.76 +            written += result;
    1.77 +          }
    1.78 +        }
    1.79 +        str += MOONBR_IO_WRITEBUFLEN - handle->writecnt;
    1.80 +        strlen -= MOONBR_IO_WRITEBUFLEN - handle->writecnt;
    1.81 +        handle->writecnt = 0;
    1.82 +      }
    1.83 +    }
    1.84 +  }
    1.85 +  lua_settop(L, 1);
    1.86 +  return 1;
    1.87 +}
    1.88 +
    1.89 +static int moonbr_io_flush(lua_State *L) {
    1.90 +  moonbr_io_handle_t *handle;
    1.91 +  size_t written;
    1.92 +  ssize_t result;
    1.93 +  handle = luaL_checkudata(L, 1, MOONBR_IO_HANDLE_MT_REGKEY);
    1.94 +  if (handle->writecnt < 0) {
    1.95 +    lua_pushnil(L);
    1.96 +    lua_pushliteral(L, "Previous write error");
    1.97 +    return 2;
    1.98 +  }
    1.99 +  written = 0;
   1.100 +  while (written < handle->writecnt) {
   1.101 +    result = write(handle->fd, handle->writebuf + written, handle->writecnt - written);
   1.102 +    if (result < 0) {
   1.103 +      if (errno != EINTR) {
   1.104 +        moonbr_io_errmsg();
   1.105 +        handle->writecnt = -1;
   1.106 +        lua_pushnil(L);
   1.107 +        lua_pushstring(L, errmsg);
   1.108 +        return 2;
   1.109 +      }
   1.110 +    } else {
   1.111 +      written += result;
   1.112 +    }
   1.113 +  }
   1.114 +  handle->writecnt = 0;
   1.115 +  lua_settop(L, 1);
   1.116 +  return 1;
   1.117 +}
   1.118 +
   1.119 +void moonbr_io_pushhandle(lua_State *L, int fd, int gc_idx) {
   1.120    moonbr_io_handle_t *handle;
   1.121    handle = lua_newuserdata(L, sizeof(moonbr_io_handle_t));
   1.122    handle->fd = fd;
   1.123 +  handle->writecnt = 0;
   1.124    luaL_getmetatable(L, MOONBR_IO_HANDLE_MT_REGKEY);
   1.125    lua_setmetatable(L, -2);
   1.126    lua_newtable(L);  // uservalue
   1.127 +  if (gc_idx) lua_pushvalue(L, gc_idx);
   1.128 +  else lua_pushcfunction(L, moonbr_io_close);
   1.129 +  lua_setfield(L, -2, "gc");
   1.130    lua_newtable(L);  // public
   1.131    luaL_getmetatable(L, MOONBR_IO_HANDLE_PUBLIC_MT_REGKEY);
   1.132    lua_setmetatable(L, -2);
   1.133 @@ -36,6 +144,7 @@
   1.134  }
   1.135  
   1.136  static int moonbr_io_handleindex(lua_State *L) {
   1.137 +  luaL_checkudata(L, 1, MOONBR_IO_HANDLE_MT_REGKEY);
   1.138    lua_getuservalue(L, 1);
   1.139    lua_getfield(L, -1, "public");
   1.140    lua_pushvalue(L, 2);
   1.141 @@ -44,6 +153,7 @@
   1.142  }
   1.143  
   1.144  static int moonbr_io_handlenewindex(lua_State *L) {
   1.145 +  luaL_checkudata(L, 1, MOONBR_IO_HANDLE_MT_REGKEY);
   1.146    lua_getuservalue(L, 1);
   1.147    lua_getfield(L, -1, "public");
   1.148    lua_pushvalue(L, 2);
   1.149 @@ -52,24 +162,34 @@
   1.150    return 0;
   1.151  }
   1.152  
   1.153 +static int moonbr_io_handlegc(lua_State *L) {
   1.154 +  moonbr_io_handle_t *handle;
   1.155 +  handle = luaL_checkudata(L, 1, MOONBR_IO_HANDLE_MT_REGKEY);
   1.156 +  if (handle->fd >= 0) {
   1.157 +    lua_getuservalue(L, 1);
   1.158 +    lua_getfield(L, -1, "gc");
   1.159 +    lua_pushvalue(L, 1);
   1.160 +    lua_call(L, 1, 0);
   1.161 +  }
   1.162 +  return 0;
   1.163 +}
   1.164 +
   1.165  static int moonbr_io_getdummy(lua_State *L) {
   1.166 -  moonbr_io_pushhandle(L, 1);
   1.167 +  moonbr_io_pushhandle(L, 2, 0);
   1.168    return 1;
   1.169  }
   1.170  
   1.171 -static int moonbr_io_testmethod(lua_State *L) {
   1.172 -  fprintf(stderr, "DEBUG\n");
   1.173 -  return 0;
   1.174 -}
   1.175 -
   1.176  static const struct luaL_Reg moonbr_io_handle_methods[] = {
   1.177 -  {"testmethod", moonbr_io_testmethod},
   1.178 +  {"close", moonbr_io_close},
   1.179 +  {"write", moonbr_io_write},
   1.180 +  {"flush", moonbr_io_flush},
   1.181    {NULL, NULL}
   1.182  };
   1.183  
   1.184  static const struct luaL_Reg moonbr_io_handle_metamethods[] = {
   1.185    {"__index", moonbr_io_handleindex},
   1.186    {"__newindex", moonbr_io_handlenewindex},
   1.187 +  {"__gc", moonbr_io_handlegc},
   1.188    {NULL, NULL}
   1.189  };
   1.190  
   1.191 @@ -80,9 +200,13 @@
   1.192  
   1.193  int luaopen_moonbridge_io(lua_State *L) {
   1.194  
   1.195 +  lua_newtable(L);  // module
   1.196 +
   1.197    lua_newtable(L);  // public metatable
   1.198    lua_newtable(L);  // handle methods
   1.199    luaL_setfuncs(L, moonbr_io_handle_methods, 0);
   1.200 +  lua_pushvalue(L, -1);
   1.201 +  lua_setfield(L, -4, "handle");
   1.202    lua_setfield(L, -2, "__index");
   1.203    lua_setfield(L, LUA_REGISTRYINDEX, MOONBR_IO_HANDLE_PUBLIC_MT_REGKEY);
   1.204  
   1.205 @@ -90,7 +214,6 @@
   1.206    luaL_setfuncs(L, moonbr_io_handle_metamethods, 0);
   1.207    lua_setfield(L, LUA_REGISTRYINDEX, MOONBR_IO_HANDLE_MT_REGKEY);
   1.208  
   1.209 -  lua_newtable(L);  // module
   1.210    luaL_setfuncs(L, moonbr_io_module_funcs, 0);
   1.211    return 1;
   1.212  
     2.1 --- a/moonbridge_io.h	Sun Apr 05 18:01:31 2015 +0200
     2.2 +++ b/moonbridge_io.h	Mon Apr 06 01:35:23 2015 +0200
     2.3 @@ -1,4 +1,4 @@
     2.4  
     2.5 -void moonbr_io_pushhandle(lua_State *L, int fd);
     2.6 +void moonbr_io_pushhandle(lua_State *L, int fd, int gc_idx);
     2.7  int luaopen_moonbridge_io(lua_State *L);
     2.8  

Impressum / About Us