mikejonesguy
mikejonesguy

Reputation: 9989

How to make a Lua function block until a closure is called

I have a custom Lua interpreter executable with some basic socket functionality built in. It's not Luasocket, and as much as I would like to be using Luasocket here, I can't (so please don't suggest it as an answer).

The socket API that I'm working with relies on asynchronous closures to signal that a network operation is complete. So, in the code below, socketConnect() returns immediately and then onConnect() is called later on when the connection is complete.

local function onConnect(cookie, err, sock)
  print("Connected!")
end

local function connect(host, port)
  local success, err = socketConnect(host, port, onConnect)
  print("Connecting...")
end

So, here's the question. I want to make the connect() function block until the onConnect() closure is called. I'm pretty new at Lua, but I'm hoping that coroutines might be helpful here?

EDIT: Here's my attempt at making the function block by using a coroutine:

local connected = false
local function onConnect(cookie, err, sock)
  print("Connected!")
  connected = true
end

local coroConnect = coroutine.create(
  function()
    local success, err = socketConnect(m_sHost, m_nPort, onConnect);
    while not connected do
      coroutine.yield()
    end
  end
)

local function connect(sHost, nPort)
  m_sHost = sHost
  m_nPort = nPort
  while not coroutine.status(coroConnect) ~= "dead" do
    coroutine.resume(coroConnect)
    print("Connecting...")
  end
end

Upvotes: 1

Views: 1059

Answers (1)

Paul Kulchenko
Paul Kulchenko

Reputation: 26744

If you want to use coroutines, something along these lines may work for you (or give you an idea on what to try):

-- this should really be a socket property, but good enough for this example
local connected
local function onConnect(cookie, err, sock)
  print("Connected!")
  connected = true
end

local function connect(host, port)
  connected = false
  local success, err = socketConnect(host, port, onConnect)
  while not connected do
    coroutine.yield()
  end
  print("Connecting...")
end

If you now create a coroutine from connect function and continue calling that coroutine with coroutine.resume until it's completed (coroutine.status for that coroutine will return 'dead'), you will get the desired result. Obviously, you can move that while loop into socketConnect function itself, which will make is synchronous from the user perspective as it won't return anything until onConnect is executed.

Upvotes: 1

Related Questions