coroutine pool in parallel code
This commit is contained in:
@@ -1,8 +1,31 @@
|
|||||||
local class = require('class')
|
local class = require('class')
|
||||||
|
|
||||||
local parallel = _G.parallel
|
local os = _G.os
|
||||||
|
|
||||||
local TaskRunner = class()
|
local TaskRunner = class()
|
||||||
|
local free = { }
|
||||||
|
|
||||||
|
local function createTask(fn)
|
||||||
|
local task = table.remove(free)
|
||||||
|
if not task then
|
||||||
|
task = {
|
||||||
|
fn = fn,
|
||||||
|
co = coroutine.create(function()
|
||||||
|
local args = { }
|
||||||
|
while true do
|
||||||
|
pcall(task.fn, table.unpack(args))
|
||||||
|
task.dead = true
|
||||||
|
table.insert(free, task)
|
||||||
|
args = { coroutine.yield() }
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
}
|
||||||
|
else
|
||||||
|
task.dead = nil
|
||||||
|
task.fn = fn
|
||||||
|
end
|
||||||
|
return task
|
||||||
|
end
|
||||||
|
|
||||||
function TaskRunner:init(args)
|
function TaskRunner:init(args)
|
||||||
self.tasks = { }
|
self.tasks = { }
|
||||||
@@ -14,17 +37,30 @@ function TaskRunner:init(args)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function TaskRunner:add(fn)
|
function TaskRunner:add(fn)
|
||||||
table.insert(self.tasks, function()
|
table.insert(self.tasks, createTask(fn))
|
||||||
local s, m = pcall(fn)
|
|
||||||
if not s and m then
|
|
||||||
self:onError(m)
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function TaskRunner:run()
|
function TaskRunner:run()
|
||||||
if #self.tasks > 0 then
|
if #self.tasks > 0 then
|
||||||
parallel.waitForAll(table.unpack(self.tasks))
|
local event = { }
|
||||||
|
|
||||||
|
while #self.tasks > 0 do
|
||||||
|
for n = #self.tasks, 1, -1 do
|
||||||
|
local task = self.tasks[n]
|
||||||
|
if task.filter == nil or task.filter == event[1] or event[1] == "terminate" then
|
||||||
|
local ok, param = coroutine.resume(task.co, table.unpack(event))
|
||||||
|
if not ok then
|
||||||
|
self:onError(param)
|
||||||
|
else
|
||||||
|
task.filter = param
|
||||||
|
end
|
||||||
|
if task.dead then
|
||||||
|
table.remove(self.tasks, n)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
event = { os.pullEventRaw() }
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user