diff options
-rw-r--r-- | luaevent/luaevent.lua | 54 | ||||
-rw-r--r-- | luaevent/src/luaevent.c | 32 | ||||
-rw-r--r-- | luaevent/test/test.lua | 33 | ||||
-rw-r--r-- | luaevent/test/testClient.lua | 27 |
4 files changed, 83 insertions, 63 deletions
diff --git a/luaevent/luaevent.lua b/luaevent/luaevent.lua index 3b8ed18..be7f296 100644 --- a/luaevent/luaevent.lua +++ b/luaevent/luaevent.lua @@ -9,18 +9,10 @@ local EV_READ = luaevent.core.EV_READ local EV_WRITE = luaevent.core.EV_WRITE local fair = false --- Weak keys.. the keys are the client sockets -local clientTable = {} or setmetatable({}, {'__mode', 'k'}) +local hookedObjectMt = false -local function getWrapper() - local running = coroutine.running() - return function(...) - print(coroutine.running(), running) - print(debug.traceback()) - if coroutine.running() == running then return end - return select(2, coroutine.resume(running, ...)) - end -end +-- Weak keys.. the keys are the client sockets +local clientTable = setmetatable({}, {'__mode', 'k'}) function send(sock, data, start, stop) local s, err @@ -35,7 +27,6 @@ function send(sock, data, start, stop) coroutine.yield(EV_WRITE) end if s or err ~= "timeout" then return s, err, sent end - if not clientTable[sock] then clientTable[sock] = luaevent.core.addevent(sock, EV_WRITE, getWrapper()) end coroutine.yield(EV_WRITE) until false end @@ -45,7 +36,6 @@ function receive(sock, pattern, part) repeat s, err, part = sock:receive(pattern, part) if s or err ~= "timeout" then return s, err, part end - if not clientTable[sock] then clientTable[sock] = luaevent.core.addevent(sock, EV_READ, getWrapper()) end coroutine.yield(EV_READ) until false end @@ -58,7 +48,6 @@ function receivePartial(client, pattern) s, err, part = client:receive(pattern) if s or ( (type(pattern)=="number") and part~="" and part ~=nil ) or err ~= "timeout" then return s, err, part end - if not clientTable[sock] then clientTable[sock] = luaevent.core.addevent(sock, EV_READ, getWrapper()) end coroutine.yield(EV_READ) until false end @@ -66,7 +55,6 @@ function connect(sock, ...) sock:settimeout(0) local ret, err = sock:connect(...) if ret or err ~= "timeout" then return ret, err end - if not clientTable[sock] then clientTable[sock] = luaevent.core.addevent(sock, EV_WRITE, getWrapper()) end coroutine.yield(EV_WRITE) ret, err = sock:connect(...) if err == "already connected" then @@ -81,28 +69,44 @@ local function clientCoroutine(sock, handler) -- Figure out what to do ...... return handler(sock) end -local function handleClient(co, client, handler) - local ok, res, event = coroutine.resume(co, client, handler) -end + local function serverCoroutine(sock, callback) - local listenItem = luaevent.core.addevent(sock, EV_READ, getWrapper()) repeat local event = coroutine.yield(EV_READ) -- Get new socket local client = sock:accept() if client then + --cl[#cl + 1] = client client:settimeout(0) - local co = coroutine.create(clientCoroutine) - handleClient(co, client, callback) + local coFunc = coroutine.wrap(clientCoroutine) + clientTable[client] = luaevent.core.addevent(client, coFunc, client, callback) end until false end + +local oldAddEvent = luaevent.core.addevent +luaevent.core.addevent = function(...) + local item = oldAddEvent(...) + print("SETUP ITEM FOR: ", debug.getmetatable(item).getfd(item)) + if not hookedObjectMt then + hookedObjectMt = true + local mt = debug.getmetatable(item) + local oldGC = mt.__gc + mt.__gc = function(...) + print("RELEASING ITEM FOR: ", mt.getfd(...)) + return oldGC(...) + end + end + return item +end + function addserver(sock, callback) - local coro = coroutine.create(serverCoroutine) - assert(coroutine.resume(coro, sock, callback)) + local coFunc = coroutine.wrap(serverCoroutine) + clientTable[sock] = luaevent.core.addevent(sock, coFunc, sock, callback) end -function addthread(func, ...) - return coroutine.resume(coroutine.create(func), ...) +function addthread(sock, func, ...) + local coFunc = coroutine.wrap(func) + clientTable[sock] = luaevent.core.addevent(sock, coFunc, ...) end local _skt_mt = {__index = { connect = function(self, ...) diff --git a/luaevent/src/luaevent.c b/luaevent/src/luaevent.c index 311ad0e..d79345e 100644 --- a/luaevent/src/luaevent.c +++ b/luaevent/src/luaevent.c @@ -74,6 +74,12 @@ static int luaevent_cb_gc(lua_State* 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; +} + int getSocketFd(lua_State* L, int idx) { int fd; luaL_checktype(L, idx, LUA_TUSERDATA); @@ -90,23 +96,35 @@ int getSocketFd(lua_State* L, int idx) { /* Expected to be called at the beginning of the coro that uses it.. Value must be kept until coro is complete.... */ -/* sock, event, callback */ +/* sock, callback */ static int luaevent_addevent(lua_State* L) { - int fd, event, callbackRef; + int fd, callbackRef; + int top, ret; le_callback* arg; fd = getSocketFd(L, 1); - event = luaL_checkinteger(L, 2); - luaL_checktype(L, 3, LUA_TFUNCTION); - lua_pushvalue(L, 3); + 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.. */ + lua_call(L, top - 2, 1); + ret = lua_tointeger(L, -1); + lua_pop(L, 1); + if(ret == -1) { /* Done, no need to setup event */ + luaL_unref(L, LUA_REGISTRYINDEX, callbackRef); + return 0; + } arg = lua_newuserdata(L, sizeof(*arg)); luaL_getmetatable(L, EVENT_CALLBACK_ARG_MT); lua_setmetatable(L, -2); arg->L = L; arg->callbackRef = callbackRef; + /* Setup event... */ - event_set(&arg->ev, fd, event | EV_PERSIST, luaevent_callback, arg); + event_set(&arg->ev, fd, ret | EV_PERSIST, luaevent_callback, arg); event_base_set(getEventBase(L), &arg->ev); event_add(&arg->ev, NULL); return 1; @@ -157,6 +175,8 @@ int luaopen_luaevent_core(lua_State* L) { 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_pop(L, 1); setEventBase(L, event_init()); diff --git a/luaevent/test/test.lua b/luaevent/test/test.lua index 1bcd173..f7a44da 100644 --- a/luaevent/test/test.lua +++ b/luaevent/test/test.lua @@ -6,29 +6,18 @@ require"luaevent" require"socket" local function echoHandler(skt) - while true do - print(skt) - local data,ret = luaevent.receive(skt, 10) - print("GOT: ", data, ret) - if data == "quit" or ret == 'closed' then - break - end - luaevent.send(skt, data) - end - print("DONE") -end -local function setupHook(thread) - if not thread then debug.sethook(function(event) print("TRACE >: ", debug.getinfo(2, 'n').name) end, 'c') - else debug.sethook(thread, function(event) print("TRACE ", thread,">: ", debug.getinfo(2, 'n').name) end, 'c') end + while true do + local data,ret = luaevent.receive(skt, 10) + if data == "quit" or ret == 'closed' then + break + end + --collectgarbage() + luaevent.send(skt, data) + end end + local server = assert(socket.bind("localhost", 20000)) server:settimeout(0) -setupHook() -local coro = coroutine.create -coroutine.create = function(...) - local ret = coro(...) - setupHook(ret) - return ret -end + luaevent.addserver(server, echoHandler) -luaevent.loop() +luaevent.loop()
\ No newline at end of file diff --git a/luaevent/test/testClient.lua b/luaevent/test/testClient.lua index b6dfa44..0557230 100644 --- a/luaevent/test/testClient.lua +++ b/luaevent/test/testClient.lua @@ -1,15 +1,22 @@ require"luaevent" require"socket" +local function setupHook(thread) + if not thread then debug.sethook(function(event) print("TRACE >: ", debug.getinfo(2, 'n').name) end, 'c') + else debug.sethook(thread, function(event) print("TRACE ", thread,">: ", debug.getinfo(2, 'n').name) end, 'c') end +end -local function func() - print("ACTIVATED") - local sock = socket.tcp() - --sock: +local function func(sock) sock = luaevent.wrap(sock) - print(assert(sock:connect("localhost", 20000))) - for i = 1, 100000 do assert(sock:send("Greet me ")) assert(sock:receive(10)) collectgarbage() end + assert(sock:connect("localhost", 20000)) + for i = 1, 10 do + for z = 1, 100 do + assert(sock:send("Greet me ")) + end + assert(sock:receive(10 * 100)) + end end - -luaevent.addthread(func) - -luaevent.loop()
\ No newline at end of file +for i = 1, 1020 do + local sock = assert(socket.tcp()) + luaevent.addthread(sock, func, sock) +end +luaevent.loop() |