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