luaevent/luaevent.lua

changeset 0
f2e807614be9
child 1
31c782cfe7fe
equal deleted inserted replaced
-1:000000000000 0:f2e807614be9
1 module("luaevent", package.seeall)
2 require("luaevent.core")
3
4 local EV_READ = luaevent.core.EV_READ
5 local EV_WRITE = luaevent.core.EV_WRITE
6 local fair = false
7
8 -- Weak keys.. the keys are the client sockets
9 local clientTable = {} or setmetatable({}, {'__mode', 'k'})
10
11 local function getWrapper()
12 local running = coroutine.running()
13 return function(...)
14 print(coroutine.running(), running)
15 print(debug.traceback())
16 if coroutine.running() == running then return end
17 return select(2, coroutine.resume(running, ...))
18 end
19 end
20
21 function send(sock, data, start, stop)
22 local s, err
23 local from = start or 1
24 local sent = 0
25 repeat
26 from = from + sent
27 s, err, sent = sock:send(data, from, stop)
28 -- Add extra coro swap for fairness
29 -- CURRENTLY DISABLED FOR TESTING......
30 if fair and math.random(100) > 90 then
31 coroutine.yield(EV_WRITE)
32 end
33 if s or err ~= "timeout" then return s, err, sent end
34 if not clientTable[sock] then clientTable[sock] = luaevent.core.addevent(sock, EV_WRITE, getWrapper()) end
35 coroutine.yield(EV_WRITE)
36 until false
37 end
38 function receive(sock, pattern, part)
39 local s, err
40 pattern = pattern or '*l'
41 repeat
42 s, err, part = sock:receive(pattern, part)
43 if s or err ~= "timeout" then return s, err, part end
44 if not clientTable[sock] then clientTable[sock] = luaevent.core.addevent(sock, EV_READ, getWrapper()) end
45 coroutine.yield(EV_READ)
46 until false
47 end
48 -- same as above but with special treatment when reading chunks,
49 -- unblocks on any data received.
50 function receivePartial(client, pattern)
51 local s, err, part
52 pattern = pattern or "*l"
53 repeat
54 s, err, part = client:receive(pattern)
55 if s or ( (type(pattern)=="number") and part~="" and part ~=nil ) or
56 err ~= "timeout" then return s, err, part end
57 if not clientTable[sock] then clientTable[sock] = luaevent.core.addevent(sock, EV_READ, getWrapper()) end
58 coroutine.yield(EV_READ)
59 until false
60 end
61 function connect(sock, ...)
62 sock:settimeout(0)
63 local ret, err = sock:connect(...)
64 if ret or err ~= "timeout" then return ret, err end
65 if not clientTable[sock] then clientTable[sock] = luaevent.core.addevent(sock, EV_WRITE, getWrapper()) end
66 coroutine.yield(EV_WRITE)
67 ret, err = sock:connect(...)
68 if err == "already connected" then
69 return 1
70 end
71 return ret, err
72 end
73 -- Deprecated..
74 function flush(sock)
75 end
76 local function clientCoroutine(sock, handler)
77 -- Figure out what to do ......
78 return handler(sock)
79 end
80 local function handleClient(co, client, handler)
81 local ok, res, event = coroutine.resume(co, client, handler)
82 end
83 local function serverCoroutine(sock, callback)
84 local listenItem = luaevent.core.addevent(sock, EV_READ, getWrapper())
85 repeat
86 local event = coroutine.yield(EV_READ)
87 -- Get new socket
88 local client = sock:accept()
89 if client then
90 client:settimeout(0)
91 local co = coroutine.create(clientCoroutine)
92 handleClient(co, client, callback)
93 end
94 until false
95 end
96 function addserver(sock, callback)
97 local coro = coroutine.create(serverCoroutine)
98 assert(coroutine.resume(coro, sock, callback))
99 end
100 function addthread(func, ...)
101 return coroutine.resume(coroutine.create(func), ...)
102 end
103 local _skt_mt = {__index = {
104 connect = function(self, ...)
105 return connect(self.socket, ...)
106 end,
107 send = function (self, data)
108 return send (self.socket, data)
109 end,
110
111 receive = function (self, pattern)
112 if (self.timeout==0) then
113 return receivePartial(self.socket, pattern)
114 end
115 return receive (self.socket, pattern)
116 end,
117
118 flush = function (self)
119 return flush (self.socket)
120 end,
121
122 settimeout = function (self,time)
123 self.timeout=time
124 return
125 end,
126 }}
127 function wrap(sock)
128 return setmetatable({socket = sock}, _skt_mt)
129 end
130 loop = luaevent.core.loop

mercurial