/* * gcsd * * gcsd the generic command sequencer daemon can be used to serialize * commands sent over various paralell communication channels to a * single command output. It can be seen as a multiplexer for any * kind of communication between a single resource and various clients * which want to submit commands to it or query information from it. * gcsd is written in C and Lua. The goal is to provide an easy to * understand high level API based on Lua which can be used to * implement the business logic of the so formed multiplexer daemon. * * * Copyright (C) 2009-2010 Markus Grueneis * Christian Pointner * * This file is part of gcsd. * * gcsd is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * gcsd is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with gcsd. If not, see . */ #include #include #include #include #include #include "l_timer.h" typedef struct timeval timer_t; #define LUA_TIMER_UDATA_NAME "timer_t" static int l_timer_add(lua_State *L); static int l_timer_sub(lua_State *L); static timer_t* newtimerudata(lua_State *L) { timer_t* tv = (timer_t*)lua_newuserdata(L, sizeof(timer_t)); if(luaL_newmetatable(L, LUA_TIMER_UDATA_NAME)) { lua_pushliteral(L, "__add"); lua_pushcfunction(L, l_timer_add); lua_settable(L, -3); lua_pushliteral(L, "__sub"); lua_pushcfunction(L, l_timer_sub); lua_settable(L, -3); } lua_setmetatable(L, -2); return tv; } static int l_timer_new(lua_State *L) { int ms = luaL_optint(L, 1, 0); timer_t* tv = newtimerudata(L); tv->tv_sec = ms/1000; tv->tv_usec = (ms%1000)*1000; return 1; } static int l_timer_now(lua_State *L) { timer_t* now = newtimerudata(L); int ret = gettimeofday(now, NULL); if(ret) { lua_pushnil(L); lua_pushstring(L, strerror(errno)); // FIXXXXXME: strerror is not threadsafe!!! return 2; } return 1; } static int l_timer_add(lua_State *L) { timer_t* a = (timer_t*)luaL_checkudata(L, 1, LUA_TIMER_UDATA_NAME); timer_t* b = (timer_t*)luaL_checkudata(L, 2, LUA_TIMER_UDATA_NAME); timer_t* res = newtimerudata(L); timeradd(a, b, res); return 1; } static int l_timer_sub(lua_State *L) { timer_t* a = (timer_t*)luaL_checkudata(L, 1, LUA_TIMER_UDATA_NAME); timer_t* b = (timer_t*)luaL_checkudata(L, 2, LUA_TIMER_UDATA_NAME); timer_t* res = newtimerudata(L); timersub(a, b, res); return 1; } static int l_timer_cmp(lua_State *L) { timer_t* a = (timer_t*)luaL_checkudata(L, 1, LUA_TIMER_UDATA_NAME); timer_t* b = (timer_t*)luaL_checkudata(L, 2, LUA_TIMER_UDATA_NAME); if(timercmp(a, b, <)) lua_pushinteger(L, -1); else if(timercmp(a, b, >)) lua_pushinteger(L, 1); else lua_pushinteger(L, 0); return 1; } static const struct luaL_Reg timer_funcs [] = { { "new", l_timer_new }, { "now", l_timer_now }, { "add", l_timer_add }, { "sub", l_timer_sub }, { "cmp", l_timer_cmp }, { NULL, NULL } }; LUALIB_API int luaopen_timer(lua_State *L) { #if LUA_VERSION_NUM > 501 lua_newtable(L); luaL_setfuncs(L, timer_funcs, 0); lua_pushvalue(L, -1); lua_setglobal(L, LUA_TIMERLIBNAME); #else luaL_register(L, LUA_TIMERLIBNAME, timer_funcs); #endif return 1; }