luaevent/src/luaevent.c

changeset 8
b134613f6303
parent 7
e13f7c9cb6c7
child 9
1f3b72ba96c9
equal deleted inserted replaced
7:e13f7c9cb6c7 8:b134613f6303
8 8
9 #define EVENT_BASE_MT "EVENT_BASE_MT" 9 #define EVENT_BASE_MT "EVENT_BASE_MT"
10 #define EVENT_CALLBACK_ARG_MT "EVENT_CALLBACK_ARG_MT" 10 #define EVENT_CALLBACK_ARG_MT "EVENT_CALLBACK_ARG_MT"
11 #define EVENT_BASE_LOCATION 1 11 #define EVENT_BASE_LOCATION 1
12 12
13 void setEventBase(lua_State* L, struct event_base* base) { 13 static void setEventBase(lua_State* L, struct event_base* base) {
14 struct event_base** pbase = lua_newuserdata(L, sizeof(base)); 14 struct event_base** pbase = lua_newuserdata(L, sizeof(base));
15 *pbase = base; 15 *pbase = base;
16 luaL_getmetatable(L, EVENT_BASE_MT); 16 luaL_getmetatable(L, EVENT_BASE_MT);
17 lua_setmetatable(L, -2); 17 lua_setmetatable(L, -2);
18 lua_rawseti(L, LUA_ENVIRONINDEX, EVENT_BASE_LOCATION); 18 lua_rawseti(L, LUA_ENVIRONINDEX, EVENT_BASE_LOCATION);
23 base = *(struct event_base**)lua_topointer(L, -1); 23 base = *(struct event_base**)lua_topointer(L, -1);
24 lua_pop(L, 1); 24 lua_pop(L, 1);
25 return base; 25 return base;
26 } 26 }
27 27
28 void freeCallbackArgs(le_callback* arg) { 28 static void freeCallbackArgs(le_callback* arg) {
29 if(arg->L) { 29 if(arg->L) {
30 lua_State* L = arg->L; 30 lua_State* L = arg->L;
31 arg->L = NULL; 31 arg->L = NULL;
32 event_del(&arg->ev); 32 event_del(&arg->ev);
33 luaL_unref(L, LUA_REGISTRYINDEX, arg->callbackRef); 33 luaL_unref(L, LUA_REGISTRYINDEX, arg->callbackRef);
34 } 34 }
35 } 35 }
36
37 static int call_callback_function(lua_State* L, int argCount) {
38 int ret;
39 if(lua_pcall(L, argCount, 1, 0) || !(lua_isnil(L, -1) || lua_isnumber(L, -1))) {
40 printf("ERROR IN INIT: %s\n", lua_tostring(L, -1));
41 lua_pop(L, 1);
42 return 0;
43 }
44 /* Lua_isnil returns 1 if the value is nil... */
45 ret = lua_tointeger(L, -1) | -lua_isnil(L, -1);
46 lua_pop(L, 1);
47 if(ret < 0) { /* Done, no need to setup event */
48 return 0;
49 }
50 if(ret != EV_READ && ret != EV_WRITE) {
51 printf("BAD RET_VAL IN INIT: %i\n", ret);
52 }
53 return 1;
54 }
55
56 static void luaevent_callback(int fd, short event, void* p);
57
58 static void setup_event(le_callback* arg, int fd, short event, int resetEvent) {
59 /* Setup event... */
60 if(resetEvent) event_del(&arg->ev);
61 event_set(&arg->ev, fd, event| EV_PERSIST, luaevent_callback, arg);
62 if(!resetEvent) event_base_set(getEventBase(arg->L), &arg->ev);
63 event_add(&arg->ev, NULL);
64 }
65
36 /* le_callback is allocated at the beginning of the coroutine in which it 66 /* le_callback is allocated at the beginning of the coroutine in which it
37 is used, no need to manually de-allocate */ 67 is used, no need to manually de-allocate */
38 68
39 /* Index for coroutine is fd as integer for *nix, as lightuserdata for Win */ 69 /* Index for coroutine is fd as integer for *nix, as lightuserdata for Win */
40 static void luaevent_callback(int fd, short event, void* p) { 70 static void luaevent_callback(int fd, short event, void* p) {
41 le_callback* arg = p; 71 le_callback* arg = p;
42 lua_State* L = arg->L; 72 lua_State* L = arg->L;
43 int ret; 73 int ret;
44 lua_rawgeti(L, LUA_REGISTRYINDEX, arg->callbackRef); 74 lua_rawgeti(L, LUA_REGISTRYINDEX, arg->callbackRef);
45 lua_pushinteger(L, event); 75 lua_pushinteger(L, event);
46 if(lua_pcall(L, 1, 1, 0) || !(lua_isnil(L, -1) || lua_isnumber(L, -1))) { 76
47 printf("ERROR IN CB: %s\n", lua_tostring(L, -1)); 77 if(0 == call_callback_function(L, 1)) {
48 lua_pop(L, 1);
49 freeCallbackArgs(arg); 78 freeCallbackArgs(arg);
50 return; 79 return;
51 } 80 }
52 ret = lua_tointeger(L, -1) | -1lua_isnil(L, -1); 81
53 lua_pop(L, 1);
54 if(ret < 0) {
55 freeCallbackArgs(arg);
56 return;
57 }
58 if(ret != EV_READ && ret != EV_WRITE) {
59 printf("BAD RET_VAL: %i\n", ret);
60 }
61 printf("RET VAL: %i\n", ret); 82 printf("RET VAL: %i\n", ret);
62 struct event *ev = &arg->ev; 83 if(event != ret)
63 int newEvent = ret; 84 setup_event(arg, fd, ret, 1);
64 if(newEvent != event) { // Need to hook up new event...
65 event_del(ev);
66 event_set(ev, fd, EV_PERSIST | newEvent, luaevent_callback, arg);
67 event_add(ev, NULL);
68 }
69 } 85 }
70 86
71 static int luaevent_base_gc(lua_State* L) { 87 static int luaevent_base_gc(lua_State* L) {
72 struct event_base** pbase = luaL_checkudata(L, 1, EVENT_BASE_MT); 88 struct event_base** pbase = luaL_checkudata(L, 1, EVENT_BASE_MT);
73 if(*pbase) { 89 if(*pbase) {
87 le_callback* arg = luaL_checkudata(L, 1, EVENT_CALLBACK_ARG_MT); 103 le_callback* arg = luaL_checkudata(L, 1, EVENT_CALLBACK_ARG_MT);
88 lua_pushinteger(L, arg->ev.ev_fd); 104 lua_pushinteger(L, arg->ev.ev_fd);
89 return 1; 105 return 1;
90 } 106 }
91 107
92 int getSocketFd(lua_State* L, int idx) { 108 static int getSocketFd(lua_State* L, int idx) {
93 int fd; 109 int fd;
94 luaL_checktype(L, idx, LUA_TUSERDATA); 110 luaL_checktype(L, idx, LUA_TUSERDATA);
95 lua_getfield(L, idx, "getfd"); 111 lua_getfield(L, idx, "getfd");
96 if(lua_isnil(L, -1)) 112 if(lua_isnil(L, -1))
97 return luaL_error(L, "Socket type missing 'getfd' method"); 113 return luaL_error(L, "Socket type missing 'getfd' method");
100 fd = lua_tointeger(L, -1); 116 fd = lua_tointeger(L, -1);
101 lua_pop(L, 1); 117 lua_pop(L, 1);
102 return fd; 118 return fd;
103 } 119 }
104 120
121 static void push_new_callback(lua_State* L, int callbackRef, int fd, short event) {
122 le_callback* arg = lua_newuserdata(L, sizeof(*arg));
123 luaL_getmetatable(L, EVENT_CALLBACK_ARG_MT);
124 lua_setmetatable(L, -2);
125
126 arg->L = L;
127 arg->callbackRef = callbackRef;
128
129 setup_event(arg, fd, event, 0);
130 }
105 /* Expected to be called at the beginning of the coro that uses it.. 131 /* Expected to be called at the beginning of the coro that uses it..
106 Value must be kept until coro is complete.... 132 Value must be kept until coro is complete....
107 */ 133 */
108 /* sock, callback */ 134 /* sock, callback */
109 static int luaevent_addevent(lua_State* L) { 135 static int luaevent_addevent(lua_State* L) {
110 int fd, callbackRef; 136 int fd, callbackRef;
111 int top, ret; 137 int top, ret;
112 le_callback* arg;
113 fd = getSocketFd(L, 1); 138 fd = getSocketFd(L, 1);
114 luaL_checktype(L, 2, LUA_TFUNCTION); 139 luaL_checktype(L, 2, LUA_TFUNCTION);
115 top = lua_gettop(L); 140 top = lua_gettop(L);
116 /* Preserve the callback function */ 141 /* Preserve the callback function */
117 lua_pushvalue(L, 2); 142 lua_pushvalue(L, 2);
118 callbackRef = luaL_ref(L, LUA_REGISTRYINDEX); 143 callbackRef = luaL_ref(L, LUA_REGISTRYINDEX);
119
120 /* Call the callback with all arguments after it to get the loop primed.. */ 144 /* Call the callback with all arguments after it to get the loop primed.. */
121 if(lua_pcall(L, top - 2, 1, 0) || !(lua_isnil(L, -1) || lua_isnumber(L, -1))) { 145 if(0 == call_callback_function(L, top - 2)) {
122 printf("ERROR IN INIT: %s\n", lua_tostring(L, -1));
123 lua_pop(L, 1);
124 return 0;
125 }
126 /* Lua_isnil returns 1 if the value is nil... */
127 ret = lua_tointeger(L, -1) | -lua_isnil(L, -1);
128 lua_pop(L, 1);
129 if(ret < 0) { /* Done, no need to setup event */
130 luaL_unref(L, LUA_REGISTRYINDEX, callbackRef); 146 luaL_unref(L, LUA_REGISTRYINDEX, callbackRef);
131 return 0; 147 return 0;
132 } 148 }
133 if(ret != EV_READ && ret != EV_WRITE) { 149
134 printf("BAD RET_VAL IN INIT: %i\n", ret); 150 push_new_callback(L, callbackRef, fd, ret);
135 }
136 arg = lua_newuserdata(L, sizeof(*arg));
137 luaL_getmetatable(L, EVENT_CALLBACK_ARG_MT);
138 lua_setmetatable(L, -2);
139
140 arg->L = L;
141 arg->callbackRef = callbackRef;
142
143 /* Setup event... */
144 event_set(&arg->ev, fd, ret | EV_PERSIST, luaevent_callback, arg);
145 event_base_set(getEventBase(L), &arg->ev);
146 event_add(&arg->ev, NULL);
147 return 1; 151 return 1;
148 } 152 }
149 153
150 static int luaevent_loop(lua_State* L) { 154 static int luaevent_loop(lua_State* L) {
151 int ret = event_base_loop(getEventBase(L), 0); 155 int ret = event_base_loop(getEventBase(L), 0);

mercurial