From c54533bbb20483941cef7f975d22ccbed3af765d Mon Sep 17 00:00:00 2001 From: bol-van Date: Mon, 22 Jun 2026 19:45:43 +0300 Subject: [PATCH] nfqws2: accept string or function in timer_set() --- docs/changes.txt | 4 ++++ docs/manual.en.md | 4 ++-- docs/manual.md | 4 ++-- lua/zapret-tests.lua | 12 ++++++++++-- nfq2/lua.c | 43 ++++++++++++++++++++++++++++++++++--------- nfq2/timer.c | 20 +++++--------------- nfq2/timer.h | 4 ++-- 7 files changed, 59 insertions(+), 32 deletions(-) diff --git a/docs/changes.txt b/docs/changes.txt index f3b95b4..11ff6bd 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -307,3 +307,7 @@ v0.9.4.3 1.0.2 * nfqws2: fix 60 msec lua-gc default to 60 sec + +1.0.3 + +* nfqws2: accept string or function in timer_set(). remember function as a function, not as a string. diff --git a/docs/manual.en.md b/docs/manual.en.md index ed6a2b8..32b2779 100644 --- a/docs/manual.en.md +++ b/docs/manual.en.md @@ -2424,7 +2424,7 @@ function timer_set(name, func, period, oneshot, data) ``` * name - a unique timer name. If a timer with this name already exists, it is deleted and replaced with a new one. When replaced, the countdown restarts. -* func - the timer function name (string) +* func - the timer function. string or function. if it's a string function is resolved during timer_set call and remembered as a function, not as a string. * period - the timer call frequency in milliseconds * oneshot - a bool indicating whether the timer is single-shot (true) or periodic (false) * data - an arbitrary variable passed to the [timer-function](#timer-function-prototype) @@ -2451,7 +2451,7 @@ Returns table in case of success, nil otherwise. | Field | Type | Description | | :------ | :----- | :------------------ | | name | string | unique timer name | -| func | string | timer function name | +| func | function | timer function | | oneshot | bool | true = single shot timer, false = periodic timer | | period | number | timer period in msec | | fires | number | number of timer calls made | diff --git a/docs/manual.md b/docs/manual.md index 9acd03d..72299d1 100644 --- a/docs/manual.md +++ b/docs/manual.md @@ -2584,7 +2584,7 @@ function timer_set(name, func, period, oneshot, data) ``` * name - уникальное имя таймера. если таймер с таким именем уже есть, он удаляется и замещается новым. При замещении отсчет времени начинается заново. -* func - имя таймер функции (string) +* func - таймер функция. string или function. в случае string функция ищется по имени в момент вызова timer_set и запоминается по ссылке, а не как строка. * period - периодичность вызова таймера в миллисекундах * oneshot - bool признак является ли таймер однократным (true) или периодическим (false) * data - произвольная переменная, передаваемая [таймер-функции](#прототип-функции-таймера) @@ -2611,7 +2611,7 @@ function timer_info(name) | Поле | Тип | Описание | | :------ | :----- | :------------------ | | name | string | уникальное имя таймера | -| func | string | имя таймер функции | +| func | function | таймер функция | | oneshot | bool | true = однократный таймер, false = периодический | | period | number | период таймера в мсек | | fires | number | количество выполненных вызовов таймера | diff --git a/lua/zapret-tests.lua b/lua/zapret-tests.lua index e19c175..6690c05 100644 --- a/lua/zapret-tests.lua +++ b/lua/zapret-tests.lua @@ -914,7 +914,6 @@ function print_current_time() end function timer_info_print(tinfo) print(" timer_info.name="..tinfo.name) - print(" timer_info.func="..tinfo.func) print(" timer_info.period="..tinfo.period) print(" timer_info.oneshot="..tostring(tinfo.oneshot)) print(" timer_info.fires="..tinfo.fires) @@ -939,8 +938,17 @@ function timer2(name, data) end end function test_timer(opts) - timer_set("t1","timer1",500,true,"sample_data"); + -- anonymous function + timer_set("t0",function(name,data) + print("timer "..name.." fired. anonymous timer function") + print_current_time() + end, + 100,true) + + -- pass function as function + timer_set("t1",timer1,500,true,"sample_data"); local tbl = {n=0} + -- pass function through string name timer_set("t2","timer2",700,false,tbl); print("* timers\n") diff --git a/nfq2/lua.c b/nfq2/lua.c index 9d8e453..3fe1845 100644 --- a/nfq2/lua.c +++ b/nfq2/lua.c @@ -3795,16 +3795,31 @@ static int luacall_timer_set(lua_State *L) LUA_STACK_GUARD_ENTER(L) int argc=lua_gettop(L); + const char *name = luaL_checkstring(L,1); - const char *func = luaL_checkstring(L,2); lua_Integer period = luaL_checkinteger(L,3); if (period<10) luaL_error(L,"invalid timer period. must be >=10 ms"); + bool oneshot = argc>=4 && lua_toboolean(L,4); - lua_getglobal(L, func); - bool is_f = lua_isfunction(L, -1); - lua_pop(L, 1); - if (!is_f) luaL_error(L, "timer function '%s' does not exist", func); + const char *func; + switch(lua_type(L,2)) + { + case LUA_TSTRING: + func = lua_tostring(L,2); + lua_getglobal(L, func); + if (!lua_isfunction(L, -1)) + { + lua_pop(L, 1); + luaL_error(L, "timer function '%s' does not exist", func); + } + break; + case LUA_TFUNCTION: + lua_pushvalue(L, 2); + break; + default: + luaL_error(L,"invalid timer function type"); + } const char *action; timer_pool *timer = TimerPoolSearch(params.timers, name); @@ -3816,15 +3831,20 @@ static int luacall_timer_set(lua_State *L) else action = "created"; - timer = TimerPoolAdd(¶ms.timers, name, func, period, oneshot); - if (!timer) luaL_error(L,"could not create timer"); + timer = TimerPoolAdd(¶ms.timers, name, period, oneshot); + if (!timer) + { + lua_pop(L, 1); + luaL_error(L,"could not create timer"); + } + timer->func_ref = luaL_ref(L, LUA_REGISTRYINDEX); if (argc>=5) { lua_pushvalue(L, 5); timer->lua_ref = luaL_ref(L, LUA_REGISTRYINDEX); } - DLOG("timer: '%s' %s. function '%s' period %llu oneshot %u\n", timer->str, action, timer->func, timer->period, timer->oneshot); + DLOG("timer: '%s' %s. period %llu oneshot %u\n", timer->str, action, timer->period, timer->oneshot); params.timers_dirty = true; LUA_STACK_GUARD_RETURN(L,0) @@ -3853,7 +3873,12 @@ static void lua_push_timer_info(lua_State *L, const timer_pool *timer) { lua_newtable(L); if (timer->str) lua_pushf_str(L, "name", timer->str); - if (timer->func) lua_pushf_str(L, "func", timer->func); + if (timer->func_ref!=LUA_NOREF) + { + lua_pushliteral(L, "func"); + lua_rawgeti(L, LUA_REGISTRYINDEX, timer->func_ref); + lua_rawset(L,-3); + } lua_pushf_lint(L, "period", timer->period); lua_pushf_bool(L, "oneshot", timer->oneshot); lua_pushf_lint(L, "fires", timer->fires); diff --git a/nfq2/timer.c b/nfq2/timer.c index ab44c1a..3f18ecc 100644 --- a/nfq2/timer.c +++ b/nfq2/timer.c @@ -19,8 +19,8 @@ static unsigned int timer_n=0; static void TimerPoolDestroyItem(timer_pool *elem) { free(elem->str); - free(elem->func); luaL_unref(params.L, LUA_REGISTRYINDEX, elem->lua_ref); + luaL_unref(params.L, LUA_REGISTRYINDEX, elem->func_ref); } void TimerPoolDel(timer_pool **pp, timer_pool *p) { @@ -39,15 +39,11 @@ struct timer_pool *TimerPoolSearch(timer_pool *p, const char *str) HASH_FIND_STR(p, str, elem_find); return elem_find; } -struct timer_pool *TimerPoolAdd(timer_pool **pp, const char *str, const char *func, uint64_t period, bool oneshot) +struct timer_pool *TimerPoolAdd(timer_pool **pp, const char *str, uint64_t period, bool oneshot) { ADD_STR_POOL(timer_pool, pp, str, strlen(str)) elem->lua_ref = LUA_NOREF; - if (!(elem->func = strdup(func))) - { - TimerPoolDel(pp,elem); - return NULL; - } + elem->func_ref = LUA_NOREF; elem->period = period; elem->oneshot = oneshot; elem->bt_next = boottime_ms() + elem->period; @@ -58,17 +54,11 @@ struct timer_pool *TimerPoolAdd(timer_pool **pp, const char *str, const char *fu static bool TimerPoolRunTimer(timer_pool *p) { - lua_getglobal(params.L, p->func); - if (!lua_isfunction(params.L, -1)) - { - lua_pop(params.L, 1); - DLOG_ERR("timer: '%s' function '%s' does not exist\n",p->str,p->func); - return false; - } + lua_rawgeti(params.L, LUA_REGISTRYINDEX, p->func_ref); lua_pushstring(params.L, p->str); lua_rawgeti(params.L, LUA_REGISTRYINDEX, p->lua_ref); p->fires++; - DLOG("\ntimer: '%s' function '%s' period %llu oneshot %u fires=%u\n",p->str,p->func,p->period,p->oneshot,p->fires); + DLOG("\ntimer: '%s' period %llu oneshot %u fires=%u\n",p->str,p->period,p->oneshot,p->fires); int status = lua_pcall(params.L, 2, 0, 0); if (status) { diff --git a/nfq2/timer.h b/nfq2/timer.h index eec336d..260c33d 100644 --- a/nfq2/timer.h +++ b/nfq2/timer.h @@ -7,7 +7,7 @@ typedef struct timer_pool { char *str; /* key */ - char *func; + int func_ref; uint64_t period; bool oneshot; int lua_ref; @@ -18,7 +18,7 @@ typedef struct timer_pool { void TimerPoolDestroy(timer_pool **pp); struct timer_pool *TimerPoolSearch(timer_pool *p, const char *str); -struct timer_pool *TimerPoolAdd(timer_pool **pp, const char *str, const char *func, uint64_t period, bool oneshot); +struct timer_pool *TimerPoolAdd(timer_pool **pp, const char *str, uint64_t period, bool oneshot); void TimerPoolDel(timer_pool **pp, timer_pool *p); // return next timer fire time uint64_t TimerPoolRun(timer_pool **pp, bool *dirty, uint64_t bt);