Optimize core.after in a simple way (#8351)
authorDS <vorunbekannt75@web.de>
Wed, 27 Mar 2019 20:05:50 +0000 (21:05 +0100)
committersfan5 <sfan5@live.de>
Wed, 27 Mar 2019 20:05:50 +0000 (21:05 +0100)
builtin/common/after.lua

index 1bed2d31f48d8616b700b458076c7f1b0d06624b..b314711c9827185cddc3260dae67cf4052364a72 100644 (file)
@@ -1,22 +1,28 @@
 local jobs = {}
 local time = 0.0
+local time_next = math.huge
 
 core.register_globalstep(function(dtime)
        time = time + dtime
 
-       if #jobs < 1 then
+       if time < time_next then
                return
        end
 
+       time_next = math.huge
+
        -- Iterate backwards so that we miss any new timers added by
-       -- a timer callback, and so that we don't skip the next timer
-       -- in the list if we remove one.
+       -- a timer callback.
        for i = #jobs, 1, -1 do
                local job = jobs[i]
                if time >= job.expire then
                        core.set_last_run_mod(job.mod_origin)
                        job.func(unpack(job.arg))
-                       table.remove(jobs, i)
+                       local jobs_l = #jobs
+                       jobs[i] = jobs[jobs_l]
+                       jobs[jobs_l] = nil
+               elseif job.expire < time_next then
+                       time_next = job.expire
                end
        end
 end)
@@ -24,10 +30,12 @@ end)
 function core.after(after, func, ...)
        assert(tonumber(after) and type(func) == "function",
                "Invalid minetest.after invocation")
+       local expire = time + after
        jobs[#jobs + 1] = {
                func = func,
-               expire = time + after,
+               expire = expire,
                arg = {...},
                mod_origin = core.get_last_run_mod()
        }
+       time_next = math.min(time_next, expire)
 end