mirror of
https://github.com/troglobit/libuev.git
synced 2026-10-07 15:54:07 +07:00
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 <troglobit@gmail.com>
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
libuev.a
|
||||
libuev.o
|
||||
libuev.so.1
|
||||
test
|
||||
@@ -0,0 +1,2 @@
|
||||
Flemming Madsen <flemming!madsen()madsensoft!dk>
|
||||
Joachim Nilsson <troglobit()gmail!com>
|
||||
@@ -0,0 +1,21 @@
|
||||
Copyright (c) 2012 Flemming Madsen <flemming!madsen()madsensoft!dk>
|
||||
Copyright (c) 2013 Joachim Nilsson <troglobit()gmail!com>
|
||||
|
||||
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.
|
||||
@@ -1,47 +1,64 @@
|
||||
##
|
||||
# @file Makefile
|
||||
# Make the micro eventlib, lua bindings and tests
|
||||
# -*-Makefile-*- for libuev
|
||||
#
|
||||
# $Id$
|
||||
# Copyright (c) 2012 Flemming Madsen <flemming!madsen()madsensoft!dk>
|
||||
# Copyright (c) 2013 Joachim Nilsson <troglobit()gmail!com>
|
||||
#
|
||||
# (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
|
||||
|
||||
@@ -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
|
||||
|
||||
<!-- vim: set syntax=mkd textwidth=79 nofoldenable: -->
|
||||
|
||||
@@ -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.
|
||||
|
||||
+31
-15
@@ -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 <flemming!madsen()madsensoft!dk>
|
||||
* Copyright (c) 2013 Joachim Nilsson <troglobit()gmail!com>
|
||||
*
|
||||
* 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 <assert.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <poll.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <stdbool.h>
|
||||
#include <sys/times.h>
|
||||
#include <fcntl.h>
|
||||
#include <time.h>
|
||||
#include <poll.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "llist.h"
|
||||
#include "libuevent.h"
|
||||
#include "libuev.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
#define Debug(f, args...) printf(":LUE: " f "\n", ##args)
|
||||
@@ -0,0 +1,68 @@
|
||||
/* libuev - Asynchronous event loop library
|
||||
*
|
||||
* Copyright (c) 2012 Flemming Madsen <flemming!madsen()madsensoft!dk>
|
||||
* Copyright (c) 2013 Joachim Nilsson <troglobit()gmail!com>
|
||||
*
|
||||
* 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:
|
||||
-75
@@ -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.
|
||||
******************************************************************************/
|
||||
|
||||
@@ -1,419 +0,0 @@
|
||||
/**
|
||||
* @file
|
||||
* Lua binding to libuevent
|
||||
* $Id:$
|
||||
*
|
||||
* (C) Copyright 2012 flemming.madsen at madsensoft.dk. See libuevent.h
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
#include <assert.h>
|
||||
#include <lua.h>
|
||||
#include <lauxlib.h>
|
||||
#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".
|
||||
* <br> 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 <pre>
|
||||
* local hdl<br>
|
||||
* hdl = luevent.addTimer(50, function() hdl = nil xxx end)<br>
|
||||
* ......<br>
|
||||
* if hdl then hdl:clear() hdl = nil end<br>
|
||||
* </pre>
|
||||
* Here <tt>hdl</tt> 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:
|
||||
@@ -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 <flemming!madsen()madsensoft!dk>
|
||||
* Copyright (c) 2013 Joachim Nilsson <troglobit()gmail!com>
|
||||
*
|
||||
* 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 <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "libuevent.h"
|
||||
#include <unistd.h> /* 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()
|
||||
|
||||
@@ -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:
|
||||
Reference in New Issue
Block a user