diff options
author | Waqas Hussain <waqas20@gmail.com> | 2013-10-30 17:44:42 -0400 |
---|---|---|
committer | Waqas Hussain <waqas20@gmail.com> | 2013-10-30 17:44:42 -0400 |
commit | 495b904d7210537b53736f6fd2330a26527ce89c (patch) | |
tree | ff11c1b8dae686f95c1a2222bda607fd58b8ef9f /util/timer.lua | |
parent | 511f7a76a11199b7cd4d13c85f0703f3e7930e3c (diff) | |
download | prosody-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.lua | 58 |
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; |