ZAN
ZAN

Reputation: 591

How to run blocking operation in Corona SDK Lua?

I'm new to LUA and I'm writing a tcp messaging library in LUA using Corona SDK. I stuck with a problem that socket reading operation hangs application UI even if it is run in coroutine.

How I start coroutine:

function Messaging:readLoop()
   self.readCoroutine = coroutine.create(function() self:blockingLoop() end)
   coroutine.resume(self.readCoroutine)
end

Blocking loop:

function Messaging:blockingLoop()
   line,err,rest = self.sock:receive(BUFSIZE) -- <= Hangs UI if there is no incoming data 
end

Of course I know that coroutines are not equal to threads, but I expected that LUA interpreter switched to another coroutine on blocking operation (like Python threads with GIL). Is there any possibility to read from socket without blocking UI? For example with real threading or async approach? Thanks.

P.S. Eliminating BUFSIZ is not the option since I don't want to have UI blocked at all, even for 0.2..0.4 seconds (slow mobile network delay)

Upvotes: 3

Views: 1554

Answers (3)

ZAN
ZAN

Reputation: 591

Based on links posted by Mud and SatheeshJM, I finally made a messaging class which might be helpful for somebody

-- Messaging prototype
Messaging = {sock = nil, sockTimer = nil}

-- Messaging constructor
function Messaging:new (o)
   o = o or {}
   setmetatable(o, self)
   self.__index = self
   return o
end

function Messaging:connect()
   self.sock = socket.tcp()
   print( self.sock:connect(HOST, PORT) )
   self.sock:settimeout(0)
   self.sockTimer = timer.performWithDelay(50, function() self:checkData() end, 0)
end

function Messaging:close()
   timer.cancel(self.sockTimer)
   self.sock:close()
end

function Messaging:checkData()
   local data, status, rest = self.sock:receive()
   local s
   if data then
      s = data
   else
      s = rest
   end
   if s:len() ~= 0 then
      print ('received', s)
   end
end

Important notes:

  1. self.sock:settimeout(0) required to make socket non-blocking
  2. local data, status, rest = self.sock:receive() <- In most cased data will be in "rest" variable when "timeout" error appeared, that is why we need a check below to learn how exactly the data transfered

Upvotes: 0

Mud
Mud

Reputation: 29010

Corona contains LuaSockets which will let you do asynchronous socket communication, as seen here.

Upvotes: 2

SatheeshJM
SatheeshJM

Reputation: 3643

Corona has a network.request API for Asynchronous calls..

If you do not want to use that, take a look at this asynchronous http library.

Upvotes: 1

Related Questions