|
1 -- Prosody IM |
|
2 -- Copyright (C) 2008-2010 Matthew Wild |
|
3 -- Copyright (C) 2008-2010 Waqas Hussain |
|
4 -- |
|
5 -- This project is MIT/X11 licensed. Please see the |
|
6 -- COPYING file in the source package for more information. |
|
7 -- |
|
8 |
|
9 local indexedbheap = require "util.indexedbheap"; |
|
10 local log = require "util.logger".init("timer"); |
|
11 local server = require "net.server"; |
|
12 local get_time = require "socket".gettime; |
|
13 local type = type; |
|
14 local debug_traceback = debug.traceback; |
|
15 local tostring = tostring; |
|
16 local xpcall = xpcall; |
|
17 |
|
18 module "timer" |
|
19 |
|
20 local _add_task = server.add_task; |
|
21 --add_task = _add_task; |
|
22 |
|
23 local h = indexedbheap.create(); |
|
24 local params = {}; |
|
25 local next_time = nil; |
|
26 local _id, _callback, _now, _param; |
|
27 local function _call() return _callback(_now, _id, _param); end |
|
28 local function _traceback_handler(err) log("error", "Traceback[timer]: %s", debug_traceback(tostring(err), 2)); end |
|
29 local function _on_timer(now) |
|
30 local peek; |
|
31 while true do |
|
32 peek = h:peek(); |
|
33 if peek == nil or peek > now then break; end |
|
34 local _; |
|
35 _, _callback, _id = h:pop(); |
|
36 _now = now; |
|
37 _param = params[_id]; |
|
38 params[_id] = nil; |
|
39 --item(now, id, _param); -- FIXME pcall |
|
40 local success, err = xpcall(_call, _traceback_handler); |
|
41 if success and type(err) == "number" then |
|
42 h:insert(_callback, err + now, _id); -- re-add |
|
43 params[_id] = _param; |
|
44 end |
|
45 end |
|
46 next_time = peek; |
|
47 if peek ~= nil then |
|
48 return peek - now; |
|
49 end |
|
50 end |
|
51 function add_task(delay, callback, param) |
|
52 local current_time = get_time(); |
|
53 local event_time = current_time + delay; |
|
54 |
|
55 local id = h:insert(callback, event_time); |
|
56 params[id] = param; |
|
57 if next_time == nil or event_time < next_time then |
|
58 next_time = event_time; |
|
59 _add_task(next_time - current_time, _on_timer); |
|
60 end |
|
61 return id; |
|
62 end |
|
63 function stop(id) |
|
64 params[id] = nil; |
|
65 return h:remove(id); |
|
66 end |
|
67 function reschedule(id, delay) |
|
68 local current_time = get_time(); |
|
69 local event_time = current_time + delay; |
|
70 h:reprioritize(id, delay); |
|
71 if next_time == nil or event_time < next_time then |
|
72 next_time = event_time; |
|
73 _add_task(next_time - current_time, _on_timer); |
|
74 end |
|
75 return id; |
|
76 end |
|
77 |
|
78 return _M; |