aboutsummaryrefslogtreecommitdiff
path: root/src/select.c
diff options
context:
space:
mode:
authorDiego Nehab <diego@tecgraf.puc-rio.br>2004-06-15 06:24:00 +0000
committerDiego Nehab <diego@tecgraf.puc-rio.br>2004-06-15 06:24:00 +0000
commit58096449c6044b7aade5cd41cfd71c6bec1d273d (patch)
tree1814ffebe89c4c2556d84f97f66db37a7e8b4554 /src/select.c
parent9ed7f955e5fc69af9bf1794fa2c8cd227981ba24 (diff)
downloadluasocket-58096449c6044b7aade5cd41cfd71c6bec1d273d.tar.gz
luasocket-58096449c6044b7aade5cd41cfd71c6bec1d273d.tar.bz2
luasocket-58096449c6044b7aade5cd41cfd71c6bec1d273d.zip
Manual is almost done. HTTP is missing.
Implemented new distribution scheme. Select is now purely C. HTTP reimplemented seems faster dunno why. LTN12 functions that coroutines fail gracefully.
Diffstat (limited to 'src/select.c')
-rw-r--r--src/select.c221
1 files changed, 146 insertions, 75 deletions
diff --git a/src/select.c b/src/select.c
index 1ebd82c..13f9d6e 100644
--- a/src/select.c
+++ b/src/select.c
@@ -9,26 +9,21 @@
9#include <lua.h> 9#include <lua.h>
10#include <lauxlib.h> 10#include <lauxlib.h>
11 11
12#include "luasocket.h"
13#include "socket.h" 12#include "socket.h"
14#include "auxiliar.h"
15#include "select.h" 13#include "select.h"
16 14
17/*=========================================================================*\ 15/*=========================================================================*\
18* Internal function prototypes. 16* Internal function prototypes.
19\*=========================================================================*/ 17\*=========================================================================*/
20static int meth_set(lua_State *L); 18static int getfd(lua_State *L);
21static int meth_isset(lua_State *L); 19static int dirty(lua_State *L);
22static int c_select(lua_State *L); 20static int collect_fd(lua_State *L, int tab, int max_fd, int itab, fd_set *set);
21static int check_dirty(lua_State *L, int tab, int dtab, fd_set *set);
22static void return_fd(lua_State *L, fd_set *set, int max_fd,
23 int itab, int tab, int start);
24static void make_assoc(lua_State *L, int tab);
23static int global_select(lua_State *L); 25static int global_select(lua_State *L);
24 26
25/* fd_set object methods */
26static luaL_reg set[] = {
27 {"set", meth_set},
28 {"isset", meth_isset},
29 {NULL, NULL}
30};
31
32/* functions in library namespace */ 27/* functions in library namespace */
33static luaL_reg func[] = { 28static luaL_reg func[] = {
34 {"select", global_select}, 29 {"select", global_select},
@@ -36,22 +31,13 @@ static luaL_reg func[] = {
36}; 31};
37 32
38/*=========================================================================*\ 33/*=========================================================================*\
39* Internal function prototypes. 34* Exported functions
40\*=========================================================================*/ 35\*=========================================================================*/
41/*-------------------------------------------------------------------------*\ 36/*-------------------------------------------------------------------------*\
42* Initializes module 37* Initializes module
43\*-------------------------------------------------------------------------*/ 38\*-------------------------------------------------------------------------*/
44int select_open(lua_State *L) 39int select_open(lua_State *L) {
45{ 40 luaL_openlib(L, NULL, func, 0);
46 /* get select auxiliar lua function from lua code and register
47 * pass it as an upvalue to global_select */
48#ifdef LUASOCKET_COMPILED
49#include "select.lch"
50#else
51 lua_dofile(L, "select.lua");
52#endif
53 luaL_openlib(L, NULL, func, 1);
54 aux_newclass(L, "select{fd_set}", set);
55 return 0; 41 return 0;
56} 42}
57 43
@@ -61,64 +47,149 @@ int select_open(lua_State *L)
61/*-------------------------------------------------------------------------*\ 47/*-------------------------------------------------------------------------*\
62* Waits for a set of sockets until a condition is met or timeout. 48* Waits for a set of sockets until a condition is met or timeout.
63\*-------------------------------------------------------------------------*/ 49\*-------------------------------------------------------------------------*/
64static int global_select(lua_State *L) 50static int global_select(lua_State *L) {
65{ 51 int timeout, rtab, wtab, itab, max_fd, ret, ndirty;
66 fd_set *read_fd_set, *write_fd_set; 52 fd_set rset, wset;
67 /* make sure we have enough arguments (nil is the default) */ 53 FD_ZERO(&rset); FD_ZERO(&wset);
68 lua_settop(L, 3); 54 lua_settop(L, 3);
69 /* check timeout */ 55 timeout = lua_isnil(L, 3) ? -1 : (int)(luaL_checknumber(L, 3) * 1000);
70 if (!lua_isnil(L, 3) && !lua_isnumber(L, 3)) 56 lua_newtable(L); itab = lua_gettop(L);
71 luaL_argerror(L, 3, "number or nil expected"); 57 lua_newtable(L); rtab = lua_gettop(L);
72 /* select auxiliar lua function to be called comes first */ 58 lua_newtable(L); wtab = lua_gettop(L);
73 lua_pushvalue(L, lua_upvalueindex(1)); 59 max_fd = collect_fd(L, 1, -1, itab, &rset);
74 lua_insert(L, 1); 60 ndirty = check_dirty(L, 1, rtab, &rset);
75 /* pass fd_set objects */ 61 timeout = ndirty > 0? 0: timeout;
76 read_fd_set = (fd_set *) lua_newuserdata(L, sizeof(fd_set)); 62 max_fd = collect_fd(L, 2, max_fd, itab, &wset);
77 FD_ZERO(read_fd_set); 63 ret = sock_select(max_fd+1, &rset, &wset, NULL, timeout);
78 aux_setclass(L, "select{fd_set}", -1); 64 if (ret > 0 || (ret == 0 && ndirty > 0)) {
79 write_fd_set = (fd_set *) lua_newuserdata(L, sizeof(fd_set)); 65 return_fd(L, &rset, max_fd+1, itab, rtab, ndirty);
80 FD_ZERO(write_fd_set); 66 return_fd(L, &wset, max_fd+1, itab, wtab, 0);
81 aux_setclass(L, "select{fd_set}", -1); 67 make_assoc(L, rtab);
82 /* pass select auxiliar C function */ 68 make_assoc(L, wtab);
83 lua_pushcfunction(L, c_select); 69 return 2;
84 /* call select auxiliar lua function */ 70 } else if (ret == 0) {
85 lua_call(L, 6, 3); 71 lua_pushstring(L, "timeout");
86 return 3; 72 return 3;
73 } else {
74 lua_pushnil(L);
75 lua_pushnil(L);
76 lua_pushstring(L, "error");
77 return 3;
78 }
87} 79}
88 80
89/*=========================================================================*\ 81/*=========================================================================*\
90* Lua methods 82* Internal functions
91\*=========================================================================*/ 83\*=========================================================================*/
92static int meth_set(lua_State *L) 84static int getfd(lua_State *L) {
93{ 85 int fd = -1;
94 fd_set *set = (fd_set *) aux_checkclass(L, "select{fd_set}", 1); 86 lua_pushstring(L, "getfd");
95 t_sock fd = (t_sock) lua_tonumber(L, 2); 87 lua_gettable(L, -2);
96 if (fd >= 0) FD_SET(fd, set); 88 if (!lua_isnil(L, -1)) {
97 return 0; 89 lua_pushvalue(L, -2);
90 lua_call(L, 1, 1);
91 if (lua_isnumber(L, -1))
92 fd = lua_tonumber(L, -1);
93 }
94 lua_pop(L, 1);
95 return fd;
98} 96}
99 97
100static int meth_isset(lua_State *L) 98static int dirty(lua_State *L) {
101{ 99 int is = 0;
102 fd_set *set = (fd_set *) aux_checkclass(L, "select{fd_set}", 1); 100 lua_pushstring(L, "dirty");
103 t_sock fd = (t_sock) lua_tonumber(L, 2); 101 lua_gettable(L, -2);
104 if (fd >= 0 && FD_ISSET(fd, set)) lua_pushnumber(L, 1); 102 if (!lua_isnil(L, -1)) {
105 else lua_pushnil(L); 103 lua_pushvalue(L, -2);
106 return 1; 104 lua_call(L, 1, 1);
105 is = lua_toboolean(L, -1);
106 }
107 lua_pop(L, 1);
108 return is;
107} 109}
108 110
109/*=========================================================================*\ 111static int collect_fd(lua_State *L, int tab, int max_fd,
110* Internal functions 112 int itab, fd_set *set) {
111\*=========================================================================*/ 113 int i = 1;
112static int c_select(lua_State *L) 114 if (lua_isnil(L, tab))
113{ 115 return max_fd;
114 int max_fd = (int) lua_tonumber(L, 1); 116 while (1) {
115 fd_set *read_fd_set = (fd_set *) aux_checkclass(L, "select{fd_set}", 2); 117 int fd;
116 fd_set *write_fd_set = (fd_set *) aux_checkclass(L, "select{fd_set}", 3); 118 lua_pushnumber(L, i);
117 int timeout = lua_isnil(L, 4) ? -1 : (int)(lua_tonumber(L, 4) * 1000); 119 lua_gettable(L, tab);
118 struct timeval tv; 120 if (lua_isnil(L, -1)) {
119 tv.tv_sec = timeout / 1000; 121 lua_pop(L, 1);
120 tv.tv_usec = (timeout % 1000) * 1000; 122 break;
121 lua_pushnumber(L, select(max_fd, read_fd_set, write_fd_set, NULL, 123 }
122 timeout < 0 ? NULL : &tv)); 124 fd = getfd(L);
123 return 1; 125 if (fd > 0) {
126 FD_SET(fd, set);
127 if (max_fd < fd) max_fd = fd;
128 lua_pushnumber(L, fd);
129 lua_pushvalue(L, -2);
130 lua_settable(L, itab);
131 }
132 lua_pop(L, 1);
133 i = i + 1;
134 }
135 return max_fd;
136}
137
138static int check_dirty(lua_State *L, int tab, int dtab, fd_set *set) {
139 int ndirty = 0, i = 1;
140 if (lua_isnil(L, tab))
141 return 0;
142 while (1) {
143 int fd;
144 lua_pushnumber(L, i);
145 lua_gettable(L, tab);
146 if (lua_isnil(L, -1)) {
147 lua_pop(L, 1);
148 break;
149 }
150 fd = getfd(L);
151 if (fd > 0 && dirty(L)) {
152 lua_pushnumber(L, ++ndirty);
153 lua_pushvalue(L, -2);
154 lua_settable(L, dtab);
155 FD_CLR(fd, set);
156 }
157 lua_pop(L, 1);
158 i = i + 1;
159 }
160 return ndirty;
161}
162
163static void return_fd(lua_State *L, fd_set *set, int max_fd,
164 int itab, int tab, int start) {
165 int fd;
166 for (fd = 0; fd < max_fd; fd++) {
167 if (FD_ISSET(fd, set)) {
168 lua_pushnumber(L, ++start);
169 lua_pushnumber(L, fd);
170 lua_gettable(L, itab);
171 lua_settable(L, tab);
172 }
173 }
174}
175
176static void make_assoc(lua_State *L, int tab) {
177 int i = 1, atab;
178 lua_newtable(L); atab = lua_gettop(L);
179 while (1) {
180 lua_pushnumber(L, i);
181 lua_gettable(L, tab);
182 if (!lua_isnil(L, -1)) {
183 lua_pushnumber(L, i);
184 lua_pushvalue(L, -2);
185 lua_settable(L, atab);
186 lua_pushnumber(L, i);
187 lua_settable(L, atab);
188 } else {
189 lua_pop(L, 1);
190 break;
191 }
192 i = i+1;
193 }
124} 194}
195