aboutsummaryrefslogtreecommitdiff
path: root/src/select.c
diff options
context:
space:
mode:
authorDiego Nehab <diego@tecgraf.puc-rio.br>2003-06-09 18:23:40 +0000
committerDiego Nehab <diego@tecgraf.puc-rio.br>2003-06-09 18:23:40 +0000
commit58bdb658aaa1c30a8f3bed46eef880d308fae582 (patch)
tree5bf880c715daff79c1a2062f2f3ae8336858c83f /src/select.c
parentb2724ad2d1cc3768a04270ed3f8014ec65ad133b (diff)
downloadluasocket-58bdb658aaa1c30a8f3bed46eef880d308fae582.tar.gz
luasocket-58bdb658aaa1c30a8f3bed46eef880d308fae582.tar.bz2
luasocket-58bdb658aaa1c30a8f3bed46eef880d308fae582.zip
Select re-implemented in a nicer way.
Few changes in internal class and group registration. Lua modules are compiled and built into library. Dynamic library tested in Linux and Mac OS X.
Diffstat (limited to 'src/select.c')
-rw-r--r--src/select.c191
1 files changed, 83 insertions, 108 deletions
diff --git a/src/select.c b/src/select.c
index 9f56b47..3cabbd1 100644
--- a/src/select.c
+++ b/src/select.c
@@ -1,154 +1,129 @@
1/*=========================================================================*\ 1/*=========================================================================*\
2* Select implementation 2* Select implementation
3* Global Lua fuctions:
4* select: waits until socket ready
5* RCS ID: $Id$ 3* RCS ID: $Id$
6\*=========================================================================*/ 4\*=========================================================================*/
7#include <string.h> 5#include <string.h>
6
8#include <lua.h> 7#include <lua.h>
9#include <lauxlib.h> 8#include <lauxlib.h>
10 9
11#include "luasocket.h" 10#include "luasocket.h"
12#include "lspriv.h" 11#include "socket.h"
13#include "lsselect.h" 12#include "auxiliar.h"
14#include "lsfd.h" 13#include "select.h"
15 14
16/* auxiliar functions */ 15static int meth_set(lua_State *L);
17static int local_select(lua_State *L); 16static int meth_isset(lua_State *L);
18static int local_getfd(lua_State *L); 17static int c_select(lua_State *L);
19static int local_pending(lua_State *L); 18static int global_select(lua_State *L);
20static int local_FD_SET(lua_State *L); 19static void check_obj_tab(lua_State *L, int tabidx);
21static int local_FD_ISSET(lua_State *L);
22 20
23static int select_lua_select(lua_State *L); 21/* fd_set object methods */
22static luaL_reg set[] = {
23 {"set", meth_set},
24 {"isset", meth_isset},
25 {NULL, NULL}
26};
24 27
25/*-------------------------------------------------------------------------*\ 28/* functions in library namespace */
26* Marks type as selectable 29static luaL_reg func[] = {
27* Input 30 {"select", global_select},
28* name: type name 31 {NULL, NULL}
29\*-------------------------------------------------------------------------*/ 32};
30void select_addclass(lua_State *L, cchar *lsclass)
31{
32 lua_pushstring(L, "luasocket(select)");
33 lua_gettable(L, LUA_REGISTRYINDEX);
34 lua_pushstring(L, lsclass);
35 lua_pushnumber(L, 1);
36 lua_settable(L, -3);
37 lua_pop(L, 1);
38}
39 33
40void select_open(lua_State *L) 34void select_open(lua_State *L)
41{ 35{
42 /* push select auxiliar lua function and register 36 /* get select auxiliar lua function from lua code and register
43 * select_lua_select with it as an upvalue */ 37 * pass it as an upvalue to global_select */
44#ifdef LUASOCKET_DOFILE 38#ifdef LUASOCKET_COMPILED
45 lua_dofile(L, "lsselect.lua"); 39#include "select.lch"
46#else 40#else
47#include "lsselect.loh" 41 lua_dofile(L, "select.lua");
48#endif 42#endif
49 lua_getglobal(L, LUASOCKET_LIBNAME); 43 luaL_openlib(L, LUASOCKET_LIBNAME, func, 1);
50 lua_pushstring(L, "_select");
51 lua_gettable(L, -2);
52 lua_pushcclosure(L, select_lua_select, 1);
53 priv_newglobal(L, "select");
54 lua_pop(L, 1); 44 lua_pop(L, 1);
55 /* create luasocket(select) table */ 45 aux_newclass(L, "select{fd_set}", set);
56 lua_pushstring(L, "luasocket(select)");
57 lua_newtable(L);
58 lua_settable(L, LUA_REGISTRYINDEX);
59} 46}
60 47
61/*-------------------------------------------------------------------------*\ 48/*-------------------------------------------------------------------------*\
62* Waits for a set of sockets until a condition is met or timeout. 49* Waits for a set of sockets until a condition is met or timeout.
63* Lua Input: {input}, {output} [, timeout]
64* {input}: table of sockets to be tested for input
65* {output}: table of sockets to be tested for output
66* timeout: maximum amount of time to wait for condition, in seconds
67* Lua Returns: {input}, {output}, err
68* {input}: table with sockets ready for input
69* {output}: table with sockets ready for output
70* err: "timeout" or nil
71\*-------------------------------------------------------------------------*/ 50\*-------------------------------------------------------------------------*/
72static int select_lua_select(lua_State *L) 51static int global_select(lua_State *L)
73{ 52{
74 fd_set read, write; 53 fd_set *read_fd_set, *write_fd_set;
75 FD_ZERO(&read);
76 FD_ZERO(&write);
77 /* push select lua auxiliar function */
78 lua_pushvalue(L, lua_upvalueindex(1)); lua_insert(L, 1);
79 /* make sure we have enough arguments (nil is the default) */ 54 /* make sure we have enough arguments (nil is the default) */
80 lua_settop(L, 4); 55 lua_settop(L, 3);
81 /* pass FD_SET and manipulation functions */ 56 /* check object tables */
82 lua_boxpointer(L, &read); 57 check_obj_tab(L, 1);
83 lua_boxpointer(L, &write); 58 check_obj_tab(L, 2);
84 lua_pushcfunction(L, local_FD_SET); 59 /* check timeout */
85 lua_pushcfunction(L, local_FD_ISSET); 60 if (!lua_isnil(L, 3) && !lua_isnumber(L, 3))
86 /* pass getfd function with selectable table as upvalue */ 61 luaL_argerror(L, 3, "number or nil expected");
87 lua_pushstring(L, "luasocket(select)"); lua_gettable(L, LUA_REGISTRYINDEX); 62 /* select auxiliar lua function to be called comes first */
88 lua_pushcclosure(L, local_getfd, 1); 63 lua_pushvalue(L, lua_upvalueindex(1));
89 /* pass pending function */ 64 lua_insert(L, 1);
90 lua_pushstring(L, "luasocket(select)"); lua_gettable(L, LUA_REGISTRYINDEX); 65 /* pass fd_set objects */
91 lua_pushcclosure(L, local_pending, 1); 66 read_fd_set = lua_newuserdata(L, sizeof(fd_set));
67 FD_ZERO(read_fd_set);
68 aux_setclass(L, "select{fd_set}", -1);
69 write_fd_set = lua_newuserdata(L, sizeof(fd_set));
70 FD_ZERO(write_fd_set);
71 aux_setclass(L, "select{fd_set}", -1);
92 /* pass select auxiliar C function */ 72 /* pass select auxiliar C function */
93 lua_pushcfunction(L, local_select); 73 lua_pushcfunction(L, c_select);
94 /* call select auxiliar lua function */ 74 /* call select auxiliar lua function */
95 lua_call(L, 10, 3); 75 lua_call(L, 6, 3);
96 return 3; 76 return 3;
97} 77}
98 78
99static int local_getfd(lua_State *L) 79static int c_select(lua_State *L)
100{
101 priv_pushclass(L, 1);
102 lua_gettable(L, lua_upvalueindex(1));
103 if (!lua_isnil(L, -1)) {
104 p_fd sock = (p_fd) lua_touserdata(L, 1);
105 lua_pushnumber(L, sock->fd);
106 }
107 return 1;
108}
109
110static int local_pending(lua_State *L)
111{
112 priv_pushclass(L, 1);
113 lua_gettable(L, lua_upvalueindex(1));
114 if (!lua_isnil(L, -1)) {
115 p_fd sock = (p_fd) lua_touserdata(L, 1);
116 if (sock->fd_pending(L, sock)) lua_pushnumber(L, 1);
117 else lua_pushnil(L);
118 }
119 return 1;
120}
121
122static int local_select(lua_State *L)
123{ 80{
124 int max_fd = (int) lua_tonumber(L, 1); 81 int max_fd = (int) lua_tonumber(L, 1);
125 fd_set *read_set = (fd_set *) lua_touserdata(L, 2); 82 fd_set *read_fd_set = (fd_set *) aux_checkclass(L, "select{fd_set}", 2);
126 fd_set *write_set = (fd_set *) lua_touserdata(L, 3); 83 fd_set *write_fd_set = (fd_set *) aux_checkclass(L, "select{fd_set}", 3);
127 int deadline = lua_isnil(L, 4) ? -1 : (int)(lua_tonumber(L, 4) * 1000); 84 int timeout = lua_isnil(L, 4) ? -1 : (int)(lua_tonumber(L, 4) * 1000);
128 struct timeval tv; 85 struct timeval tv;
129 if (deadline >= 0) { 86 tv.tv_sec = timeout / 1000;
130 tv.tv_sec = deadline / 1000; 87 tv.tv_usec = (timeout % 1000) * 1000;
131 tv.tv_usec = (deadline % 1000) * 1000; 88 lua_pushnumber(L, select(max_fd, read_fd_set, write_fd_set, NULL,
132 lua_pushnumber(L, select(max_fd, read_set, write_set, NULL, &tv)); 89 timeout < 0 ? NULL : &tv));
133 } else {
134 lua_pushnumber(L, select(max_fd, read_set, write_set, NULL, NULL));
135 }
136 return 1; 90 return 1;
137} 91}
138 92
139static int local_FD_SET(lua_State *L) 93static int meth_set(lua_State *L)
140{ 94{
141 COMPAT_FD fd = (COMPAT_FD) lua_tonumber(L, 1); 95 fd_set *set = (fd_set *) aux_checkclass(L, "select{fd_set}", 1);
142 fd_set *set = (fd_set *) lua_topointer(L, 2); 96 t_sock fd = (t_sock) lua_tonumber(L, 2);
143 if (fd >= 0) FD_SET(fd, set); 97 if (fd >= 0) FD_SET(fd, set);
144 return 0; 98 return 0;
145} 99}
146 100
147static int local_FD_ISSET(lua_State *L) 101static int meth_isset(lua_State *L)
148{ 102{
149 COMPAT_FD fd = (COMPAT_FD) lua_tonumber(L, 1); 103 fd_set *set = (fd_set *) aux_checkclass(L, "select{fd_set}", 1);
150 fd_set *set = (fd_set *) lua_topointer(L, 2); 104 t_sock fd = (t_sock) lua_tonumber(L, 2);
151 if (fd >= 0 && FD_ISSET(fd, set)) lua_pushnumber(L, 1); 105 if (fd >= 0 && FD_ISSET(fd, set)) lua_pushnumber(L, 1);
152 else lua_pushnil(L); 106 else lua_pushnil(L);
153 return 1; 107 return 1;
154} 108}
109
110static void check_obj_tab(lua_State *L, int tabidx)
111{
112 if (tabidx < 0) tabidx = lua_gettop(L) + tabidx + 1;
113 if (lua_istable(L, tabidx)) {
114 lua_pushnil(L);
115 while (lua_next(L, tabidx) != 0) {
116 if (aux_getgroupudata(L, "select{able}", -1) == NULL) {
117 char msg[45];
118 if (lua_isnumber(L, -2))
119 sprintf(msg, "table entry #%g is invalid",
120 lua_tonumber(L, -2));
121 else
122 sprintf(msg, "invalid entry found in table");
123 luaL_argerror(L, tabidx, msg);
124 }
125 lua_pop(L, 1);
126 }
127 } else if (!lua_isnil(L, tabidx))
128 luaL_argerror(L, tabidx, "table or nil expected");
129}