【问题标题】:How to make a Lua function block until a closure is called如何在调用闭包之前制作 Lua 功能块
【发布时间】:2014-12-18 05:30:57
【问题描述】:

我有一个自定义的 Lua 解释器可执行文件,内置了一些基本的套接字功能。它不是 Luasocket,尽管我想在这里使用 Luasocket,但我不能(所以请不要将其作为答案)。

我正在使用的套接字 API 依赖于异步闭包来发出网络操作已完成的信号。因此,在下面的代码中,socketConnect() 立即返回,然后在连接完成后调用 onConnect()

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

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

那么,问题来了。我想制作 connect() 功能块,直到调用 onConnect() 闭包。我是 Lua 的新手,但我希望协程在这里可能会有所帮助?

编辑:这是我使用协程制作功能块的尝试:

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

【问题讨论】:

  • Lua 不支持多线程或异步回调,因此socketConnect 在回调返回之前调用回调,或者代码使用一些多线程扩展,在这种情况下,知道哪一个会很有帮助。
  • 我的 custom Lua 解释器确实有一个工作线程,从中调用回调。如果我调用上面的 connect(),打印输出将是“Connecting...Connected!”

标签: lua coroutine


【解决方案1】:

如果您想使用协程,这些方面的东西可能对您有用(或让您知道尝试什么):

-- 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

如果您现在从 connect 函数创建一个协程并继续使用 coroutine.resume 调用该协程直到它完成(该协程的 coroutine.status 将返回“死亡”),您将获得所需的结果。显然,您可以将 while 循环移动到 socketConnect 函数本身,从用户的角度来看,这将是同步的,因为在执行 onConnect 之前它不会返回任何内容。

【讨论】:

  • 保罗,我尝试了这种方法,但协程无限期地继续。 :/ 我希望我做错了,并且有一些神奇的调味料可以让它工作,但我怀疑我的自定义解释器的架构是这个问题的根源。
  • 我会接受这个答案,因为我认为这个建议是合理的,即使它没有解决我的问题。
  • 嗯,我不希望协程无限期地继续,因为在打印“正在连接...”之后,它会完成并返回,这将使其状态为“死亡”。似乎您可能没有进行最后一次“恢复”调用,这使协程处于“未完成”状态。这仍然不是一个大问题,如果没有其他引用指向它,它将被垃圾收集。
  • Paul,看看我的编辑,我尝试使用协程。使用这段代码,我一遍又一遍地得到“正在连接...”,但它永远不会变成“已连接!”。
  • @mikejonesguy,这行不通;在coroutine.resume(coroConnect) 之前,您需要做一些socketConnect 正在做的工作,最后调用onConnect。如果有另一个协同程序可以完成这项工作(“调用回调的工作线程”),那么您需要在coroutine.resume(coroConnect) 之前添加coroutine.resume(workerThread)(或类似的东西)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-14
  • 1970-01-01
  • 2023-03-03
相关资源
最近更新 更多