-
Notifications
You must be signed in to change notification settings - Fork 15
Expand file tree
/
Copy pathtimer.lua
More file actions
101 lines (87 loc) · 2.17 KB
/
timer.lua
File metadata and controls
101 lines (87 loc) · 2.17 KB
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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
local timers = {}
local tbinsert = table.insert
local tbremove = table.remove
local ipairs = ipairs
local xpcall = xpcall
local traceback = debug.traceback
local co_create = coroutine.create
local co_running = coroutine.running
local co_resume = coroutine.resume
local co_yield = coroutine.yield
---you can replace this with your clock function
local clock = os.clock
local function insert_timer(sec, fn)
local expiretime = clock() + sec
local pos = 1
for i, v in ipairs(timers) do
if v.expiretime > expiretime then
break
end
pos = i+1
end
local context = { expiretime =expiretime, fn = fn}
tbinsert(timers, pos, context)
return context
end
local co_pool = setmetatable({}, {__mode = "kv"})
local function coresume(co, ...)
local ok, err = co_resume(co, ...)
if not ok then
error(traceback(co, err))
end
return ok, err
end
local function routine(fn)
local co = co_running()
while true do
fn()
co_pool[#co_pool + 1] = co
fn = co_yield()
end
end
local M = {}
function M.async(fn)
local co = tbremove(co_pool)
if not co then
co = co_create(routine)
end
local _, res = coresume(co, fn)
if res then
return res
end
return co
end
---@param seconds integer @duration in seconds,decimal part means millseconds
---@param fn function @ timeout callback
function M.timeout(seconds, fn)
return insert_timer(seconds, fn)
end
---coroutine style
---@param seconds integer @duration in seconds,decimal part means millseconds
function M.sleep(seconds)
local co = co_running()
insert_timer(seconds, function()
co_resume(co)
end)
return co_yield()
end
function M.remove(ctx)
ctx.remove = true
end
function M.update()
while #timers >0 do
local timer = timers[1]
if timer.expiretime <= clock() then
tbremove(timers,1)
if not timer.remove then
local ok, err = xpcall(timer.fn, traceback)
if not ok then
print("timer error:", err)
end
end
else
break
end
end
end
return M