X-Git-Url: https://git.enpas.org/?a=blobdiff_plain;f=util%2Ftimer.lua;h=2277ee77b5025707cb0ce199a3071fa88b7f53bd;hb=b244d865c10f013995fa3615cd9ddc019c352d55;hp=23bd6a37d592da8b47180d2645784841d7df18cc;hpb=95dfe4b0aaaf26ee4651c09eb9757c56210a135a;p=prosody.git diff --git a/util/timer.lua b/util/timer.lua index 23bd6a37..2277ee77 100644 --- a/util/timer.lua +++ b/util/timer.lua @@ -9,82 +9,18 @@ local indexedbheap = require "util.indexedbheap"; local log = require "util.logger".init("timer"); local server = require "net.server"; -local math_min = math.min -local math_huge = math.huge local get_time = require "socket".gettime; -local t_insert = table.insert; -local pairs = pairs; local type = type; local debug_traceback = debug.traceback; local tostring = tostring; local xpcall = xpcall; -local data = {}; -local new_data = {}; +local _ENV = nil; -module "timer" - -local _add_task; -if not server.event then - function _add_task(delay, callback) - local current_time = get_time(); - delay = delay + current_time; - if delay >= current_time then - t_insert(new_data, {delay, callback}); - else - local r = callback(current_time); - if r and type(r) == "number" then - return _add_task(r, callback); - end - end - end - - server._addtimer(function() - local current_time = get_time(); - if #new_data > 0 then - for _, d in pairs(new_data) do - t_insert(data, d); - end - new_data = {}; - end - - local next_time = math_huge; - for i, d in pairs(data) do - local t, callback = d[1], d[2]; - if t <= current_time then - data[i] = nil; - local r = callback(current_time); - if type(r) == "number" then - _add_task(r, callback); - next_time = math_min(next_time, r); - end - else - next_time = math_min(next_time, t - current_time); - end - end - return next_time; - end); -else - local event = server.event; - local event_base = server.event_base; - local EVENT_LEAVE = (event.core and event.core.LEAVE) or -1; - - function _add_task(delay, callback) - local event_handle; - event_handle = event_base:addevent(nil, 0, function () - local ret = callback(get_time()); - if ret then - return 0, ret; - elseif event_handle then - return EVENT_LEAVE; - end - end - , delay); - end -end - ---add_task = _add_task; +local _add_task = server.add_task; +local _server_timer; +local _active_timers = 0; local h = indexedbheap.create(); local params = {}; local next_time = nil; @@ -108,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; @@ -121,15 +67,30 @@ 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); + local result, item, result_sync = h:remove(id); + local peek = h:peek(); + if peek ~= next_time and _server_timer then + next_time = peek; + _server_timer:close(); + if next_time ~= nil then + _server_timer = _add_task(next_time - get_time(), _on_timer); + end + end + return result, item, result_sync; 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); @@ -140,4 +101,9 @@ function reschedule(id, delay) return id; end -return _M; +return { + add_task = add_task; + stop = stop; + reschedule = reschedule; +}; +