Mercurial > prosody-hg
comparison util/timer.lua @ 6609:d2faaaca695d
Merge 0.10->trunk
| author | Matthew Wild <mwild1@gmail.com> |
|---|---|
| date | Fri, 27 Mar 2015 22:24:57 +0000 |
| parents | dbc72cd1332e |
| children | e813e8cf6046 |
comparison
equal
deleted
inserted
replaced
| 6608:b6e558febb7a | 6609:d2faaaca695d |
|---|---|
| 4 -- | 4 -- |
| 5 -- This project is MIT/X11 licensed. Please see the | 5 -- This project is MIT/X11 licensed. Please see the |
| 6 -- COPYING file in the source package for more information. | 6 -- COPYING file in the source package for more information. |
| 7 -- | 7 -- |
| 8 | 8 |
| 9 local indexedbheap = require "util.indexedbheap"; | |
| 10 local log = require "util.logger".init("timer"); | |
| 9 local server = require "net.server"; | 11 local server = require "net.server"; |
| 10 local math_min = math.min | |
| 11 local math_huge = math.huge | |
| 12 local get_time = require "socket".gettime; | 12 local get_time = require "socket".gettime; |
| 13 local t_insert = table.insert; | |
| 14 local pairs = pairs; | |
| 15 local type = type; | 13 local type = type; |
| 16 | 14 local debug_traceback = debug.traceback; |
| 17 local data = {}; | 15 local tostring = tostring; |
| 18 local new_data = {}; | 16 local xpcall = xpcall; |
| 19 | 17 |
| 20 module "timer" | 18 module "timer" |
| 21 | 19 |
| 22 local _add_task; | 20 local _add_task = server.add_task; |
| 23 if not server.event then | 21 --add_task = _add_task; |
| 24 function _add_task(delay, callback) | 22 |
| 25 local current_time = get_time(); | 23 local h = indexedbheap.create(); |
| 26 delay = delay + current_time; | 24 local params = {}; |
| 27 if delay >= current_time then | 25 local next_time = nil; |
| 28 t_insert(new_data, {delay, callback}); | 26 local _id, _callback, _now, _param; |
| 29 else | 27 local function _call() return _callback(_now, _id, _param); end |
| 30 local r = callback(current_time); | 28 local function _traceback_handler(err) log("error", "Traceback[timer]: %s", debug_traceback(tostring(err), 2)); end |
| 31 if r and type(r) == "number" then | 29 local function _on_timer(now) |
| 32 return _add_task(r, callback); | 30 local peek; |
| 33 end | 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; | |
| 34 end | 44 end |
| 35 end | 45 end |
| 36 | 46 next_time = peek; |
| 37 server._addtimer(function() | 47 if peek ~= nil then |
| 38 local current_time = get_time(); | 48 return peek - now; |
| 39 if #new_data > 0 then | |
| 40 for _, d in pairs(new_data) do | |
| 41 t_insert(data, d); | |
| 42 end | |
| 43 new_data = {}; | |
| 44 end | |
| 45 | |
| 46 local next_time = math_huge; | |
| 47 for i, d in pairs(data) do | |
| 48 local t, callback = d[1], d[2]; | |
| 49 if t <= current_time then | |
| 50 data[i] = nil; | |
| 51 local r = callback(current_time); | |
| 52 if type(r) == "number" then | |
| 53 _add_task(r, callback); | |
| 54 next_time = math_min(next_time, r); | |
| 55 end | |
| 56 else | |
| 57 next_time = math_min(next_time, t - current_time); | |
| 58 end | |
| 59 end | |
| 60 return next_time; | |
| 61 end); | |
| 62 else | |
| 63 local event = server.event; | |
| 64 local event_base = server.event_base; | |
| 65 local EVENT_LEAVE = (event.core and event.core.LEAVE) or -1; | |
| 66 | |
| 67 function _add_task(delay, callback) | |
| 68 local event_handle; | |
| 69 event_handle = event_base:addevent(nil, 0, function () | |
| 70 local ret = callback(get_time()); | |
| 71 if ret then | |
| 72 return 0, ret; | |
| 73 elseif event_handle then | |
| 74 return EVENT_LEAVE; | |
| 75 end | |
| 76 end | |
| 77 , delay); | |
| 78 end | 49 end |
| 79 end | 50 end |
| 51 function add_task(delay, callback, param) | |
| 52 local current_time = get_time(); | |
| 53 local event_time = current_time + delay; | |
| 80 | 54 |
| 81 add_task = _add_task; | 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 | |
| 82 | 77 |
| 83 return _M; | 78 return _M; |
