在lua工作,我有一个键/值对表
local fmtsToRun = {
name = function()
return configSubTable
end
}
长度可以是1个或多个条目。我需要循环遍历每个条目并运行一个子进程(通过一些libuvC绑定(。
对于正常的for循环,子进程在循环完成运行后从libuv返回,导致出现问题。结果将是
- 循环启动
- 循环条目1
- 作业1开始
- 循环入口2
- 作业2开始
- 循环结束
- Job1返回
- Job2返回
我需要的是
- 循环启动
- 循环条目1
- 作业1开始
- Job1返回
- 循环入口2
- 作业2开始
- Job2返回
- 循环结束
我还尝试将自己版本的pairs()
编写到并使用类似协程的东西来处理回调
for fmt, output in jobIterator(fmtsToRun) do
print('finished running', output)
end
local function jobIterator(tbl)
return coroutine.wrap(function()
local fmtConf, fmtName
fmtName, fmtConf = next(tbl, fmtName)
if nil~=fmtConf then
local conf = fmtConf()
local output = nil
-- wrapper util from Libuv library
local job = Job:new({
cmd = conf.cmd,
args = conf.args,
on_stdout = onStdout, -- process output
on_stderr = onStderr, -- process any error
on_exit = function()
coroutine.yield(fmtName, output)
end
})
job.send(conf.data)
end
end)
end
这导致了该错误消息。
attempt to yield across C-call boundary
什么是";右";如何在保持正确顺序的同时等待job
完成并继续循环?
一个更好的选择是手动控制流,并递归调用一个函数,一次遍历一个表项。
local runner = {}
for _, output in pairs(fmtsToRun) do
table.insert(runner, output)
end
jobIterator(runner)
local function jobIterator(tbl)
local F = {}
function F.step()
if #tbl == 0 then
return
end
local current = table.remove(tbl, 1)
F.run(current)
end
function F.run(conf)
local output = nil
-- wrapper util from Libuv library
local job =
Job:new(
{
cmd = conf.cmd,
args = conf.args,
on_stdout = onStdout, -- process output
on_stderr = onStderr, -- process any error
on_exit = function()
-- do what you need with output
print(output)
F.step()
end
}
)
job.send(conf.data)
end
F.step()
end