lua/luaevent.lua

changeset 17
1a093a31059d
parent 15
9b91d1bdbb40
child 70
004edb92a6e8
equal deleted inserted replaced
16:742a6620b378 17:1a093a31059d
5 module("luaevent", package.seeall) 5 module("luaevent", package.seeall)
6 require("luaevent.core") 6 require("luaevent.core")
7 7
8 local EV_READ = luaevent.core.EV_READ 8 local EV_READ = luaevent.core.EV_READ
9 local EV_WRITE = luaevent.core.EV_WRITE 9 local EV_WRITE = luaevent.core.EV_WRITE
10 local fair = false -- Not recommended for most cases...
11 local base = luaevent.core.new() 10 local base = luaevent.core.new()
12 local sockMap = setmetatable({}, {'__mode', 'kv'}) 11
13 local function addevent(sock, ...) 12 local function addevent(...)
14 local item = base:addevent(sock, ...) 13 return base:addevent(...)
15 if not item then print("FAILED TO SETUP ITEM") return item end
16 local fd = sock:getfd()
17 sockMap[item] = fd
18 print("SETUP ITEM FOR: ", fd)
19 if not hookedObjectMt then
20 hookedObjectMt = true
21 --[[
22 local mt = debug.getmetatable(item)
23 local oldGC = mt.__gc
24 mt.__gc = function(...)
25 print("RELEASING ITEM FOR: ", sockMap[(...)])
26 return oldGC(...)
27 end]]
28 end
29 return item
30 end 14 end
31 -- Weak keys.. the keys are the client sockets
32 local clientTable = setmetatable({}, {'__mode', 'kv'})
33 15
34 local function getWrapper() 16 local function getWrapper()
35 local running = coroutine.running() 17 local running = coroutine.running()
36 return function(...) 18 return function(...)
37 if coroutine.running() == running then return end
38 return select(2, coroutine.resume(running, ...)) 19 return select(2, coroutine.resume(running, ...))
39 end 20 end
40 end 21 end
22 -- Weak keys.. the keys are the client sockets
23 local clientTable = setmetatable({}, {'__mode', 'kv'})
24 local function socketWait(sock, event)
25 if not clientTable[sock] then clientTable[sock] = addevent(sock, event, getWrapper()) end
26 coroutine.yield(event)
27 end
28
41 29
42 function send(sock, data, start, stop) 30 function send(sock, data, start, stop)
43 local s, err 31 local s, err
44 local from = start or 1 32 local from = start or 1
45 local sent = 0 33 local sent = 0
46 repeat 34 repeat
47 from = from + sent 35 from = from + sent
48 s, err, sent = sock:send(data, from, stop) 36 s, err, sent = sock:send(data, from, stop)
49 -- Add extra coro swap for fairness
50 -- CURRENTLY DISABLED FOR TESTING......
51 if fair and math.random(100) > 90 then
52 if not clientTable[sock] then clientTable[sock] = addevent(sock, EV_WRITE, getWrapper()) end
53 coroutine.yield(EV_WRITE)
54 end
55 if s or err ~= "timeout" then return s, err, sent end 37 if s or err ~= "timeout" then return s, err, sent end
56 if not clientTable[sock] then clientTable[sock] = addevent(sock, EV_WRITE, getWrapper()) end 38 socketWait(sock, EV_WRITE)
57 coroutine.yield(EV_WRITE)
58 until false 39 until false
59 end 40 end
60 function receive(sock, pattern, part) 41 function receive(sock, pattern, part)
61 local s, err 42 local s, err
62 pattern = pattern or '*l' 43 pattern = pattern or '*l'
63 repeat 44 repeat
64 s, err, part = sock:receive(pattern, part) 45 s, err, part = sock:receive(pattern, part)
65 if s or err ~= "timeout" then return s, err, part end 46 if s or err ~= "timeout" then return s, err, part end
66 if not clientTable[sock] then clientTable[sock] = addevent(sock, EV_READ, getWrapper()) end 47 socketWait(sock, EV_READ)
67 coroutine.yield(EV_READ)
68 until false 48 until false
69 end 49 end
70 -- same as above but with special treatment when reading chunks, 50 -- same as above but with special treatment when reading chunks,
71 -- unblocks on any data received. 51 -- unblocks on any data received.
72 function receivePartial(client, pattern) 52 function receivePartial(client, pattern)
74 pattern = pattern or "*l" 54 pattern = pattern or "*l"
75 repeat 55 repeat
76 s, err, part = client:receive(pattern) 56 s, err, part = client:receive(pattern)
77 if s or ( (type(pattern)=="number") and part~="" and part ~=nil ) or 57 if s or ( (type(pattern)=="number") and part~="" and part ~=nil ) or
78 err ~= "timeout" then return s, err, part end 58 err ~= "timeout" then return s, err, part end
79 if not clientTable[sock] then clientTable[sock] = addevent(sock, EV_READ, getWrapper()) end 59 socketWait(sock, EV_READ)
80 coroutine.yield(EV_READ)
81 until false 60 until false
82 end 61 end
83 function connect(sock, ...) 62 function connect(sock, ...)
84 sock:settimeout(0) 63 sock:settimeout(0)
85 local ret, err = sock:connect(...) 64 local ret, err = sock:connect(...)
86 if ret or err ~= "timeout" then return ret, err end 65 if ret or err ~= "timeout" then return ret, err end
87 if not clientTable[sock] then clientTable[sock] = addevent(sock, EV_WRITE, getWrapper()) end 66 socketWait(sock, EV_WRITE)
88 coroutine.yield(EV_WRITE)
89 ret, err = sock:connect(...) 67 ret, err = sock:connect(...)
90 if err == "already connected" then 68 if err == "already connected" then
91 return 1 69 return 1
92 end 70 end
93 return ret, err 71 return ret, err

mercurial