aboutsummaryrefslogtreecommitdiffstats
path: root/util/timer.lua
diff options
context:
space:
mode:
authorWaqas Hussain <waqas20@gmail.com>2013-10-30 17:44:42 -0400
committerWaqas Hussain <waqas20@gmail.com>2013-10-30 17:44:42 -0400
commit495b904d7210537b53736f6fd2330a26527ce89c (patch)
treeff11c1b8dae686f95c1a2222bda607fd58b8ef9f /util/timer.lua
parent511f7a76a11199b7cd4d13c85f0703f3e7930e3c (diff)
downloadprosody-495b904d7210537b53736f6fd2330a26527ce89c.tar.gz
prosody-495b904d7210537b53736f6fd2330a26527ce89c.zip
util.timer: Updated to use util.indexedbheap to provide a more complete API. Timers can now be stopped or rescheduled. Callbacks are now pcall'd. Adding/removing timers from within timer callbacks works better. Optional parameter can be passed when creating timer which gets passed to callback, eliminating the need for closures in various timer uses. Timers are now much more lightweight.
Diffstat (limited to 'util/timer.lua')
-rw-r--r--util/timer.lua58
1 files changed, 57 insertions, 1 deletions
diff --git a/util/timer.lua b/util/timer.lua
index 0e10e144..d7a9b0bf 100644
--- a/util/timer.lua
+++ b/util/timer.lua
@@ -6,6 +6,8 @@
-- COPYING file in the source package for more information.
--
+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
@@ -78,6 +80,60 @@ else
end
end
-add_task = _add_task;
+--add_task = _add_task;
+
+local h = indexedbheap.create();
+local params = {};
+local next_time = nil;
+local _id, _callback, _now, _param;
+local function _call() return _callback(_now, _id, _param); end
+local function _traceback_handler(err) log("error", "Traceback[timer]: %s", traceback(tostring(err), 2)); end
+local function _on_timer(now)
+ local peek;
+ while true do
+ peek = h:peek();
+ if peek == nil or peek > now then break; end
+ local _;
+ _, _callback, _id = h:pop();
+ _now = now;
+ _param = params[id];
+ params[id] = nil;
+ --item(now, id, _param); -- FIXME pcall
+ local success, err = xpcall(_call, _traceback_handler);
+ if success and type(err) == "number" then
+ h:insert(_callback, err + now, _id); -- re-add
+ end
+ end
+ next_time = peek;
+ if peek ~= nil then
+ return peek - now;
+ end
+end
+function add_task(delay, callback, param)
+ local current_time = get_time();
+ local event_time = current_time + delay;
+
+ local id = h:insert(callback, event_time);
+ 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);
+ end
+ return id;
+end
+function stop(id)
+ params[id] = nil;
+ return h:remove(id);
+end
+function reschedule(id, delay)
+ local current_time = get_time();
+ local event_time = current_time + delay;
+ h:reprioritize(id, delay);
+ if next_time == nil or event_time < next_time then
+ next_time = event_time;
+ _add_task(next_time - current_time, on_timer);
+ end
+ return id;
+end
return _M;