diff options
author | Diego Nehab <diego@tecgraf.puc-rio.br> | 2004-06-15 06:24:00 +0000 |
---|---|---|
committer | Diego Nehab <diego@tecgraf.puc-rio.br> | 2004-06-15 06:24:00 +0000 |
commit | 58096449c6044b7aade5cd41cfd71c6bec1d273d (patch) | |
tree | 1814ffebe89c4c2556d84f97f66db37a7e8b4554 /src/select.c | |
parent | 9ed7f955e5fc69af9bf1794fa2c8cd227981ba24 (diff) | |
download | luasocket-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.c | 221 |
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 | \*=========================================================================*/ |
20 | static int meth_set(lua_State *L); | 18 | static int getfd(lua_State *L); |
21 | static int meth_isset(lua_State *L); | 19 | static int dirty(lua_State *L); |
22 | static int c_select(lua_State *L); | 20 | static int collect_fd(lua_State *L, int tab, int max_fd, int itab, fd_set *set); |
21 | static int check_dirty(lua_State *L, int tab, int dtab, fd_set *set); | ||
22 | static void return_fd(lua_State *L, fd_set *set, int max_fd, | ||
23 | int itab, int tab, int start); | ||
24 | static void make_assoc(lua_State *L, int tab); | ||
23 | static int global_select(lua_State *L); | 25 | static int global_select(lua_State *L); |
24 | 26 | ||
25 | /* fd_set object methods */ | ||
26 | static 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 */ |
33 | static luaL_reg func[] = { | 28 | static 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 | \*-------------------------------------------------------------------------*/ |
44 | int select_open(lua_State *L) | 39 | int 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 | \*-------------------------------------------------------------------------*/ |
64 | static int global_select(lua_State *L) | 50 | static 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 | \*=========================================================================*/ |
92 | static int meth_set(lua_State *L) | 84 | static 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 | ||
100 | static int meth_isset(lua_State *L) | 98 | static 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 | /*=========================================================================*\ | 111 | static 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; |
112 | static 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 | |||
138 | static 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 | |||
163 | static 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 | |||
176 | static 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 | |||