Mercurial > luasocket
comparison src/select.c @ 0:4b915342e2a8
LuaSocket 2.0.2 + CMake build description.
author | Eric Wing <ewing . public |-at-| gmail . com> |
---|---|
date | Tue, 26 Aug 2008 18:40:01 -0700 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:4b915342e2a8 |
---|---|
1 /*=========================================================================*\ | |
2 * Select implementation | |
3 * LuaSocket toolkit | |
4 * | |
5 * RCS ID: $Id: select.c,v 1.22 2005/11/20 07:20:23 diego Exp $ | |
6 \*=========================================================================*/ | |
7 #include <string.h> | |
8 | |
9 #include "lua.h" | |
10 #include "lauxlib.h" | |
11 | |
12 #include "socket.h" | |
13 #include "timeout.h" | |
14 #include "select.h" | |
15 | |
16 /*=========================================================================*\ | |
17 * Internal function prototypes. | |
18 \*=========================================================================*/ | |
19 static t_socket getfd(lua_State *L); | |
20 static int dirty(lua_State *L); | |
21 static t_socket collect_fd(lua_State *L, int tab, t_socket max_fd, | |
22 int itab, fd_set *set); | |
23 static int check_dirty(lua_State *L, int tab, int dtab, fd_set *set); | |
24 static void return_fd(lua_State *L, fd_set *set, t_socket max_fd, | |
25 int itab, int tab, int start); | |
26 static void make_assoc(lua_State *L, int tab); | |
27 static int global_select(lua_State *L); | |
28 | |
29 /* functions in library namespace */ | |
30 static luaL_reg func[] = { | |
31 {"select", global_select}, | |
32 {NULL, NULL} | |
33 }; | |
34 | |
35 /*=========================================================================*\ | |
36 * Exported functions | |
37 \*=========================================================================*/ | |
38 /*-------------------------------------------------------------------------*\ | |
39 * Initializes module | |
40 \*-------------------------------------------------------------------------*/ | |
41 int select_open(lua_State *L) { | |
42 luaL_openlib(L, NULL, func, 0); | |
43 return 0; | |
44 } | |
45 | |
46 /*=========================================================================*\ | |
47 * Global Lua functions | |
48 \*=========================================================================*/ | |
49 /*-------------------------------------------------------------------------*\ | |
50 * Waits for a set of sockets until a condition is met or timeout. | |
51 \*-------------------------------------------------------------------------*/ | |
52 static int global_select(lua_State *L) { | |
53 int rtab, wtab, itab, ret, ndirty; | |
54 t_socket max_fd; | |
55 fd_set rset, wset; | |
56 t_timeout tm; | |
57 double t = luaL_optnumber(L, 3, -1); | |
58 FD_ZERO(&rset); FD_ZERO(&wset); | |
59 lua_settop(L, 3); | |
60 lua_newtable(L); itab = lua_gettop(L); | |
61 lua_newtable(L); rtab = lua_gettop(L); | |
62 lua_newtable(L); wtab = lua_gettop(L); | |
63 max_fd = collect_fd(L, 1, SOCKET_INVALID, itab, &rset); | |
64 ndirty = check_dirty(L, 1, rtab, &rset); | |
65 t = ndirty > 0? 0.0: t; | |
66 timeout_init(&tm, t, -1); | |
67 timeout_markstart(&tm); | |
68 max_fd = collect_fd(L, 2, max_fd, itab, &wset); | |
69 ret = socket_select(max_fd+1, &rset, &wset, NULL, &tm); | |
70 if (ret > 0 || ndirty > 0) { | |
71 return_fd(L, &rset, max_fd+1, itab, rtab, ndirty); | |
72 return_fd(L, &wset, max_fd+1, itab, wtab, 0); | |
73 make_assoc(L, rtab); | |
74 make_assoc(L, wtab); | |
75 return 2; | |
76 } else if (ret == 0) { | |
77 lua_pushstring(L, "timeout"); | |
78 return 3; | |
79 } else { | |
80 lua_pushstring(L, "error"); | |
81 return 3; | |
82 } | |
83 } | |
84 | |
85 /*=========================================================================*\ | |
86 * Internal functions | |
87 \*=========================================================================*/ | |
88 static t_socket getfd(lua_State *L) { | |
89 t_socket fd = SOCKET_INVALID; | |
90 lua_pushstring(L, "getfd"); | |
91 lua_gettable(L, -2); | |
92 if (!lua_isnil(L, -1)) { | |
93 lua_pushvalue(L, -2); | |
94 lua_call(L, 1, 1); | |
95 if (lua_isnumber(L, -1)) | |
96 fd = (t_socket) lua_tonumber(L, -1); | |
97 } | |
98 lua_pop(L, 1); | |
99 return fd; | |
100 } | |
101 | |
102 static int dirty(lua_State *L) { | |
103 int is = 0; | |
104 lua_pushstring(L, "dirty"); | |
105 lua_gettable(L, -2); | |
106 if (!lua_isnil(L, -1)) { | |
107 lua_pushvalue(L, -2); | |
108 lua_call(L, 1, 1); | |
109 is = lua_toboolean(L, -1); | |
110 } | |
111 lua_pop(L, 1); | |
112 return is; | |
113 } | |
114 | |
115 static t_socket collect_fd(lua_State *L, int tab, t_socket max_fd, | |
116 int itab, fd_set *set) { | |
117 int i = 1; | |
118 if (lua_isnil(L, tab)) | |
119 return max_fd; | |
120 while (1) { | |
121 t_socket fd; | |
122 lua_pushnumber(L, i); | |
123 lua_gettable(L, tab); | |
124 if (lua_isnil(L, -1)) { | |
125 lua_pop(L, 1); | |
126 break; | |
127 } | |
128 fd = getfd(L); | |
129 if (fd != SOCKET_INVALID) { | |
130 FD_SET(fd, set); | |
131 if (max_fd == SOCKET_INVALID || max_fd < fd) | |
132 max_fd = fd; | |
133 lua_pushnumber(L, fd); | |
134 lua_pushvalue(L, -2); | |
135 lua_settable(L, itab); | |
136 } | |
137 lua_pop(L, 1); | |
138 i = i + 1; | |
139 } | |
140 return max_fd; | |
141 } | |
142 | |
143 static int check_dirty(lua_State *L, int tab, int dtab, fd_set *set) { | |
144 int ndirty = 0, i = 1; | |
145 if (lua_isnil(L, tab)) | |
146 return 0; | |
147 while (1) { | |
148 t_socket fd; | |
149 lua_pushnumber(L, i); | |
150 lua_gettable(L, tab); | |
151 if (lua_isnil(L, -1)) { | |
152 lua_pop(L, 1); | |
153 break; | |
154 } | |
155 fd = getfd(L); | |
156 if (fd != SOCKET_INVALID && dirty(L)) { | |
157 lua_pushnumber(L, ++ndirty); | |
158 lua_pushvalue(L, -2); | |
159 lua_settable(L, dtab); | |
160 FD_CLR(fd, set); | |
161 } | |
162 lua_pop(L, 1); | |
163 i = i + 1; | |
164 } | |
165 return ndirty; | |
166 } | |
167 | |
168 static void return_fd(lua_State *L, fd_set *set, t_socket max_fd, | |
169 int itab, int tab, int start) { | |
170 t_socket fd; | |
171 for (fd = 0; fd < max_fd; fd++) { | |
172 if (FD_ISSET(fd, set)) { | |
173 lua_pushnumber(L, ++start); | |
174 lua_pushnumber(L, fd); | |
175 lua_gettable(L, itab); | |
176 lua_settable(L, tab); | |
177 } | |
178 } | |
179 } | |
180 | |
181 static void make_assoc(lua_State *L, int tab) { | |
182 int i = 1, atab; | |
183 lua_newtable(L); atab = lua_gettop(L); | |
184 while (1) { | |
185 lua_pushnumber(L, i); | |
186 lua_gettable(L, tab); | |
187 if (!lua_isnil(L, -1)) { | |
188 lua_pushnumber(L, i); | |
189 lua_pushvalue(L, -2); | |
190 lua_settable(L, atab); | |
191 lua_pushnumber(L, i); | |
192 lua_settable(L, atab); | |
193 } else { | |
194 lua_pop(L, 1); | |
195 break; | |
196 } | |
197 i = i+1; | |
198 } | |
199 } | |
200 |