]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
daemon/bindings: event.reschedule(ev, timeout)
authorMarek Vavrusa <marek@vavrusa.com>
Thu, 26 May 2016 00:14:52 +0000 (17:14 -0700)
committerMarek Vavrusa <marek@vavrusa.com>
Wed, 6 Jul 2016 06:33:38 +0000 (23:33 -0700)
this allows for efficient variable-interval
running events, so that the timer doesn't have
to be closed and recreated for each iteration

daemon/README.rst
daemon/bindings.c

index 3e93b4e48a1f2168600e13436f5480f37f50fc4c..f4c640fbd6fb702505548ba1c265a214c4b4d135 100644 (file)
@@ -847,6 +847,24 @@ For example, ``5 * hour`` represents five hours, or 5*60*60*100 milliseconds.
                print('Hi #'..msg_count)
        end)
 
+.. function:: event.reschedule(event_id, timeout)
+
+   Reschedule a running event, it has no effect on canceled events.
+   New events may reuse the event_id, so the behaviour is undefined if the function
+   is called after another event is started.
+
+   Example:
+
+   .. code-block:: lua
+
+   local interval = 1 * minute
+   event.after(1 * minute, function (ev)
+      print('Good morning!')
+      -- Halven the interval for each iteration
+      interval = interval / 2
+      event.reschedule(ev, interval)
+   end)
+
 .. function:: event.cancel(event_id)
 
    Cancel running event, it has no effect on already canceled events.
index bc76147ac3ea4dbae18ac8a5116a1ea5632e5f47..28190a6f93b3137743f00a08ae691087439e0d26 100644 (file)
@@ -722,7 +722,7 @@ static void event_callback(uv_timer_t *timer)
        lua_pushinteger(L, (intptr_t) timer->data);
        int ret = execute_callback(L, 1);
        /* Free callback if not recurrent or an error */
-       if (ret != 0 || uv_timer_get_repeat(timer) == 0) {
+       if (ret != 0 || (uv_timer_get_repeat(timer) == 0 && uv_is_active((uv_handle_t *)timer) == 0)) {
                if (!uv_is_closing((uv_handle_t *)timer)) {
                        uv_close((uv_handle_t *)timer, (uv_close_cb) event_free);
                }
@@ -829,6 +829,39 @@ static int event_cancel(lua_State *L)
        return 1;
 }
 
+static int event_reschedule(lua_State *L)
+{
+       int n = lua_gettop(L);
+       if (n < 2 || !lua_isnumber(L, 1) || !lua_isnumber(L, 2)) {
+               format_error(L, "expected 'reschedule(number event, number timeout)'");
+               lua_error(L);
+       }
+
+       /* Fetch event if it exists */
+       lua_rawgeti(L, LUA_REGISTRYINDEX, lua_tointeger(L, 1));
+       if (!lua_istable(L, -1)) {
+               lua_pushboolean(L, false);
+               return 1;
+       }
+
+       /* Reschedule the timer */
+       lua_rawgeti(L, -1, 2);
+       uv_handle_t *timer = lua_touserdata(L, -1);
+       if (!uv_is_closing(timer)) {
+               if (uv_is_active(timer)) {
+                       uv_timer_stop((uv_timer_t *)timer);
+               }
+               int ret = uv_timer_start((uv_timer_t *)timer, event_callback, lua_tointeger(L, 2), 0);
+               if (ret != 0) {
+                       event_cancel(L);
+                       lua_pushboolean(L, false);
+                       return 1;
+               }
+       }
+       lua_pushboolean(L, true);
+       return 1;
+}
+
 static int event_fdwatch(lua_State *L)
 {
        /* Check parameters */
@@ -892,6 +925,7 @@ int lib_event(lua_State *L)
                { "recurrent",  event_recurrent },
                { "cancel",     event_cancel },
                { "socket",     event_fdwatch },
+               { "reschedule", event_reschedule },
                { NULL, NULL }
        };