Completely refactored event_callback creation out into event_callback.
[luaevent.git] / src / event_callback.c
blobf2cd0bc3610379a8dd8149a198eba576bee6bf97
1 /* LuaEvent - Copyright (C) 2007 Thomas Harning <harningt@gmail.com>
2 * Licensed as LGPL - See doc/COPYING for details */
3 #include "event_callback.h"
4 #include <assert.h>
5 #include <lauxlib.h>
7 #define EVENT_CALLBACK_ARG_MT "EVENT_CALLBACK_ARG_MT"
9 void freeCallbackArgs(le_callback* arg, lua_State* L) {
10 if(arg->base) {
11 arg->base = NULL;
12 event_del(&arg->ev);
13 luaL_unref(L, LUA_REGISTRYINDEX, arg->callbackRef);
16 /* le_callback is allocated at the beginning of the coroutine in which it
17 is used, no need to manually de-allocate */
19 /* Index for coroutine is fd as integer for *nix, as lightuserdata for Win */
20 void luaevent_callback(int fd, short event, void* p) {
21 le_callback* arg = p;
22 lua_State* L;
23 int ret;
24 assert(arg && arg->base && arg->base->loop_L);
25 L = arg->base->loop_L;
26 lua_rawgeti(L, LUA_REGISTRYINDEX, arg->callbackRef);
27 lua_pushinteger(L, event);
28 lua_call(L, 1, 1);
29 ret = lua_tointeger(L, -1);
30 lua_pop(L, 1);
31 if(ret == -1) {
32 freeCallbackArgs(arg, L);
33 } else {
34 struct event *ev = &arg->ev;
35 int newEvent = ret;
36 if(newEvent != event) { // Need to hook up new event...
37 event_del(ev);
38 event_set(ev, fd, EV_PERSIST | newEvent, luaevent_callback, arg);
39 event_add(ev, NULL);
44 static int luaevent_cb_gc(lua_State* L) {
45 le_callback* arg = luaL_checkudata(L, 1, EVENT_CALLBACK_ARG_MT);
46 freeCallbackArgs(arg, L);
47 return 0;
50 le_callback* event_callback_push(lua_State* L, int baseIdx, int callbackIdx) {
51 le_callback* cb;
52 le_base *base = event_base_get(L, baseIdx);
53 luaL_checktype(L, callbackIdx, LUA_TFUNCTION);
54 cb = lua_newuserdata(L, sizeof(*cb));
55 luaL_getmetatable(L, EVENT_CALLBACK_ARG_MT);
56 lua_setmetatable(L, -2);
58 lua_pushvalue(L, callbackIdx);
59 cb->callbackRef = luaL_ref(L, LUA_REGISTRYINDEX);
60 cb->base = base;
61 return cb;
64 int event_callback_register(lua_State* L) {
65 luaL_newmetatable(L, EVENT_CALLBACK_ARG_MT);
66 lua_pushcfunction(L, luaevent_cb_gc);
67 lua_setfield(L, -2, "__gc");
68 lua_newtable(L);
69 lua_pushcfunction(L, luaevent_cb_gc);
70 lua_setfield(L, -2, "close");
71 lua_setfield(L, -2, "__index");
72 lua_pop(L, 1);
73 return 0;