2 -- Copyright (C) 2008-2010 Matthew Wild
3 -- Copyright (C) 2008-2010 Waqas Hussain
5 -- This project is MIT/X11 licensed. Please see the
6 -- COPYING file in the source package for more information.
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
"util.time".now
14 local debug_traceback
= debug
.traceback
;
15 local tostring = tostring;
16 local xpcall
= require
"util.xpcall".xpcall
;
17 local math_max
= math
.max;
22 local _add_task
= server
.add_task
;
25 local _active_timers
= 0;
26 local h
= indexedbheap
.create();
28 local next_time
= nil;
29 local function _traceback_handler(err
) log("error", "Traceback[timer]: %s", debug_traceback(tostring(err
), 2)); end
30 local function _on_timer(now
)
34 if peek
== nil or peek
> now
then break; end
35 local _
, callback
, id
= h
:pop();
36 local param
= params
[id
];
38 --item(now, id, _param);
39 local success
, err
= xpcall(callback
, _traceback_handler
, now
, id
, param
);
40 if success
and type(err
) == "number" then
41 h
:insert(callback
, err
+ now
, id
); -- re-add
46 if peek
~= nil and _active_timers
> 1 and peek
== next_time
then
47 -- Another instance of _on_timer already set next_time to the same value,
48 -- so it should be safe to not renew this timer event
55 -- peek is the time of the next event
58 _active_timers
= _active_timers
- 1;
60 local function add_task(delay
, callback
, param
)
61 local current_time
= get_time();
62 local event_time
= current_time
+ delay
;
64 local id
= h
:insert(callback
, event_time
);
66 if next_time
== nil or event_time
< next_time
then
67 next_time
= event_time
;
69 _server_timer
:close();
72 _active_timers
= _active_timers
+ 1;
74 _server_timer
= _add_task(next_time
- current_time
, _on_timer
);
78 local function stop(id
)
80 local result
, item
, result_sync
= h
:remove(id
);
81 local peek
= h
:peek();
82 if peek
~= next_time
and _server_timer
then
84 _server_timer
:close();
85 if next_time
~= nil then
86 _server_timer
= _add_task(math_max(next_time
- get_time(), 0), _on_timer
);
89 return result
, item
, result_sync
;
91 local function reschedule(id
, delay
)
92 local current_time
= get_time();
93 local event_time
= current_time
+ delay
;
94 h
:reprioritize(id
, delay
);
95 if next_time
== nil or event_time
< next_time
then
96 next_time
= event_time
;
97 _add_task(next_time
- current_time
, _on_timer
);
105 reschedule
= reschedule
;