Merge 0.10->trunk
[prosody.git] / util / timer.lua
index 0ec9758588560885364696fa4089a2a56fc1f013..eb2bd7eab0ad26bd2b71983109ebccce34641fe4 100644 (file)
@@ -15,11 +15,12 @@ local debug_traceback = debug.traceback;
 local tostring = tostring;
 local xpcall = xpcall;
 
-module "timer"
+local _ENV = nil;
 
 local _add_task = server.add_task;
---add_task = _add_task;
 
+local _server_timer;
+local _active_timers = 0;
 local h = indexedbheap.create();
 local params = {};
 local next_time = nil;
@@ -43,12 +44,22 @@ local function _on_timer(now)
                        params[_id] = _param;
                end
        end
-       next_time = peek;
-       if peek ~= nil then
+
+       if peek ~= nil and _active_timers > 1 and peek == next_time then
+               -- Another instance of _on_timer already set next_time to the same value,
+               -- so it should be safe to not renew this timer event
+               peek = nil;
+       else
+               next_time = peek;
+       end
+
+       if peek then
+               -- peek is the time of the next event
                return peek - now;
        end
+       _active_timers = _active_timers - 1;
 end
-function add_task(delay, callback, param)
+local function add_task(delay, callback, param)
        local current_time = get_time();
        local event_time = current_time + delay;
 
@@ -56,15 +67,21 @@ function add_task(delay, callback, param)
        params[id] = param;
        if next_time == nil or event_time < next_time then
                next_time = event_time;
-               _add_task(next_time - current_time, _on_timer);
+               if _server_timer then
+                       _server_timer:close();
+                       _server_timer = nil;
+               else
+                       _active_timers = _active_timers + 1;
+               end
+               _server_timer = _add_task(next_time - current_time, _on_timer);
        end
        return id;
 end
-function stop(id)
+local function stop(id)
        params[id] = nil;
        return h:remove(id);
 end
-function reschedule(id, delay)
+local function reschedule(id, delay)
        local current_time = get_time();
        local event_time = current_time + delay;
        h:reprioritize(id, delay);
@@ -75,4 +92,9 @@ function reschedule(id, delay)
        return id;
 end
 
-return _M;
+return {
+       add_task = add_task;
+       stop = stop;
+       reschedule = reschedule;
+};
+