Mon, 11 Jun 2007 01:08:59 +0000
* Completed mostly working version
* Moved to a mode where addevent calls a callback rather than
it being instantiated within.
* If the callback returns -1, then no event is ever setup
* Otherwise the integer value is used to setup the event
* This allows for using coroutine.wrap rather than a cooked-up wrapper
* Tests work, although there are a few remaining issues:
* Need to figure a good way of preserving the event object,
not sure if current method is good enough, since the socket
is the only anchor, and it is only held inside the coro..
circular reference, something that Lua 'handles' well.
* Doing more than the maximum sockets the process is allows
causes strangeness to occur in libevent.. somehow
it is getting around to epoll_add which is causing valgrind
to barf.
1
31c782cfe7fe
* Adjusted licensing and added README.
Thomas Harning Jr <harningt@gmail.com>
parents:
0
diff
changeset
|
1 | --[[ |
31c782cfe7fe
* Adjusted licensing and added README.
Thomas Harning Jr <harningt@gmail.com>
parents:
0
diff
changeset
|
2 | LuaEvent - Copyright (C) 2007 Thomas Harning <harningt@gmail.com> |
31c782cfe7fe
* Adjusted licensing and added README.
Thomas Harning Jr <harningt@gmail.com>
parents:
0
diff
changeset
|
3 | Licensed as LGPL - See doc/COPYING for details. |
31c782cfe7fe
* Adjusted licensing and added README.
Thomas Harning Jr <harningt@gmail.com>
parents:
0
diff
changeset
|
4 | ]] |
0 | 5 | module("luaevent", package.seeall) |
6 | require("luaevent.core") | |
7 | ||
8 | local EV_READ = luaevent.core.EV_READ | |
9 | local EV_WRITE = luaevent.core.EV_WRITE | |
10 | local fair = false | |
11 | ||
2
01b3a96ae760
* Completed mostly working version
Thomas Harning Jr <harningt@gmail.com>
parents:
1
diff
changeset
|
12 | local hookedObjectMt = false |
0 | 13 | |
2
01b3a96ae760
* Completed mostly working version
Thomas Harning Jr <harningt@gmail.com>
parents:
1
diff
changeset
|
14 | -- Weak keys.. the keys are the client sockets |
01b3a96ae760
* Completed mostly working version
Thomas Harning Jr <harningt@gmail.com>
parents:
1
diff
changeset
|
15 | local clientTable = setmetatable({}, {'__mode', 'k'}) |
0 | 16 | |
17 | function send(sock, data, start, stop) | |
18 | local s, err | |
19 | local from = start or 1 | |
20 | local sent = 0 | |
21 | repeat | |
22 | from = from + sent | |
23 | s, err, sent = sock:send(data, from, stop) | |
24 | -- Add extra coro swap for fairness | |
25 | -- CURRENTLY DISABLED FOR TESTING...... | |
26 | if fair and math.random(100) > 90 then | |
27 | coroutine.yield(EV_WRITE) | |
28 | end | |
29 | if s or err ~= "timeout" then return s, err, sent end | |
30 | coroutine.yield(EV_WRITE) | |
31 | until false | |
32 | end | |
33 | function receive(sock, pattern, part) | |
34 | local s, err | |
35 | pattern = pattern or '*l' | |
36 | repeat | |
37 | s, err, part = sock:receive(pattern, part) | |
38 | if s or err ~= "timeout" then return s, err, part end | |
39 | coroutine.yield(EV_READ) | |
40 | until false | |
41 | end | |
42 | -- same as above but with special treatment when reading chunks, | |
43 | -- unblocks on any data received. | |
44 | function receivePartial(client, pattern) | |
45 | local s, err, part | |
46 | pattern = pattern or "*l" | |
47 | repeat | |
48 | s, err, part = client:receive(pattern) | |
49 | if s or ( (type(pattern)=="number") and part~="" and part ~=nil ) or | |
50 | err ~= "timeout" then return s, err, part end | |
51 | coroutine.yield(EV_READ) | |
52 | until false | |
53 | end | |
54 | function connect(sock, ...) | |
55 | sock:settimeout(0) | |
56 | local ret, err = sock:connect(...) | |
57 | if ret or err ~= "timeout" then return ret, err end | |
58 | coroutine.yield(EV_WRITE) | |
59 | ret, err = sock:connect(...) | |
60 | if err == "already connected" then | |
61 | return 1 | |
62 | end | |
63 | return ret, err | |
64 | end | |
65 | -- Deprecated.. | |
66 | function flush(sock) | |
67 | end | |
68 | local function clientCoroutine(sock, handler) | |
69 | -- Figure out what to do ...... | |
70 | return handler(sock) | |
71 | end | |
2
01b3a96ae760
* Completed mostly working version
Thomas Harning Jr <harningt@gmail.com>
parents:
1
diff
changeset
|
72 | |
0 | 73 | local function serverCoroutine(sock, callback) |
74 | repeat | |
75 | local event = coroutine.yield(EV_READ) | |
76 | -- Get new socket | |
77 | local client = sock:accept() | |
78 | if client then | |
2
01b3a96ae760
* Completed mostly working version
Thomas Harning Jr <harningt@gmail.com>
parents:
1
diff
changeset
|
79 | --cl[#cl + 1] = client |
0 | 80 | client:settimeout(0) |
2
01b3a96ae760
* Completed mostly working version
Thomas Harning Jr <harningt@gmail.com>
parents:
1
diff
changeset
|
81 | local coFunc = coroutine.wrap(clientCoroutine) |
01b3a96ae760
* Completed mostly working version
Thomas Harning Jr <harningt@gmail.com>
parents:
1
diff
changeset
|
82 | clientTable[client] = luaevent.core.addevent(client, coFunc, client, callback) |
0 | 83 | end |
84 | until false | |
85 | end | |
2
01b3a96ae760
* Completed mostly working version
Thomas Harning Jr <harningt@gmail.com>
parents:
1
diff
changeset
|
86 | |
01b3a96ae760
* Completed mostly working version
Thomas Harning Jr <harningt@gmail.com>
parents:
1
diff
changeset
|
87 | local oldAddEvent = luaevent.core.addevent |
01b3a96ae760
* Completed mostly working version
Thomas Harning Jr <harningt@gmail.com>
parents:
1
diff
changeset
|
88 | luaevent.core.addevent = function(...) |
01b3a96ae760
* Completed mostly working version
Thomas Harning Jr <harningt@gmail.com>
parents:
1
diff
changeset
|
89 | local item = oldAddEvent(...) |
01b3a96ae760
* Completed mostly working version
Thomas Harning Jr <harningt@gmail.com>
parents:
1
diff
changeset
|
90 | print("SETUP ITEM FOR: ", debug.getmetatable(item).getfd(item)) |
01b3a96ae760
* Completed mostly working version
Thomas Harning Jr <harningt@gmail.com>
parents:
1
diff
changeset
|
91 | if not hookedObjectMt then |
01b3a96ae760
* Completed mostly working version
Thomas Harning Jr <harningt@gmail.com>
parents:
1
diff
changeset
|
92 | hookedObjectMt = true |
01b3a96ae760
* Completed mostly working version
Thomas Harning Jr <harningt@gmail.com>
parents:
1
diff
changeset
|
93 | local mt = debug.getmetatable(item) |
01b3a96ae760
* Completed mostly working version
Thomas Harning Jr <harningt@gmail.com>
parents:
1
diff
changeset
|
94 | local oldGC = mt.__gc |
01b3a96ae760
* Completed mostly working version
Thomas Harning Jr <harningt@gmail.com>
parents:
1
diff
changeset
|
95 | mt.__gc = function(...) |
01b3a96ae760
* Completed mostly working version
Thomas Harning Jr <harningt@gmail.com>
parents:
1
diff
changeset
|
96 | print("RELEASING ITEM FOR: ", mt.getfd(...)) |
01b3a96ae760
* Completed mostly working version
Thomas Harning Jr <harningt@gmail.com>
parents:
1
diff
changeset
|
97 | return oldGC(...) |
01b3a96ae760
* Completed mostly working version
Thomas Harning Jr <harningt@gmail.com>
parents:
1
diff
changeset
|
98 | end |
01b3a96ae760
* Completed mostly working version
Thomas Harning Jr <harningt@gmail.com>
parents:
1
diff
changeset
|
99 | end |
01b3a96ae760
* Completed mostly working version
Thomas Harning Jr <harningt@gmail.com>
parents:
1
diff
changeset
|
100 | return item |
01b3a96ae760
* Completed mostly working version
Thomas Harning Jr <harningt@gmail.com>
parents:
1
diff
changeset
|
101 | end |
01b3a96ae760
* Completed mostly working version
Thomas Harning Jr <harningt@gmail.com>
parents:
1
diff
changeset
|
102 | |
0 | 103 | function addserver(sock, callback) |
2
01b3a96ae760
* Completed mostly working version
Thomas Harning Jr <harningt@gmail.com>
parents:
1
diff
changeset
|
104 | local coFunc = coroutine.wrap(serverCoroutine) |
01b3a96ae760
* Completed mostly working version
Thomas Harning Jr <harningt@gmail.com>
parents:
1
diff
changeset
|
105 | clientTable[sock] = luaevent.core.addevent(sock, coFunc, sock, callback) |
0 | 106 | end |
2
01b3a96ae760
* Completed mostly working version
Thomas Harning Jr <harningt@gmail.com>
parents:
1
diff
changeset
|
107 | function addthread(sock, func, ...) |
01b3a96ae760
* Completed mostly working version
Thomas Harning Jr <harningt@gmail.com>
parents:
1
diff
changeset
|
108 | local coFunc = coroutine.wrap(func) |
01b3a96ae760
* Completed mostly working version
Thomas Harning Jr <harningt@gmail.com>
parents:
1
diff
changeset
|
109 | clientTable[sock] = luaevent.core.addevent(sock, coFunc, ...) |
0 | 110 | end |
111 | local _skt_mt = {__index = { | |
112 | connect = function(self, ...) | |
113 | return connect(self.socket, ...) | |
114 | end, | |
115 | send = function (self, data) | |
116 | return send (self.socket, data) | |
117 | end, | |
118 | ||
119 | receive = function (self, pattern) | |
120 | if (self.timeout==0) then | |
121 | return receivePartial(self.socket, pattern) | |
122 | end | |
123 | return receive (self.socket, pattern) | |
124 | end, | |
125 | ||
126 | flush = function (self) | |
127 | return flush (self.socket) | |
128 | end, | |
129 | ||
130 | settimeout = function (self,time) | |
131 | self.timeout=time | |
132 | return | |
133 | end, | |
134 | }} | |
135 | function wrap(sock) | |
136 | return setmetatable({socket = sock}, _skt_mt) | |
137 | end | |
138 | loop = luaevent.core.loop |