|
1 #include "event_callback.h" |
|
2 #include <assert.h> |
|
3 #include <lauxlib.h> |
|
4 |
|
5 void freeCallbackArgs(le_callback* arg, lua_State* L) { |
|
6 if(arg->base) { |
|
7 arg->base = NULL; |
|
8 event_del(&arg->ev); |
|
9 luaL_unref(L, LUA_REGISTRYINDEX, arg->callbackRef); |
|
10 } |
|
11 } |
|
12 /* le_callback is allocated at the beginning of the coroutine in which it |
|
13 is used, no need to manually de-allocate */ |
|
14 |
|
15 /* Index for coroutine is fd as integer for *nix, as lightuserdata for Win */ |
|
16 void luaevent_callback(int fd, short event, void* p) { |
|
17 le_callback* arg = p; |
|
18 lua_State* L; |
|
19 int ret; |
|
20 assert(arg && arg->base && arg->base->loop_L); |
|
21 L = arg->base->loop_L; |
|
22 lua_rawgeti(L, LUA_REGISTRYINDEX, arg->callbackRef); |
|
23 lua_pushinteger(L, event); |
|
24 lua_call(L, 1, 1); |
|
25 ret = lua_tointeger(L, -1); |
|
26 lua_pop(L, 1); |
|
27 if(ret == -1) { |
|
28 freeCallbackArgs(arg, L); |
|
29 } else { |
|
30 struct event *ev = &arg->ev; |
|
31 int newEvent = ret; |
|
32 if(newEvent != event) { // Need to hook up new event... |
|
33 event_del(ev); |
|
34 event_set(ev, fd, EV_PERSIST | newEvent, luaevent_callback, arg); |
|
35 event_add(ev, NULL); |
|
36 } |
|
37 } |
|
38 } |
|
39 |
|
40 static int luaevent_cb_gc(lua_State* L) { |
|
41 le_callback* arg = luaL_checkudata(L, 1, EVENT_CALLBACK_ARG_MT); |
|
42 freeCallbackArgs(arg, L); |
|
43 return 0; |
|
44 } |
|
45 |
|
46 int event_callback_register(lua_State* L) { |
|
47 luaL_newmetatable(L, EVENT_CALLBACK_ARG_MT); |
|
48 lua_pushcfunction(L, luaevent_cb_gc); |
|
49 lua_setfield(L, -2, "__gc"); |
|
50 lua_newtable(L); |
|
51 lua_pushcfunction(L, luaevent_cb_gc); |
|
52 lua_setfield(L, -2, "close"); |
|
53 lua_setfield(L, -2, "__index"); |
|
54 lua_pop(L, 1); |
|
55 return 0; |
|
56 } |