aboutsummaryrefslogtreecommitdiffstats
path: root/luaevent/src/luaevent.c
diff options
context:
space:
mode:
Diffstat (limited to 'luaevent/src/luaevent.c')
-rw-r--r--luaevent/src/luaevent.c179
1 files changed, 77 insertions, 102 deletions
diff --git a/luaevent/src/luaevent.c b/luaevent/src/luaevent.c
index e5e33cf..38f19ce 100644
--- a/luaevent/src/luaevent.c
+++ b/luaevent/src/luaevent.c
@@ -1,111 +1,87 @@
/* LuaEvent - Copyright (C) 2007 Thomas Harning <harningt@gmail.com>
* Licensed as LGPL - See doc/COPYING for details */
-
-#include "luaevent.h"
+ #include "luaevent.h"
#include <lua.h>
#include <lauxlib.h>
+#include <assert.h>
#define EVENT_BASE_MT "EVENT_BASE_MT"
#define EVENT_CALLBACK_ARG_MT "EVENT_CALLBACK_ARG_MT"
-#define EVENT_BASE_LOCATION 1
+#define MAIN_THREAD_LOCATION 1
-static void setEventBase(lua_State* L, struct event_base* base) {
- struct event_base** pbase = lua_newuserdata(L, sizeof(base));
- *pbase = base;
- luaL_getmetatable(L, EVENT_BASE_MT);
- lua_setmetatable(L, -2);
- lua_rawseti(L, LUA_ENVIRONINDEX, EVENT_BASE_LOCATION);
+void setMainThread(lua_State* L) {
+ lua_pushthread(L);
+ lua_rawseti(L, LUA_ENVIRONINDEX, MAIN_THREAD_LOCATION);
}
-struct event_base* getEventBase(lua_State* L) {
- struct event_base* base;
- lua_rawgeti(L, LUA_ENVIRONINDEX, EVENT_BASE_LOCATION);
- base = *(struct event_base**)lua_topointer(L, -1);
+lua_State* getMainThread(lua_State* L) {
+ lua_State* g_L;
+ lua_rawgeti(L, LUA_ENVIRONINDEX, MAIN_THREAD_LOCATION);
+ g_L = lua_tothread(L, -1);
lua_pop(L, 1);
- return base;
+ return g_L;
}
-static void freeCallbackArgs(le_callback* arg) {
- if(arg->L) {
- lua_State* L = arg->L;
- arg->L = NULL;
- event_del(&arg->ev);
- luaL_unref(L, LUA_REGISTRYINDEX, arg->callbackRef);
- luaL_unref(L, LUA_REGISTRYINDEX, arg->objectRef);
- }
+int luaevent_newbase(lua_State* L) {
+ le_base *base = (le_base*)lua_newuserdata(L, sizeof(le_base));
+ base->loop_L = NULL; /* No running loop */
+ base->base = event_init();
+ luaL_getmetatable(L, EVENT_BASE_MT);
+ lua_setmetatable(L, -2);
+ return 1;
}
-static int call_callback_function(lua_State* L, int argCount) {
- int ret;
- if(lua_pcall(L, argCount, 1, 0) || !(lua_isnil(L, -1) || lua_isnumber(L, -1))) {
- printf("ERROR IN INIT: %s\n", lua_tostring(L, -1));
- lua_pop(L, 1);
- return -1;
- }
- /* Lua_isnil returns 1 if the value is nil... */
- ret = lua_tointeger(L, -1) | -lua_isnil(L, -1);
- lua_pop(L, 1);
- if(ret < 0) { /* Done, no need to setup event */
- return -1;
- }
- if(ret != EV_READ && ret != EV_WRITE) {
- printf("BAD RET_VAL IN INIT: %i\n", ret);
+void freeCallbackArgs(le_callback* arg, lua_State* L) {
+ if(arg->base) {
+ arg->base = NULL;
+ event_del(&arg->ev);
+ luaL_unref(L, LUA_REGISTRYINDEX, arg->callbackRef);
}
- return ret;
}
-
-static void luaevent_callback(int fd, short event, void* p);
-
-static void setup_event(le_callback* arg, int fd, short event, int resetEvent) {
- /* Setup event... */
- if(resetEvent) event_del(&arg->ev);
- event_set(&arg->ev, fd, event| EV_PERSIST, luaevent_callback, arg);
- if(!resetEvent) event_base_set(getEventBase(arg->L), &arg->ev);
- event_add(&arg->ev, NULL);
-}
-
/* le_callback is allocated at the beginning of the coroutine in which it
is used, no need to manually de-allocate */
/* Index for coroutine is fd as integer for *nix, as lightuserdata for Win */
static void luaevent_callback(int fd, short event, void* p) {
le_callback* arg = p;
- lua_State* L = arg->L;
+ lua_State* L;
int ret;
+ assert(arg && arg->base && arg->base->loop_L);
+ L = arg->base->loop_L;
lua_rawgeti(L, LUA_REGISTRYINDEX, arg->callbackRef);
lua_pushinteger(L, event);
-
- if(-1 == (ret = call_callback_function(L, 1))) {
- freeCallbackArgs(arg);
- return;
+ lua_call(L, 1, 1);
+ ret = lua_tointeger(L, -1);
+ lua_pop(L, 1);
+ if(ret == -1) {
+ freeCallbackArgs(arg, L);
+ } else {
+ struct event *ev = &arg->ev;
+ int newEvent = ret;
+ if(newEvent != event) { // Need to hook up new event...
+ event_del(ev);
+ event_set(ev, fd, EV_PERSIST | newEvent, luaevent_callback, arg);
+ event_add(ev, NULL);
+ }
}
-
- if(event != ret)
- setup_event(arg, fd, ret, 1);
}
static int luaevent_base_gc(lua_State* L) {
- struct event_base** pbase = luaL_checkudata(L, 1, EVENT_BASE_MT);
- if(*pbase) {
- event_base_free(*pbase);
- *pbase = NULL;
+ le_base *base = luaL_checkudata(L, 1, EVENT_BASE_MT);
+ if(base->base) {
+ event_base_free(base->base);
+ base->base = NULL;
}
return 0;
}
static int luaevent_cb_gc(lua_State* L) {
le_callback* arg = luaL_checkudata(L, 1, EVENT_CALLBACK_ARG_MT);
- freeCallbackArgs(arg);
+ freeCallbackArgs(arg, L);
return 0;
}
-static int luaevent_cb_getfd(lua_State* L) {
- le_callback* arg = luaL_checkudata(L, 1, EVENT_CALLBACK_ARG_MT);
- lua_pushinteger(L, arg->ev.ev_fd);
- return 1;
-}
-
-static int getSocketFd(lua_State* L, int idx) {
+int getSocketFd(lua_State* L, int idx) {
int fd;
luaL_checktype(L, idx, LUA_TUSERDATA);
lua_getfield(L, idx, "getfd");
@@ -118,52 +94,48 @@ static int getSocketFd(lua_State* L, int idx) {
return fd;
}
-static void push_new_callback(lua_State* L, int callbackRef, int fd, short event) {
- le_callback* arg = lua_newuserdata(L, sizeof(*arg));
+/* sock, event, callback */
+static int luaevent_addevent(lua_State* L) {
+ int fd, event, callbackRef;
+ le_callback* arg;
+ le_base *base = luaL_checkudata(L, 1, EVENT_BASE_MT);
+ fd = getSocketFd(L, 2);
+ event = luaL_checkinteger(L, 3);
+ luaL_checktype(L, 4, LUA_TFUNCTION);
+ lua_pushvalue(L, 4);
+ callbackRef = luaL_ref(L, LUA_REGISTRYINDEX);
+ arg = lua_newuserdata(L, sizeof(*arg));
luaL_getmetatable(L, EVENT_CALLBACK_ARG_MT);
lua_setmetatable(L, -2);
- arg->L = L;
+ arg->base = base;
arg->callbackRef = callbackRef;
- lua_pushvalue(L, -1);
- arg->objectRef = luaL_ref(L, LUA_REGISTRYINDEX);
- setup_event(arg, fd, event, 0);
-}
-/* Expected to be called at the beginning of the coro that uses it..
-Value must be kept until coro is complete....
-*/
-/* sock, callback */
-static int luaevent_addevent(lua_State* L) {
- int fd, callbackRef;
- int top, ret;
- fd = getSocketFd(L, 1);
- luaL_checktype(L, 2, LUA_TFUNCTION);
- top = lua_gettop(L);
- /* Preserve the callback function */
- lua_pushvalue(L, 2);
- callbackRef = luaL_ref(L, LUA_REGISTRYINDEX);
- /* Call the callback with all arguments after it to get the loop primed.. */
- if(-1 == (ret = call_callback_function(L, top - 2))) {
- luaL_unref(L, LUA_REGISTRYINDEX, callbackRef);
- return 0;
- }
-
- push_new_callback(L, callbackRef, fd, ret);
+ /* Setup event... */
+ event_set(&arg->ev, fd, event | EV_PERSIST, luaevent_callback, arg);
+ event_base_set(base->base, &arg->ev);
+ event_add(&arg->ev, NULL);
return 1;
}
static int luaevent_loop(lua_State* L) {
- int ret = event_base_loop(getEventBase(L), 0);
+ le_base *base = luaL_checkudata(L, 1, EVENT_BASE_MT);
+ base->loop_L = L;
+ int ret = event_base_loop(base->base, 0);
lua_pushinteger(L, ret);
return 1;
}
-static luaL_Reg funcs[] = {
+static luaL_Reg base_funcs[] = {
{ "addevent", luaevent_addevent },
{ "loop", luaevent_loop },
{ NULL, NULL }
};
+static luaL_Reg funcs[] = {
+ { "new", luaevent_newbase },
+ { NULL, NULL }
+};
+
typedef struct {
const char* name;
int value;
@@ -191,18 +163,21 @@ int luaopen_luaevent_core(lua_State* L) {
lua_replace(L, LUA_ENVIRONINDEX);
/* Setup metatable */
luaL_newmetatable(L, EVENT_BASE_MT);
+ lua_newtable(L);
+ luaL_register(L, NULL, base_funcs);
+ lua_setfield(L, -2, "__index");
lua_pushcfunction(L, luaevent_base_gc);
lua_setfield(L, -2, "__gc");
lua_pop(L, 1);
luaL_newmetatable(L, EVENT_CALLBACK_ARG_MT);
lua_pushcfunction(L, luaevent_cb_gc);
lua_setfield(L, -2, "__gc");
- lua_pushcfunction(L, luaevent_cb_getfd);
- lua_setfield(L, -2, "getfd");
+ lua_newtable(L);
+ lua_pushcfunction(L, luaevent_cb_gc);
+ lua_setfield(L, -2, "close");
+ lua_setfield(L, -2, "__index");
lua_pop(L, 1);
- setEventBase(L, event_init());
-
luaL_register(L, "luaevent.core", funcs);
setNamedIntegers(L, consts);
return 1;