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
|
local sys = require 'lx.sys'
local sysdef = require 'lx.sysdef'
local mainloop = {}
local fds = {}
local mainloop_must_exit = false
local mainloop_fds_change = false
function new_fd(fd, error_cb)
local fd = {
fd = fd,
error_cb = error_cb,
rd_expect = {},
wr_buf = "",
}
function fd:write(str)
-- TODO: try write immediately when possible
self.wr_buf = self.wr_buf .. str
end
function fd:expect(len, cb)
table.insert(self.rd_expect, {len, "", cb})
end
end
function mainloop.add_fd(fd, error_cb)
local fd = new_fd(fd, error_cb)
table.insert(fds, fd)
mainloop_fds_change = true
return fd
end
function mainloop.run()
mainloop_must_exit = false
sel_fds = {}
while not mainloop_must_exit do
local deadlock = true
for i, fd in pairs(fds) do
if mainloop_fds_change then
sel_fds[i] = {fd.fd}
end
local flags = sysdef.SEL_ERROR
if fd.rd_expect[1] then
flags = flags | sysdef.SEL_READ
deadlock = false
end
if #fd.wr_buf > 0 then
flags = flags | sysdef.SEL_WRITE
deadlock = false
end
sel_fds[i][2] = flags
end
mainloop_fds_change = false
assert(not deadlock, "Mainloop does nothing!")
local res = sys.select(sel_fds, -1)
assert(res, "select() call failed")
for i, fd = pairs(fds) do
local flags = sel_fds[i][3]
if flags & sysdef.SEL_ERROR ~= 0 then
fd.error_cb(fd)
else
if flags & sysdef.SEL_READ ~= 0 then
local reader = fd.rd_expect[1]
local tmp = sys.read(fd.fd, 0, reader[1] - #reader[2])
reader[2] = reader[2] .. tmp
if #reader[2] == reader[1] then
reader[3](reader[2])
table.remove(fd.rd_expect, 1)
end
end
if flags & sysdef.SEL_WRITE ~= 0 then
local r = sys.write(fd.fd, 0, fd.wr_buf)
fd.wr_buf = fd.wr_buf:sub(r+1)
end
end
end
end
end
function mainloop.exit()
mainloop_must_exit = true
end
return mainloop
|