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 |