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