1 /* LuaEvent - Copyright (C) 2007,2012 Thomas Harning <harningt@gmail.com>
2 * Licensed as LGPL - See doc/COPYING for details */
3 #include "event_callback.h"
8 #define EVENT_CALLBACK_ARG_MT "EVENT_CALLBACK_ARG_MT"
10 void freeCallbackArgs(le_callback
* arg
, lua_State
* L
) {
14 luaL_unref(L
, LUA_REGISTRYINDEX
, arg
->callbackRef
);
17 /* le_callback is allocated at the beginning of the coroutine in which it
18 is used, no need to manually de-allocate */
20 /* Index for coroutine is fd as integer for *nix, as lightuserdata for Win */
21 void luaevent_callback(int fd
, short event
, void* p
) {
25 struct timeval new_tv
= { 0, 0 };
28 return; /* Event has already been collected + destroyed */
29 assert(cb
->base
->loop_L
);
31 lua_rawgeti(L
, LUA_REGISTRYINDEX
, cb
->callbackRef
);
32 lua_pushinteger(L
, event
);
33 /* cb->base may be NULL after the pcall, if the event is destroyed */
34 le_base
* base
= cb
->base
;
35 if(lua_pcall(L
, 1, 2, 0))
37 base
->errorMessage
= luaL_ref(L
, LUA_REGISTRYINDEX
);
38 event_base_loopbreak(base
->base
);
44 return; /* event was destroyed during callback */
46 /* If nothing is returned, re-use the old event value */
47 ret
= luaL_optinteger(L
, -2, event
);
48 /* Clone the old timeout value in case a new one wasn't set */
49 memcpy(&new_tv
, &cb
->timeout
, sizeof(new_tv
));
50 if(lua_isnumber(L
, -1)) {
51 double newTimeout
= lua_tonumber(L
, -1);
53 load_timeval(newTimeout
, &new_tv
);
58 freeCallbackArgs(cb
, L
);
60 struct event
*ev
= &cb
->ev
;
62 if( newEvent
!= event
|| (cb
->timeout
.tv_sec
!= new_tv
.tv_sec
|| cb
->timeout
.tv_usec
!= new_tv
.tv_usec
) ) {
63 struct timeval
*ptv
= &cb
->timeout
;
65 if(!cb
->timeout
.tv_sec
&& !cb
->timeout
.tv_usec
)
68 event_set(ev
, fd
, EV_PERSIST
| newEvent
, luaevent_callback
, cb
);
69 /* Assume cannot set a new timeout.. */
75 static int luaevent_cb_gc(lua_State
* L
) {
76 le_callback
* arg
= luaL_checkudata(L
, 1, EVENT_CALLBACK_ARG_MT
);
77 freeCallbackArgs(arg
, L
);
81 le_callback
* event_callback_push(lua_State
* L
, int baseIdx
, int callbackIdx
) {
83 le_base
*base
= event_base_get(L
, baseIdx
);
84 luaL_checktype(L
, callbackIdx
, LUA_TFUNCTION
);
85 cb
= lua_newuserdata(L
, sizeof(*cb
));
86 luaL_getmetatable(L
, EVENT_CALLBACK_ARG_MT
);
87 lua_setmetatable(L
, -2);
89 lua_pushvalue(L
, callbackIdx
);
90 cb
->callbackRef
= luaL_ref(L
, LUA_REGISTRYINDEX
);
92 memset(&cb
->timeout
, 0, sizeof(cb
->timeout
));
96 void event_callback_register(lua_State
* L
) {
97 luaL_newmetatable(L
, EVENT_CALLBACK_ARG_MT
);
98 lua_pushcfunction(L
, luaevent_cb_gc
);
99 lua_setfield(L
, -2, "__gc");
101 lua_pushcfunction(L
, luaevent_cb_gc
);
102 lua_setfield(L
, -2, "close");
103 lua_setfield(L
, -2, "__index");