From 0bba080660c847ad821bab54bd412f0eed030620 Mon Sep 17 00:00:00 2001 From: Joachim Nilsson Date: Thu, 18 Jul 2013 23:28:09 +0200 Subject: [PATCH] Initial import of Flemming Madsen's LibUEvent This fork is called libuev and will focus solely on embedded Linux systems using C. Patches for other UNIX-like operating systems are welcome. - Remove Lua support, will not be used. - Rename from LibUEvent to libuev where applicable - Add project's MIT license to top of all files, as is customary - Add a LICENSE file, as is customary This MIT licensed code was cloned from the Mercurial repository at Google http://code.google.com/p/libuevent/ which had mislabled the license as "New BSD License", which is wrong. The actual license of the project is https://en.wikipedia.org/wiki/MIT_License Signed-off-by: Joachim Nilsson --- .gitignore | 4 + AUTHORS | 2 + LICENSE | 21 ++ Makefile | 85 ++++---- README | 71 +------ README.md | 39 ++++ libuevent.c => libuev.c | 46 +++-- libuev.h | 68 +++++++ libuevent.h | 75 ------- luevent.c | 419 ---------------------------------------- test.c | 40 +++- test.lua | 76 -------- 12 files changed, 247 insertions(+), 699 deletions(-) create mode 100644 .gitignore create mode 100644 AUTHORS create mode 100644 LICENSE mode change 100644 => 120000 README create mode 100644 README.md rename libuevent.c => libuev.c (90%) create mode 100644 libuev.h delete mode 100644 libuevent.h delete mode 100644 luevent.c delete mode 100644 test.lua diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..30c51f2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +libuev.a +libuev.o +libuev.so.1 +test diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..a33bf19 --- /dev/null +++ b/AUTHORS @@ -0,0 +1,2 @@ +Flemming Madsen +Joachim Nilsson \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..3cbd2a3 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +Copyright (c) 2012 Flemming Madsen +Copyright (c) 2013 Joachim Nilsson + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/Makefile b/Makefile index 5609241..23c7696 100644 --- a/Makefile +++ b/Makefile @@ -1,47 +1,64 @@ -## -# @file Makefile -# Make the micro eventlib, lua bindings and tests +# -*-Makefile-*- for libuev # -# $Id$ +# Copyright (c) 2012 Flemming Madsen +# Copyright (c) 2013 Joachim Nilsson # -# (C) Copyright 2012 flemming.madsen at madsensoft.dk. See libuevent.h -## +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +.PHONY: all test clean -CROSS_COMPILE= -#CROSS_COMPILE=arm-linux-uclibc- -CC=$(CROSS_COMPILE)gcc -AR=$(CROSS_COMPILE)ar +CC = $(CROSS_COMPILE)gcc +AR = $(CROSS_COMPILE)ar +STRIP = $(CROSS_COMPILE)strip +CFLAGS = -fPIC -g -Os +ARFLAGS = crus +JUNK = *~ *.bak *.map .*.d DEADJOE *.gdb *.elf core core.* -INCLUDE += -I /usr/include/lua5.1/ -LDFLAGS=-g -CFLAGS=-fPIC -g -Os $(INCLUDE) +OBJS := libuev.o +SRCS := $(OBJS:.o=.c) +DEPS := $(addprefix .,$(SRCS:.c=.d)) +VER = 1 +LIBNAME = libuev +MYLIB = $(LIBNAME).so +TARGET = $(MYLIB).$(VER) +STATICLIB = $(LIBNAME).a -MAJOR = 1 +all: $(TARGET) -all: libuevent.a libuevent.so.$(MAJOR) -lua: luevent.so +.c.o: + @printf " CC $@\n" + @$(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $< -libuevent.a: libuevent.o - $(AR) r $@ $^ - -libuevent.so.$(MAJOR): libuevent.o - $(CC) $(LDFLAGS) -shared -o $@ $^ -Wl,-soname=libuevent - -luevent.so: luevent.o all - $(CC) $(LDFLAGS) -shared -o $@ luevent.o -L . -l uevent -Wl,-soname=luevent - -stripped: all lua - $(CROSS_COMPILE)strip --strip-unneeded libuevent.a libuevent.so.$(MAJOR) luevent.so +$(TARGET): $(OBJS) + @printf " LINK $@\n" + @$(CC) $(LDFLAGS) -shared -Wl,-soname=$@ -o $@ $^ + @$(AR) $(ARFLAGS) $(STATICLIB) $^ +strip: all + @printf " STRIP %s\n" $(TARGET) + @$(STRIP) --strip-unneeded $(TARGET) $(STATICLIB) test: all - $(CC) -g -o test -D NO_DEBUG test.c libuevent.c && ./test - -luatest: lua - lua test.lua + @printf " TEST %s\n" $(STATICLIB) + @$(CC) -g -DNO_DEBUG -o test test.c $(STATICLIB) && ./test clean: - rm -f libuevent.o luevent.o libuevent.so.$(MAJOR) luevent.so test + -@$(RM) $(JUNK) $(STATICLIB) $(TARGET) *.o test - -.PHONY: all test clean luatest lua diff --git a/README b/README deleted file mode 100644 index 9de768e..0000000 --- a/README +++ /dev/null @@ -1,70 +0,0 @@ -LibUEvent - A Microscopic event library. -======================================== - -The libuevent library is a small event library in the style of the venerable -Xt(3) event loop. - -Basically an event context is created,and handlers for timeounts and stream -events can be registered with this context. - -After initial setup, the typical application will enter the event loop that -will only return at program termination. - -The C API ---------- -The typical application will do the following steps -1. Create the event context with lueCtxtCreate() -2. Register initial callbacks with lueAddInput, lueAddOutput and lueAddTimer -3. Enter the event loop - -Lua binding ------------ -A lua binding is available that should mix well with luasocket and luaposix. -Time resolutions are in milli second integers in order to support integer-only -embedded environments - -### function luevent.addFileIO(fdesc, handler, mode) -Add a handler on a stream. The handler will sustain itself GC wise. -Use *object*:clear() to unregister the handler -* fdesc The posix file descriptor "small integer". - Use the ":getfd()" method on a "normal" lua stream or socket to obtain fdesc. -* handler A function object. The handler object is supplied as the first parameter when called. -* mode Optional. Input ("r") or output ("w") event. Default is input -* return A new filehandler object - -### function luevent.addTimer(msecs, handler) -Create a new timer object. Implicitly cleared when handler is called. -Typical usage: - local hdl - hdl = luevent.addTimer(50, function() hdl = nil ..... end) - ...... - if hdl then hdl:clear() hdl = nil end -Here *hdl* is used to keep track of whether the timer is active. - -* msecs The number of milliseconds until the timer expires -* handler A function object. The handler object is supplied as the first parameter when called. -* return A new timer object - -### function object:clear() -Cancel a callback registration. Renders the object ready for GC. - -### function object:handler() -Obtain the handler function from a callback registration. - - -Building --------- -Use make: - -* make all: The library -* make test: Test and showcase -* make lua: Build the lua binding - -Installation ------------- -Is purely manual, but would be something along the lines of: - sudo install -m 444 libuevent.so.1 /usr/lib/libuevent.so.1 - sudo install -m 444 luevent.so /usr/lib/lua/5.1/luevent.so - - - diff --git a/README b/README new file mode 120000 index 0000000..42061c0 --- /dev/null +++ b/README @@ -0,0 +1 @@ +README.md \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..6d70a8b --- /dev/null +++ b/README.md @@ -0,0 +1,39 @@ +libuev - Asynchronous event loop library +======================================== + +The libuev library is a small event library in the style of the venerable +Xt(3) event loop. + +Basically an event context is created,and handlers for timeounts and stream +events can be registered with this context. + +After initial setup, the typical application will enter the event loop that +will only return at program termination. + +The C API +--------- +The typical application will do the following steps + +1. Create the event context with lueCtxtCreate() +2. Register initial callbacks with lueAddInput, lueAddOutput and lueAddTimer +3. Enter the event loop + +Building +-------- +Use make: + +* make all: The library +* make test: Test and showcase + +Installation +------------ +Is purely manual, but would be something along the lines of: + sudo install -m 444 libuev.so.1 /usr/lib/libuev.so.1 + +Warning +------- +Not thread safe! + +The ctxt structure needs mutex protection in case of multi threaded +access. + diff --git a/libuevent.c b/libuev.c similarity index 90% rename from libuevent.c rename to libuev.c index 0662913..be8d313 100644 --- a/libuevent.c +++ b/libuev.c @@ -1,25 +1,41 @@ -/** - * @file - * Micro event library libuevent. - * Asynchronous event / mainloop library. - * Not thread safe! - * The ctxt structure needs mutex protection in case of multithreaded access - * $Id:$ +/* libuev - Asynchronous event loop library * - * (C) Copyright 2012 flemming.madsen at madsensoft.dk. See libuevent.h + * Copyright (c) 2012 Flemming Madsen + * Copyright (c) 2013 Joachim Nilsson + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include +#include +#include +#include +#include #include #include -#include -#include #include -#include #include -#include -#include -#include +#include + #include "llist.h" -#include "libuevent.h" +#include "libuev.h" #ifdef DEBUG #define Debug(f, args...) printf(":LUE: " f "\n", ##args) diff --git a/libuev.h b/libuev.h new file mode 100644 index 0000000..2758ea0 --- /dev/null +++ b/libuev.h @@ -0,0 +1,68 @@ +/* libuev - Asynchronous event loop library + * + * Copyright (c) 2012 Flemming Madsen + * Copyright (c) 2013 Joachim Nilsson + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef LIBUEV_H +#define LIBUEV_H + +struct LUETimerH; +struct LUEFileEventH; +struct LUECtxt; + +/** + * Typedef file handler callbacks + */ +typedef int (*LUEFileHandler)(struct LUECtxt *ctxt, + struct LUEFileEventH *handle, + int fd, + void *data); +/** + * Typedef timer handler callbacks + */ +typedef int (*LUETimerHandler)(struct LUECtxt *ctxt, + struct LUETimerH *handle, + void *data); + +struct LUEFileEventH *lueAddInput(struct LUECtxt *ctxt, + int fd, LUEFileHandler handler, void *data); +int lueRemInput(struct LUECtxt *ctxt, struct LUEFileEventH *hdl); +struct LUEFileEventH *lueAddOutput(struct LUECtxt *ctxt, + int fd, LUEFileHandler handler, void *data); +int lueRemOutput(struct LUECtxt *ctxt, struct LUEFileEventH *hdl); +int lueRemFd(struct LUECtxt *ctxt, int fd); + +struct LUETimerH *lueAddTimer(struct LUECtxt *ctxt, int periodMs, + LUETimerHandler handler, void *data); +int lueRemTimer(struct LUECtxt *ctxt, struct LUETimerH *hdl); + +struct LUECtxt *lueCtxtCreate(); +void lueCtxtDestroy(struct LUECtxt *lue); +void lueTimeAdvance(struct LUECtxt *ctxt, int mSecs); +void lueRun(struct LUECtxt *ctxt); +int lueProcessPending(struct LUECtxt *ctxt); +void lueTerminate(struct LUECtxt *ctxt); + +#endif /* LIBUEV_H */ + +// vim: set ts=8 sw=3 sts=3 et: diff --git a/libuevent.h b/libuevent.h deleted file mode 100644 index 2e376f4..0000000 --- a/libuevent.h +++ /dev/null @@ -1,75 +0,0 @@ -/** - * @file - * Micro event library libuevent. - * Asynchronous event / mainloop library. - * Not thread safe! - * The ctxt structure needs mutex protection in case of multithreaded access - * $Id:$ - * - * (C) Copyright 2012 flemming.madsen at madsensoft.dk. Notice at end of file - */ -#ifndef LIBUEVENT_H -#define LIBUEVENT_H - -struct LUETimerH; -struct LUEFileEventH; -struct LUECtxt; - -/** - * Typedef file handler callbacks - */ -typedef int (*LUEFileHandler)(struct LUECtxt *ctxt, - struct LUEFileEventH *handle, - int fd, - void *data); -/** - * Typedef timer handler callbacks - */ -typedef int (*LUETimerHandler)(struct LUECtxt *ctxt, - struct LUETimerH *handle, - void *data); - -struct LUEFileEventH *lueAddInput(struct LUECtxt *ctxt, - int fd, LUEFileHandler handler, void *data); -int lueRemInput(struct LUECtxt *ctxt, struct LUEFileEventH *hdl); -struct LUEFileEventH *lueAddOutput(struct LUECtxt *ctxt, - int fd, LUEFileHandler handler, void *data); -int lueRemOutput(struct LUECtxt *ctxt, struct LUEFileEventH *hdl); -int lueRemFd(struct LUECtxt *ctxt, int fd); - -struct LUETimerH *lueAddTimer(struct LUECtxt *ctxt, int periodMs, - LUETimerHandler handler, void *data); -int lueRemTimer(struct LUECtxt *ctxt, struct LUETimerH *hdl); - -struct LUECtxt *lueCtxtCreate(); -void lueCtxtDestroy(struct LUECtxt *lue); -void lueTimeAdvance(struct LUECtxt *ctxt, int mSecs); -void lueRun(struct LUECtxt *ctxt); -int lueProcessPending(struct LUECtxt *ctxt); -void lueTerminate(struct LUECtxt *ctxt); - -#endif - -/****************************************************************************** -* Copyright (C) 2012 flemming.madsen at madsensoft.dk. All rights reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining -* a copy of this software and associated documentation files (the -* "Software"), to deal in the Software without restriction, including -* without limitation the rights to use, copy, modify, merge, publish, -* distribute, sublicense, and/or sell copies of the Software, and to -* permit persons to whom the Software is furnished to do so, subject to -* the following conditions: -* -* The above copyright notice and this permission notice shall be -* included in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -******************************************************************************/ - diff --git a/luevent.c b/luevent.c deleted file mode 100644 index d8f4823..0000000 --- a/luevent.c +++ /dev/null @@ -1,419 +0,0 @@ -/** - * @file - * Lua binding to libuevent - * $Id:$ - * - * (C) Copyright 2012 flemming.madsen at madsensoft.dk. See libuevent.h - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "libuevent.h" - -static char * LUA_LTIMER_MT = "libuevent-timer"; -static char * LUA_LFILEH_MT = "libuevent-fileh"; -static char * LUA_LUEOBJ = "libuevent-objects"; - -typedef struct lue_data -{ - lua_State *L; // Index to our world - struct LUETimerH *timer; - struct LUEFileEventH *file; -} lue_data; -#define toptimer(L) ((struct lue_data *)luaL_checkudata(L, 1, LUA_LTIMER_MT)) -#define topfileh(L) ((struct lue_data *)luaL_checkudata(L, 1, LUA_LFILEH_MT)) - -static struct LUECtxt *getCtxt(lua_State *L) -{ - lua_getfield(L, LUA_REGISTRYINDEX, LUA_LUEOBJ); - lua_rawgeti(L, -1, 1); - struct LUECtxt *ret = lua_touserdata(L, -1); - lua_pop(L, 2); - return ret; -} - -static void l_newType(lua_State* L, const char *name) -{ - luaL_newmetatable(L, name); // create metatable - lua_pushvalue(L, -1); // dup - lua_setfield(L, -2, "__index"); // metatable.__index = metatable -} - -static int l_traceback (lua_State *L) -{ - lua_getfield(L, LUA_GLOBALSINDEX, "debug"); - if (!lua_istable(L, -1)) { - lua_pop(L, 1); - return 1; - } - lua_getfield(L, -1, "traceback"); - if (!lua_isfunction(L, -1)) { - lua_pop(L, 2); - return 1; - } - lua_pushvalue(L, 1); /* pass error message */ - lua_pushinteger(L, 2); /* skip this function and traceback */ - lua_call(L, 2, 1); /* call debug.traceback */ - return 1; -} - -// Top half -static int _lueHandler(lua_State *L, void *data, bool remObj) -{ - lua_pushcfunction(L, l_traceback); /* push traceback function */ - - lua_getfield(L, LUA_REGISTRYINDEX, LUA_LUEOBJ); - lua_pushlightuserdata(L, data); - lua_rawget(L, -2); // objects[object_p] => The object - lua_pushvalue(L, -1); - lua_rawget(L, -3); // object[object] => closure - - if (remObj) - { - lua_pushlightuserdata(L, data); - lua_pushnil(L); - lua_rawset(L, -5); // objects[object_p] = nil -> GC - lua_pushvalue(L, -2); - lua_pushnil(L); - lua_rawset(L, -5); // objects[object] = nil -> GC - } - lua_remove(L, -3); // objects table - - int ret; - lua_insert(L, -2); // exch: closure <-> obj - if ((ret = lua_pcall(L, 1, 0, -3))) // Call closure(object) - { - fprintf(stderr, "luevent: Error: %d:\n%s\n", - ret, lua_isnil(L, -1) ? "(nil)" : lua_tostring(L, -1)); - //exit(1); - } - lua_pop(L, 1); // Error handler, metatable - - return 0; -} - -static int _ltimerHandler(struct LUECtxt *ctxt, struct LUETimerH *handle, void *data) -{ - lue_data *self = (lue_data *) data; - if (!self || !self->timer) - return 0; - - int ret = _lueHandler(self->L, data, true); - self->timer = NULL; - return ret; -} - -static int _lfileHandler(struct LUECtxt *ctxt, struct LUEFileEventH *handle, int fd, void *data) -{ - lue_data *self = (lue_data *) data; - bool remObj = false; - if (!self || !self->file) - return 0; - - if (fcntl(fd, F_GETFD) == -1 && EBADF == errno) - { - remObj = true; - lueRemInput(getCtxt(self->L), self->file); // Works on both types - self->file = NULL; - } - - return _lueHandler(self->L, data, remObj); -} - -// Bottom half -static void lueAddObj(lua_State *L, lue_data *self, int cbix) -{ - self->L = L; - lua_getfield(L, LUA_REGISTRYINDEX, LUA_LUEOBJ); - - lua_pushlightuserdata(L, self); - lua_pushvalue(L, -3); - lua_rawset(L, -3); // objects[self_p] = obj - - lua_pushvalue(L, -2); - lua_pushvalue(L, cbix); - lua_rawset(L, -3); // objects[obj] = callback - lua_pop(L, 1); // objects -} - - /* LUADOC - * Add a handler on a stream. - * The handler will sustain itself GC wise. Use <:object>:clear() to unregister the handler - * @param fdesc The posix file descriptor "small integer". - *
Use the ":getfd()" method on a "normal" lua stream or socket to obtain fdesc. - * @param handler A function object. No paramaeter supplied when called. - * @param mode [Optional] Input ("r") or output ("w") event. Default is input - * @return A new filehandler object - function luevent.addFileIO(fdesc, handler, mode) - */ -static int lfileh_add(lua_State *L) -{ - int fd = luaL_checkint(L, 1); - luaL_checktype(L, 2, LUA_TFUNCTION); - const char *mode = luaL_optstring(L, 3, "r"); - - lue_data *self = (lue_data *) lua_newuserdata(L, sizeof(lue_data)); - struct LUEFileEventH *h = *mode == 'r' ? - lueAddInput(getCtxt(L), fd, _lfileHandler, self) : - lueAddOutput(getCtxt(L), fd, _lfileHandler, self); - if (!h) luaL_error(L, "lueAddFileIO error"); - self->file = h; - - luaL_getmetatable(L, LUA_LFILEH_MT); - lua_setmetatable(L, -2); - lueAddObj(L, self, 2); - - return 1; -} - - /* LUADOC - * Create a new timer object. Implicitly cleared when handler is called. - * @usage
-  *  local hdl
- * hdl = luevent.addTimer(50, function() hdl = nil xxx end)
- * ......
- * if hdl then hdl:clear() hdl = nil end
- *
- * Here hdl is used to keep track of whether the timer is active. - * @param msecs The number of milliseconds until the timer expires - * @param handler A function object - * @return A new timer object - function luevent.addTimer(msecs, handler) - */ -static int ltimer_add(lua_State *L) -{ - int mSecs = luaL_checkint(L, 1); - luaL_checktype(L, 2, LUA_TFUNCTION); - - lue_data *self = (lue_data *) lua_newuserdata(L, sizeof(lue_data)); - struct LUETimerH *h = self ? lueAddTimer(getCtxt(L), mSecs, _ltimerHandler, self) : NULL; - if (!h) - luaL_error(L, "lueAddTimer error"); - self->timer = h; - - luaL_getmetatable(L, LUA_LTIMER_MT); - lua_setmetatable(L, 3); - lueAddObj(L, self, 2); - - return 1; -} - -static void lobj_clear(lua_State *L, lue_data *self) -{ - lua_getfield(L, LUA_REGISTRYINDEX, LUA_LUEOBJ); - lua_pushlightuserdata(L, self); - lua_rawget(L, -2); // objects[object_p] => The object - - lua_pushnil(L); - lua_rawset(L, -3); // objects[object] = nil -> GC - lua_pushlightuserdata(L, self); - lua_pushnil(L); - lua_rawset(L, -3); // objects[object_p] = nil -> GC - lua_pop(L, 1); // pop objects -} - - /* LUADOC - * Cancel a timer callback. Renders the object ready for GC. - function timer:clear() - */ -static int ltimer_clear(lua_State *L) -{ - lue_data *self = toptimer(L); - - if (self->timer) - { - lueRemTimer(getCtxt(L), self->timer); - self->timer = NULL; - } - lobj_clear(L, self); - - return 0; -} - - /* LUADOC - * Cancel a fileio callback. Renders the object ready for GC. - function fileio:clear() - */ -static int lfileh_clear(lua_State *L) -{ - lue_data *self = topfileh(L); - - if (self->file) - { - lueRemInput(getCtxt(L), self->file); // Works on both types - self->file = NULL; - } - lobj_clear(L, self); - - return 0; -} - - /* LUADOC - * Obtain the registered handler on the object - * @return The handler - function luevent_object:handler() - */ -static int luevent_handler(lua_State *L) -{ - lue_data *self = lua_touserdata(L, 1); - - if (self) - { - lua_getfield(L, LUA_REGISTRYINDEX, LUA_LUEOBJ); - - lua_getfield(L, -1, "_objects"); - lua_getfield(L, -2, "_callbacks"); - if (lua_istable(L, -1) && lua_istable(L, -2)) - { - lua_pushlightuserdata(L, self); - lua_rawget(L, -2); // The object - lua_rawget(L, -2); // callbacks[obj] -> closure - return 1; - } - } - return 0; -} - -static int ltimer_gc(lua_State *L) -{ - //STACKDUMP(L); - lue_data *self = toptimer(L); - - if (self->timer) - { - lueRemTimer(getCtxt(L), self->timer); - self->timer = NULL; - } - return 0; -} - -static int lfileh_gc(lua_State *L) -{ - lue_data *self = topfileh(L); - - if (self->file) - { - lueRemInput(getCtxt(L), self->file); - self->file = NULL; - } - return 0; -} - -static int luevent_tostring(lua_State *L) -{ - lue_data *self = lua_touserdata(L, 1); - - lua_getmetatable(L, 1); - lua_getfield(L, -1, "_typename"); - const char *t = lua_tostring(L, -1); - - if (!self->timer && !self->file) - lua_pushfstring(L, "%s (cleared)", t); - else - lua_pushfstring(L, "%s (%p)", t, self); - return 1; -} - -/* LUADOC - * Get the system time in hight resolution - * @return two numbers: seconds and milliseconds since the epoch - function luevent.systemTime() - */ -static int l_systemTime (lua_State *L) -{ - struct timeval v; - - gettimeofday(&v, (struct timezone *) NULL); - lua_pushinteger(L, v.tv_sec); - lua_pushinteger(L, v.tv_usec / 1000); - return 2; // num of results -} - -static int l_run(lua_State * L) -{ - lueRun(getCtxt(L)); - return 0; -} - -static int l_terminate(lua_State * L) -{ - lueTerminate(getCtxt(L)); - return 0; -} - -static int l_cleanup(lua_State * L) -{ - struct LUECtxt *ctxt = getCtxt(L); - - lua_pushnil(L); - lua_setfield(L, LUA_REGISTRYINDEX, LUA_LUEOBJ); - lua_gc(L, LUA_GCCOLLECT, 0); // Make sure all timers & schedules & callbacks are gone before context - - lueCtxtDestroy(ctxt); - return 0; -} - -static const luaL_Reg lueventlib[] = { - {"addFileIO", lfileh_add}, - {"clearFileIO", lfileh_clear}, - {"addTimer", ltimer_add}, - {"clearTimer", ltimer_clear}, - {"systemTime", l_systemTime}, - {"run", l_run}, - {"terminate", l_terminate}, - {"__gc", l_cleanup}, - { NULL, NULL} -}; - -static const luaL_Reg ltimermeta[] = { - {"clear", ltimer_clear}, - {"handler", luevent_handler}, - {"__gc", ltimer_gc}, - {"__tostring", luevent_tostring}, - { NULL, NULL} -}; - -static const luaL_Reg lfilehmeta[] = { - {"clear", lfileh_clear}, - {"handler", luevent_handler}, - {"__gc", lfileh_gc}, - {"__tostring", luevent_tostring}, - { NULL, NULL} -}; - -int luaopen_luevent(lua_State * L) -{ - struct LUECtxt *lueContext = lueCtxtCreate(); - assert(lueContext); - - luaL_register(L, lua_tostring(L, 1), lueventlib); // calls - lua_pushvalue(L, -1); // Dup - lua_setmetatable(L, -2); // Call GC at module cleanup. - - l_newType(L, LUA_LTIMER_MT); // create metatable for timers - luaL_register(L, NULL, ltimermeta); // methods - lua_setfield(L, -2, "_meta_timer"); // easy access from test code - - l_newType(L, LUA_LFILEH_MT); // create metatable for file handlers - luaL_register(L, NULL, lfilehmeta); // methods - lua_setfield(L, -2, "_meta_fileh"); // easy access from test code - - lua_newtable(L); // Table[obj] -> Callback-closure - lua_pushvalue(L, -1); - lua_setfield(L, LUA_REGISTRYINDEX, LUA_LUEOBJ); - lua_pushlightuserdata(L, lueContext);// Table[1] = lueContext - lua_rawseti(L, -2, 1); - lua_setfield(L, -2, "_lue_objects");// easy access from test code - - lua_pop(L, 1); // pop module - return 0; -} - - -// vim: set sw=3 sts=3 et: diff --git a/test.c b/test.c index 5106f98..8c8d834 100644 --- a/test.c +++ b/test.c @@ -1,13 +1,33 @@ -/** - * @file - * Micro event library libuevent. - * Test & showcase of libuevent +/* Test libuev event library * - * (C) Copyright 2012 flemming.madsen at madsensoft.dk. See libuevent.h + * Copyright (c) 2012 Flemming Madsen + * Copyright (c) 2013 Joachim Nilsson + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + #include #include -#include "libuevent.h" +#include /* intptr_t */ + +#include "libuev.h" static period; static client_fd, server_fd, service_fd; @@ -17,14 +37,14 @@ int readFd, writeFd; static timeOutHdl(struct LUECtxt *ctxt, struct LUETimerH *handle, void *data) { timeOut = NULL; - printf("Timeout is exceeded %p\n", data); + printf("Timeout exceeded %p\n", data); lueRemFd(ctxt, readFd); lueTerminate(ctxt); } static appTimeout(struct LUECtxt *ctxt, struct LUETimerH *handle, void *data) { - printf("Lifetime is exceeded %p\n", data); + printf("Lifetime exceeded %p\n", data); exit(1); } @@ -45,14 +65,14 @@ static int readCb(struct LUECtxt *ctxt, struct LUEFileEventH *handle, int fd, vo static writeThread(struct LUECtxt *ctxt, struct LUETimerH *handle, void *data) { - int cnt = (int) data; + int cnt = (int)(intptr_t)data; char *msg = "TESTING"; write(writeFd, msg, cnt); //printf("WRITE %.*s %d\n", cnt, msg, cnt); printf("%d ", cnt); fflush(stdout); period = cnt + 5; - lueAddTimer(ctxt, period * 100, writeThread, (void *) (cnt + 1)); + lueAddTimer(ctxt, period * 100, writeThread, (void *)(intptr_t)(cnt + 1)); } main() diff --git a/test.lua b/test.lua deleted file mode 100644 index 0786b89..0000000 --- a/test.lua +++ /dev/null @@ -1,76 +0,0 @@ -#!/usr/bin/env lua ---/usr/bin/env luajit ---- --- @file --- Micro event library libuevent. --- Test & showcase of libuevent --- --- (C) Copyright 2012 flemming.madsen at madsensoft.dk. See libuevent.h ---- -require "socket" -require "luevent" - -local ADDR = "127.0.0.1" -local PORT = 42555 -local timer -local period -local appTimer, readHdl, writeTimer - -local function timeOut() - print("Timeout is exceeded") - appTimer:clear() - readHdl:clear() - writeTimer:clear() - luevent.terminate() -end - -local function writeThread(sck, cnt) - sck:send(("TESTING"):sub(1, cnt)) - period = cnt + 5 - writeTimer = luevent.addTimer(100 * period, function() writeThread(sck, cnt + 1) end) -end - -local function main() - appTimer = luevent.addTimer(5000, function() - print("Lifetime is exceeded") - os.exit(1); - end) - - local isrv = assert(socket.bind(ADDR, PORT)) - luevent.addFileIO(isrv:getfd(), function(self) - local isock = isrv:accept() - isock:settimeout(0) - readHdl = luevent.addFileIO(isock:getfd(), function(self) - -- Pipe readable - if timer then - timer:clear() - timer = luevent.addTimer(950, timeOut) - end - local str, err, prt = isock:receive(50) - if not str and err == "timeout" then str = prt end - io.write(str.."."..#str.." ") io.flush() - end) - - self:clear() -- This is a oneshot - end) - timer = luevent.addTimer(950, timeOut) - - local osck = socket.tcp() osck:settimeout(0) osck:connect(ADDR, PORT) - luevent.addFileIO(osck:getfd(), function(self) - writeThread(osck, 1) - self:clear() -- This is a oneshot - end, "w") - - luevent.run() - print "DONE" - -- Only index '1' should be there now - for k,v in pairs(luevent._lue_objects) do print(k,v) end - - package.loaded.luevent = nil - collectgarbage("collect") - print(("Period is %d must be 10: %s"):format(period, 10 == period and "OK" or "ERROR!")) - os.exit(period == 10 and 0 or 1) -end - -main() --- vim: set sw=3 sts=3 et nu: