X-Git-Url: http://git.archive.openwrt.org/?p=project%2Flibubox.git;a=blobdiff_plain;f=lua%2Fuloop.c;h=782b5a51b5fbc5a583c63d8193f8a1725738221c;hp=900e14061c54ed9387deeb2aa02c2c86ecf4ccc8;hb=663d7d4b88e7fba1ad56c6e9742d1c157724e38c;hpb=5038992465876ba0985372b64fb451f1e4fdb8fc diff --git a/lua/uloop.c b/lua/uloop.c index 900e140..782b5a5 100644 --- a/lua/uloop.c +++ b/lua/uloop.c @@ -25,6 +25,12 @@ #include "../uloop.h" #include "../list.h" +struct lua_uloop_fd { + struct uloop_fd fd; + int r; + int fd_r; +}; + struct lua_uloop_timeout { struct uloop_timeout t; int r; @@ -37,13 +43,36 @@ struct lua_uloop_process { static lua_State *state; +static void * +ul_create_userdata(lua_State *L, size_t size, const luaL_Reg *reg, lua_CFunction gc) +{ + void *ret = lua_newuserdata(L, size); + + memset(ret, 0, size); + lua_createtable(L, 0, 2); + lua_pushvalue(L, -1); + lua_setfield(L, -2, "__index"); + lua_pushcfunction(L, gc); + lua_setfield(L, -2, "__gc"); + lua_pushvalue(L, -1); + lua_setmetatable(L, -3); + lua_pushvalue(L, -2); + luaI_openlib(L, NULL, reg, 1); + lua_pushvalue(L, -2); + + return ret; +} + static void ul_timer_cb(struct uloop_timeout *t) { struct lua_uloop_timeout *tout = container_of(t, struct lua_uloop_timeout, t); lua_getglobal(state, "__uloop_cb"); lua_rawgeti(state, -1, tout->r); + lua_remove(state, -2); + lua_call(state, 0, 0); + } static int ul_timer_set(lua_State *L) @@ -70,8 +99,15 @@ static int ul_timer_free(lua_State *L) struct lua_uloop_timeout *tout = lua_touserdata(L, 1); uloop_timeout_cancel(&tout->t); + + /* obj.__index.__gc = nil , make sure executing only once*/ + lua_getfield(L, -1, "__index"); + lua_pushstring(L, "__gc"); + lua_pushnil(L); + lua_settable(L, -3); + lua_getglobal(state, "__uloop_cb"); - luaL_unref(L, -1, tout->r); + luaL_unref(state, -1, tout->r); return 1; } @@ -104,35 +140,159 @@ static int ul_timer(lua_State *L) lua_pushvalue(L, -2); ref = luaL_ref(L, -2); - tout = lua_newuserdata(L, sizeof(*tout)); - lua_createtable(L, 0, 2); - lua_pushvalue(L, -1); - lua_setfield(L, -2, "__index"); - lua_pushcfunction(L, ul_timer_free); - lua_setfield(L, -2, "__gc"); - lua_pushvalue(L, -1); - lua_setmetatable(L, -3); - lua_pushvalue(L, -2); - luaI_openlib(L, NULL, timer_m, 1); - lua_pushvalue(L, -2); - - memset(tout, 0, sizeof(*tout)); - + tout = ul_create_userdata(L, sizeof(*tout), timer_m, ul_timer_free); tout->r = ref; tout->t.cb = ul_timer_cb; + if (set) uloop_timeout_set(&tout->t, set); return 1; } +static void ul_ufd_cb(struct uloop_fd *fd, unsigned int events) +{ + struct lua_uloop_fd *ufd = container_of(fd, struct lua_uloop_fd, fd); + + lua_getglobal(state, "__uloop_cb"); + lua_rawgeti(state, -1, ufd->r); + lua_remove(state, -2); + + /* push fd object */ + lua_getglobal(state, "__uloop_fds"); + lua_rawgeti(state, -1, ufd->fd_r); + lua_remove(state, -2); + + /* push events */ + lua_pushinteger(state, events); + lua_call(state, 2, 0); +} + + +static int get_sock_fd(lua_State* L, int idx) { + int fd; + if(lua_isnumber(L, idx)) { + fd = lua_tonumber(L, idx); + } else { + luaL_checktype(L, idx, LUA_TUSERDATA); + lua_getfield(L, idx, "getfd"); + if(lua_isnil(L, -1)) + return luaL_error(L, "socket type missing 'getfd' method"); + lua_pushvalue(L, idx - 1); + lua_call(L, 1, 1); + fd = lua_tointeger(L, -1); + lua_pop(L, 1); + } + return fd; +} + +static int ul_ufd_delete(lua_State *L) +{ + struct lua_uloop_fd *ufd = lua_touserdata(L, 1); + + uloop_fd_delete(&ufd->fd); + + /* obj.__index.__gc = nil , make sure executing only once*/ + lua_getfield(L, -1, "__index"); + lua_pushstring(L, "__gc"); + lua_pushnil(L); + lua_settable(L, -3); + + lua_getglobal(state, "__uloop_cb"); + luaL_unref(state, -1, ufd->r); + lua_remove(state, -1); + + lua_getglobal(state, "__uloop_fds"); + luaL_unref(state, -1, ufd->fd_r); + lua_remove(state, -1); + + return 1; +} + +static const luaL_Reg ufd_m[] = { + { "delete", ul_ufd_delete }, + { NULL, NULL } +}; + +static int ul_ufd_add(lua_State *L) +{ + struct lua_uloop_fd *ufd; + int fd = 0; + unsigned int flags = 0; + int ref; + int fd_ref; + + if (lua_isnumber(L, -1)) { + flags = lua_tointeger(L, -1); + lua_pop(L, 1); + } + + if (!lua_isfunction(L, -1)) { + lua_pushstring(L, "invalid arg list"); + lua_error(L); + + return 0; + } + + fd = get_sock_fd(L, -2); + + lua_getglobal(L, "__uloop_cb"); + lua_pushvalue(L, -2); + ref = luaL_ref(L, -2); + lua_pop(L, 1); + + lua_getglobal(L, "__uloop_fds"); + lua_pushvalue(L, -3); + fd_ref = luaL_ref(L, -2); + lua_pop(L, 1); + + ufd = ul_create_userdata(L, sizeof(*ufd), ufd_m, ul_ufd_delete); + ufd->r = ref; + ufd->fd.fd = fd; + ufd->fd_r = fd_ref; + ufd->fd.cb = ul_ufd_cb; + if (flags) + uloop_fd_add(&ufd->fd, flags); + + return 1; +} + +static int ul_process_free(lua_State *L) +{ + struct lua_uloop_process *proc = lua_touserdata(L, 1); + + /* obj.__index.__gc = nil , make sure executing only once*/ + lua_getfield(L, -1, "__index"); + lua_pushstring(L, "__gc"); + lua_pushnil(L); + lua_settable(L, -3); + + if (proc->r != LUA_NOREF) { + uloop_process_delete(&proc->p); + + lua_getglobal(state, "__uloop_cb"); + luaL_unref(state, -1, proc->r); + lua_remove(state, -1); + } + + return 1; +} + +static const luaL_Reg process_m[] = { + { "delete", ul_process_free }, + { NULL, NULL } +}; + static void ul_process_cb(struct uloop_process *p, int ret) { struct lua_uloop_process *proc = container_of(p, struct lua_uloop_process, p); lua_getglobal(state, "__uloop_cb"); lua_rawgeti(state, -1, proc->r); + luaL_unref(state, -2, proc->r); + proc->r = LUA_NOREF; + lua_remove(state, -2); lua_pushinteger(state, ret >> 8); lua_call(state, 1, 0); } @@ -191,9 +351,7 @@ static int ul_process(lua_State *L) lua_pushvalue(L, -2); ref = luaL_ref(L, -2); - proc = lua_newuserdata(L, sizeof(*proc)); - memset(proc, 0, sizeof(*proc)); - + proc = ul_create_userdata(L, sizeof(*proc), process_m, ul_process_free); proc->r = ref; proc->p.pid = pid; proc->p.cb = ul_process_cb; @@ -218,14 +376,26 @@ static int ul_run(lua_State *L) return 1; } +static int ul_end(lua_State *L) +{ + uloop_end(); + return 1; +} + static luaL_reg uloop_func[] = { {"init", ul_init}, {"run", ul_run}, {"timer", ul_timer}, {"process", ul_process}, + {"fd_add", ul_ufd_add}, + {"cancel", ul_end}, {NULL, NULL}, }; +/* avoid warnings about missing declarations */ +int luaopen_uloop(lua_State *L); +int luaclose_uloop(lua_State *L); + int luaopen_uloop(lua_State *L) { state = L; @@ -233,11 +403,30 @@ int luaopen_uloop(lua_State *L) lua_createtable(L, 1, 0); lua_setglobal(L, "__uloop_cb"); + lua_createtable(L, 1, 0); + lua_setglobal(L, "__uloop_fds"); + luaL_openlib(L, "uloop", uloop_func, 0); lua_pushstring(L, "_VERSION"); lua_pushstring(L, "1.0"); lua_rawset(L, -3); + lua_pushstring(L, "ULOOP_READ"); + lua_pushinteger(L, ULOOP_READ); + lua_rawset(L, -3); + + lua_pushstring(L, "ULOOP_WRITE"); + lua_pushinteger(L, ULOOP_WRITE); + lua_rawset(L, -3); + + lua_pushstring(L, "ULOOP_EDGE_TRIGGER"); + lua_pushinteger(L, ULOOP_EDGE_TRIGGER); + lua_rawset(L, -3); + + lua_pushstring(L, "ULOOP_BLOCKING"); + lua_pushinteger(L, ULOOP_BLOCKING); + lua_rawset(L, -3); + return 1; }