Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I have a gopher server written in Lua [1] that uses coroutines to handle each connection. This bit of code is executed as the main menu page [2] is being displayed (with comments)

    -- -------------------
    -- Load in some modules.
    -- The first makes a gopher menu item of type link
    -- The second allows us to do a TCP connection
    -- --------------------------

    local mklink = require "port70.mklink"
    local tcp    = require "org.conman.nfl.tcp"

    -- ------------------------------
    -- tcp.connect() connects to the given address and port and timeout
    -- (in seconds).  This function will create a socket, set it
    -- to non-blocking, call connect, then yield.  When the socket has
    -- connected, the coroutine is then resumed with the connection; if
    -- 1 second has passed before the connection is done, then nil is
    -- returned when resumed.  This just calls a local QOTD service.
    -- ---------------------

    local ios = tcp.connect("127.0.0.1",'qotd',1)
    
    if ios then
      local res = ""
      -- --------------------------------
      -- The following loop will yield the coroutine until a line
      -- of data has been accumulated from the network.  The coroutine
      -- is then resumed with the line of text.
      -- ---------------------------------------
      for line in ios:lines() do
        -- -----------
        -- We're just accumulating the text into one long blob of
        -- text that we'll return
        -- -----------------
        res = res .. mklink { type = 'info' , display = line }
      end
      ios:close() -- another yield point, when closed, resume
      return res
    else
      return mklink { type = 'info' , display = "Not Available" }
    end
No exceptions here. If we can't connect, it's a simple 'if' test and do something else. The functions `tcp.connect()`, `ios:lines()` and `ios:close()` are all blocking points that cause the coroutine to yield. Yes, if I put something like `while true do end` that will block the entire process as there is no preemption, but aside from that detail, I find this code easy to read.

[1] https://github.com/spc476/port70/blob/master/share/index.por...

[2] gopher://gopher.conman.org/



tip: In order to flatten those if-statements you can return early, so if you start with if not ios then return - you get rid of one if..else.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: