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