Software /
code /
prosody
Comparison
util/timer.lua @ 11263:1274deeab39a 0.11
util.timer: Ensure timers can't run more than once per tick (fixes #1620)
See longer explanation in 2c559953ad41
author | Kim Alvefur <zash@zash.se> |
---|---|
date | Fri, 08 Jan 2021 23:23:56 +0100 |
parent | 9562:acf74ad0b795 |
child | 11264:2cdcf55c6dd5 |
comparison
equal
deleted
inserted
replaced
11262:2c559953ad41 | 11263:1274deeab39a |
---|---|
13 local type = type; | 13 local type = type; |
14 local debug_traceback = debug.traceback; | 14 local debug_traceback = debug.traceback; |
15 local tostring = tostring; | 15 local tostring = tostring; |
16 local xpcall = require "util.xpcall".xpcall; | 16 local xpcall = require "util.xpcall".xpcall; |
17 local math_max = math.max; | 17 local math_max = math.max; |
18 local pairs = pairs; | |
18 | 19 |
19 local _ENV = nil; | 20 local _ENV = nil; |
20 -- luacheck: std none | 21 -- luacheck: std none |
21 | 22 |
22 local _add_task = server.add_task; | 23 local _add_task = server.add_task; |
27 local params = {}; | 28 local params = {}; |
28 local next_time = nil; | 29 local next_time = nil; |
29 local function _traceback_handler(err) log("error", "Traceback[timer]: %s", debug_traceback(tostring(err), 2)); end | 30 local function _traceback_handler(err) log("error", "Traceback[timer]: %s", debug_traceback(tostring(err), 2)); end |
30 local function _on_timer(now) | 31 local function _on_timer(now) |
31 local peek; | 32 local peek; |
33 local readd; | |
32 while true do | 34 while true do |
33 peek = h:peek(); | 35 peek = h:peek(); |
34 if peek == nil or peek > now then break; end | 36 if peek == nil or peek > now then break; end |
35 local _, callback, id = h:pop(); | 37 local _, callback, id = h:pop(); |
36 local param = params[id]; | 38 local param = params[id]; |
37 params[id] = nil; | 39 params[id] = nil; |
38 --item(now, id, _param); | 40 --item(now, id, _param); |
39 local success, err = xpcall(callback, _traceback_handler, now, id, param); | 41 local success, err = xpcall(callback, _traceback_handler, now, id, param); |
40 if success and type(err) == "number" then | 42 if success and type(err) == "number" then |
41 h:insert(callback, err + now, id); -- re-add | 43 if readd then |
44 readd[id] = { callback, err + now }; | |
45 else | |
46 readd = { [id] = { callback, err + now } }; | |
47 end | |
42 params[id] = param; | 48 params[id] = param; |
43 end | 49 end |
50 end | |
51 | |
52 if readd then | |
53 for id,timer in pairs(readd) do | |
54 h:insert(timer[1], timer[2], id); | |
55 end | |
56 peek = h:peek(); | |
44 end | 57 end |
45 | 58 |
46 if peek ~= nil and _active_timers > 1 and peek == next_time then | 59 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, | 60 -- 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 | 61 -- so it should be safe to not renew this timer event |