File: select.lua

package info (click to toggle)
luasocket 2.0-alpha-2
  • links: PTS
  • area: main
  • in suites: sarge
  • size: 452 kB
  • ctags: 437
  • sloc: ansic: 2,015; makefile: 107
file content (83 lines) | stat: -rw-r--r-- 3,101 bytes parent folder | download
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
-----------------------------------------------------------------------------
-- Select implementation
-- LuaSocket toolkit.
-- Author: Diego Nehab
-- RCS ID: $Id: select.lua,v 1.5 2003/06/26 18:47:47 diego Exp $
-----------------------------------------------------------------------------

----------------------------------------------------------------------
-- Copy fds from tab to set, creating fd_tab association table.
----------------------------------------------------------------------
local function collect_fd(obj_tab, fd_set, fd_tab)
    for i, obj in ipairs(obj_tab) do 
        local fd = obj:fd()
        fd_set:set(fd)
        fd_tab[fd] = obj
    end
    return fd_set
end

----------------------------------------------------------------------
-- Copy socks from set to tab, using fd_tab association table.
----------------------------------------------------------------------
local function collect_obj(fd_set, max_fd, obj_tab, fd_tab)
    for fd = 0, max_fd do
        if fd_set:isset(fd) then 
            table.insert(obj_tab, fd_tab[fd]) 
        end
    end
end

----------------------------------------------------------------------
-- Treat objects with unread buffered data
----------------------------------------------------------------------
local function check_dirty(obj_tab, dirty, fd_tab)
    local any = false
    for i, obj in ipairs(obj_tab) do
        if obj:dirty() then 
            table.insert(dirty, obj)
            fd_tab[obj:fd()] = nil
            any = true
        end
    end
    return any
end

----------------------------------------------------------------------
-- Lua select helper
----------------------------------------------------------------------
return function(read_obj_tab, write_obj_tab, timeout, 
    read_fd_set, write_fd_set, c_select)
    local fd_tab = {}
    local readable, writable = {}, {}
    read_obj_tab = read_obj_tab or {}
    write_obj_tab = write_obj_tab or {}
    -- build read_fd_set from from read_obj_tab and build write_fd_set 
    -- from write_obj_tab. create fd_tab mapping fd values to their
    -- corresponding objects. 
    collect_fd(read_obj_tab, read_fd_set, fd_tab)
    collect_fd(write_obj_tab, write_fd_set, fd_tab)
    -- if there are any sockets being tested for readability that 
    -- have buffered data unread, move them to readable table and
    -- set timeout to 0
    local dirty = check_dirty(read_obj_tab, readable, fd_tab)
    if dirty then timeout = 0 end
    -- compute the maximum fd value
    local max_fd = -1
    for fd, obj in fd_tab do 
        if fd > max_fd then 
            max_fd = fd 
        end 
    end
    -- call C select
    local ret = c_select(max_fd+1, read_fd_set, write_fd_set, timeout)
    if ret > 0 then 
        -- collect readable and writable sockets from fd sets to 
        -- readable and writable object tables
        collect_obj(read_fd_set, max_fd, readable, fd_tab) 
        collect_obj(write_fd_set, max_fd, writable, fd_tab)
        ret = nil
    elseif dirty then ret = nil 
    else ret = "timeout" end
    return readable, writable, ret
end