summaryrefslogtreecommitdiff
path: root/builtin/common/after.lua
blob: 30a9c7badbe21d652e55699e5454c9aaede629da (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
local jobs = {}
local time = 0.0
local last = core.get_us_time() / 1000000

core.register_globalstep(function(dtime)
	local new = core.get_us_time() / 1000000
	if new > last then
		time = time + (new - last)
	else
		-- Overflow, we may lose a little bit of time here but
		-- only 1 tick max, potentially running timers slightly
		-- too early.
		time = time + new
	end
	last = new

	if #jobs < 1 then
		return
	end

	-- 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.
	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)
		end
	end
end)

function core.after(after, func, ...)
	assert(tonumber(after) and type(func) == "function",
		"Invalid core.after invocation")
	jobs[#jobs + 1] = {
		func = func,
		expire = time + after,
		arg = {...},
		mod_origin = core.get_last_run_mod()
	}
end