diff --git a/milo/apis/taskRunner.lua b/milo/apis/taskRunner.lua index ac1a2b3..e12c219 100644 --- a/milo/apis/taskRunner.lua +++ b/milo/apis/taskRunner.lua @@ -1,8 +1,31 @@ local class = require('class') -local parallel = _G.parallel +local os = _G.os 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) self.tasks = { } @@ -14,17 +37,30 @@ function TaskRunner:init(args) end function TaskRunner:add(fn) - table.insert(self.tasks, function() - local s, m = pcall(fn) - if not s and m then - self:onError(m) - end - end) + table.insert(self.tasks, createTask(fn)) end function TaskRunner:run() 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