4 ms·
Can I have an example here?
by gte910h 13y ago
Can I have an example here?
- spc476 13y agoHere's a Lua-esque (since Lua supports coroutines) example. I want to run a simple TCP echo server, so the main code that handles a connection ideally would look like this: function echo(socket) local remote,data = socket:read() if remote == nil then -- no data socket:close() return end socket:write(remote,data) return echo(socket) -- Tail call, this is a goto end Normally, such code would need to be run in a separate process or thread but that's too much overhead. You can use an event-based method (say, with poll() or epoll()) but then the code becomes inverted (or involves callbacks---which in this case isn't too bad, but imagine trying to implement, say, SMTP). With coroutines, we can still use an event-based mainloop, but still keep the imperative style of the original function above. Our event loop would look something like: function mainloop() local events = select:events() for i = 1 , #events do local err,keepgoing = coroutine.resume(events[i].code,events[i].socket,events[i].remote) if not keepgoing then select:remove(events[i].socket) events[i].socket:close() end end return mainloop() end and we would need to change our function just a bit: function echo() local socket,remote = coroutine.yield(true) local data = socket:read() if data == nil then return false end socket:write(remote,data) return echo() end Oh, and don't forget the coroutine to accept new connections: function echoconnection() local socket = coroutine.yield(true) local connection,remote = socket:accept() select:insert(connection,{ read = true } ,{ code = echo,remote = remote }) return echoconnection() end You can, of course, rewrite it such that socket:read() does the call to coroutine.yield(), but here I wanted to make it more explicit (as well as a shorter example) to fully hide the implementation (this is based on a working implementation I have in about 224 lines of Lua, which also handles signals and hides the coroutine calls from the main functions---the first example in this post would run as-is in the fully-blown implementation).
- 616c 13y agoVery cool stuff. I wanted to start learning Lua. Is there any way to see your code?
- spc476 13y agoWell, it's finicky. You'll need to install several custom written Lua modules [1]. These have been tested under Linux and Solaris. You will definitely have to edit the Makefile to exclude building some of the modules like org.conman.tcc [2] because of dependency issues (TCC isn't for the faint of heart). If you are on another Unix system, you'll probably be able to get most of it built (at the least, you'll need org.conman.process, org.conman.net and org.conman.pollset). You will also need to install LPeg [3]. Once all those are installed, then you'll be able to run the code: http://pastebin.com/ZBq5gSbS http://pastebin.com/ZBq5gSbS Or you can just look at the code: http://pastebin.com/ZBq5gSbS http://pastebin.com/ZBq5gSbS The coroutine stuff is there, just well hidden. I will also link to a sample multiuser chat room (no security, very basic): http://pastebin.com/u6vSPc69 http://pastebin.com/u6vSPc69 [1] https://github.com/spc476/lua-conmanorg https://github.com/spc476/lua-conmanorg [2] It's a Lua interface to the TCC library, which is a C compiler-as-a-library. Not used in the same code I posted, but it is something I find immensely useful, but I would classify as "advanced." [3] http://www.inf.puc-rio.br/~roberto/lpeg/ http://www.inf.puc-rio.br/~roberto/lpeg/ This is the Lua Parsing Expression Grammar library. If you are familiar with compiler tools, think lex and yacc (or flex and bison).