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