I'm working on a little Lua app (under Lua for Windows, if that matters) that uses sockets to communicate with the outside world. (LuaSocket)
And I'm trying to make several requests in parallel. So I thought LuaLanes was the way to go. (I'm open to alternatives, of course, if there's a better solution, but would prefer not to deal with coroutines for this.)
Something like this:
server = assert (socket.bind ('*', 1234))
client = server : accept ()
-- set id to some unique value
allClients [id] = client
theLane = lanes.gen ("", laneTest) ( id )
print (theLane [1])
Where the laneTest
function is defined as follows:
function laneTest (id)
local client = allClients [id]
print ('peer: ', client:getpeername())
end
My problem is that inside the laneTest
function, when run as a lane, I get this lovely error message:
attempt to index local 'client' (a userdata value)
(from the line client:getpeername()
)
So.. I'm not sure what's going on here? Is lanes incompatible with sockets, or am I doing something very wrong?
I guess it could be that the version of lanes that ships with Lua for Windows is ancient (luaforwindows) and doesn't work with sockets, but the latest version might? (Lanes 2.0.4 vs the more recent 3.xx)
I don't really know how to go about updating the version of Lanes I've got, else I would have tried that by now, so. I'd appreciate any advice if that's where I could be heading or there's something more obvious that I've done wrong.
Edit: I went ahead and installed lanes via luarocks, and have the same problem using lanes 3.1.6-1 that's installed as a rock.
Edit 2: Tried this (and still failed):
require ('socket')
require ('lanes')
local allClients = {}
function theLane (id)
print ('the id:', id) -- correctly prints out the id passed to the function
local SOCKET = require ('socket')
local client = allClients [id]
print ('peer:', client:getpeername())
client : close ()
end
local server = assert (SOCKET.bind ('*', 1234))
local ip, port = server:getsockname ()
local laneFunc = lanes.gen('', theLane)
local client = server:accept ()
allClients [1] = client
local x = laneFunc (1)
print (x[1])
- This fails claiming:
attempt to call global 'require' (a nil value)
- Removing the
require ('socket')
line inside the function and retrying also fails saying:attempt to index local 'client' (a userdata value)
I apologize in advance for missing the obvious, but... how do you get sockets to work with lanes?
Edit 3:
Well, I'm editing this in for future reference :)
As far as I can tell, there's no way of using Lanes with Sockets without patching luasockets. See discussion here for more about that; but in short (and as explained in Deco's answer): lanes does not work with userdata. luasocket does not provide any other way of accessing socket/socket info.
I have no desire to patch luasocket so as much as I would have rather used lanes, I'm going go ahead and stick with copas or couroutines.
Thanks all!