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 if(lua_pcall(L
, 1, 2, 0))
35 cb
->base
->errorMessage
= luaL_ref(L
, LUA_REGISTRYINDEX
);
36 event_base_loopbreak(cb
->base
->base
);
40 return; /* event was destroyed during callback */
41 /* If nothing is returned, re-use the old event value */
42 ret
= luaL_optinteger(L
, -2, event
);
43 /* Clone the old timeout value in case a new one wasn't set */
44 memcpy(&new_tv
, &cb
->timeout
, sizeof(new_tv
));
45 if(lua_isnumber(L
, -1)) {
46 double newTimeout
= lua_tonumber(L
, -1);
48 load_timeval(newTimeout
, &new_tv
);
53 freeCallbackArgs(cb
, L
);
55 struct event
*ev
= &cb
->ev
;
57 if( newEvent
!= event
|| (cb
->timeout
.tv_sec
!= new_tv
.tv_sec
|| cb
->timeout
.tv_usec
!= new_tv
.tv_usec
) ) {
58 struct timeval
*ptv
= &cb
->timeout
;
60 if(!cb
->timeout
.tv_sec
&& !cb
->timeout
.tv_usec
)
63 event_set(ev
, fd
, EV_PERSIST
| newEvent
, luaevent_callback
, cb
);
64 /* Assume cannot set a new timeout.. */
70 static int luaevent_cb_gc(lua_State
* L
) {
71 le_callback
* arg
= luaL_checkudata(L
, 1, EVENT_CALLBACK_ARG_MT
);
72 freeCallbackArgs(arg
, L
);
76 le_callback
* event_callback_push(lua_State
* L
, int baseIdx
, int callbackIdx
) {
78 le_base
*base
= event_base_get(L
, baseIdx
);
79 luaL_checktype(L
, callbackIdx
, LUA_TFUNCTION
);
80 cb
= lua_newuserdata(L
, sizeof(*cb
));
81 luaL_getmetatable(L
, EVENT_CALLBACK_ARG_MT
);
82 lua_setmetatable(L
, -2);
84 lua_pushvalue(L
, callbackIdx
);
85 cb
->callbackRef
= luaL_ref(L
, LUA_REGISTRYINDEX
);
87 memset(&cb
->timeout
, 0, sizeof(cb
->timeout
));
91 void event_callback_register(lua_State
* L
) {
92 luaL_newmetatable(L
, EVENT_CALLBACK_ARG_MT
);
93 lua_pushcfunction(L
, luaevent_cb_gc
);
94 lua_setfield(L
, -2, "__gc");
96 lua_pushcfunction(L
, luaevent_cb_gc
);
97 lua_setfield(L
, -2, "close");
98 lua_setfield(L
, -2, "__index");