mirror of
https://github.com/1bardesign/batteries.git
synced 2024-11-10 02:31:48 +00:00
[added] stall support, timers and intervals to async
This commit is contained in:
parent
3d3ccd921c
commit
bb35fc2f57
55
async.lua
55
async.lua
@ -1,6 +1,11 @@
|
|||||||
--[[
|
--[[
|
||||||
simple kernel for async tasks running in the background
|
simple kernel for async tasks running in the background
|
||||||
|
|
||||||
|
can "stall" a task by yielding the string "stall"
|
||||||
|
this will suspend the coroutine until the rest of
|
||||||
|
the queue has been processed or stalled
|
||||||
|
and can early-out update_for_time
|
||||||
|
|
||||||
todo:
|
todo:
|
||||||
multiple types of callbacks
|
multiple types of callbacks
|
||||||
finish, error, step
|
finish, error, step
|
||||||
@ -15,6 +20,7 @@ async._mt = {__index = async}
|
|||||||
function async:new()
|
function async:new()
|
||||||
return setmetatable({
|
return setmetatable({
|
||||||
tasks = {},
|
tasks = {},
|
||||||
|
tasks_stalled = {},
|
||||||
}, self._mt)
|
}, self._mt)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -33,8 +39,15 @@ function async:update()
|
|||||||
--grab task definition
|
--grab task definition
|
||||||
local td = table.remove(self.tasks, 1)
|
local td = table.remove(self.tasks, 1)
|
||||||
if not td then
|
if not td then
|
||||||
|
--have we got stalled tasks to re-try?
|
||||||
|
if #self.tasks_stalled > 0 then
|
||||||
|
--swap queues rather than churning elements
|
||||||
|
self.tasks_stalled, self.tasks = self.tasks, self.tasks_stalled
|
||||||
|
td = table.remove(self.tasks, 1)
|
||||||
|
else
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
end
|
||||||
--run a step
|
--run a step
|
||||||
local co, args, cb, error_cb = td[1], td[2], td[3], td[4]
|
local co, args, cb, error_cb = td[1], td[2], td[3], td[4]
|
||||||
--(reuse these 8 temps)
|
--(reuse these 8 temps)
|
||||||
@ -54,23 +67,61 @@ function async:update()
|
|||||||
--check done
|
--check done
|
||||||
if coroutine.status(co) == "dead" then
|
if coroutine.status(co) == "dead" then
|
||||||
--done? run callback with result
|
--done? run callback with result
|
||||||
|
if cb then
|
||||||
cb(a, b, c, d, e, f, g, h)
|
cb(a, b, c, d, e, f, g, h)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
--if not completed, re-add to the appropriate queue
|
||||||
|
if a == "stall" then
|
||||||
|
--add to stalled queue as signalled stall
|
||||||
|
table.insert(self.tasks_stalled, td)
|
||||||
else
|
else
|
||||||
--if not done, re-add
|
|
||||||
table.insert(self.tasks, td)
|
table.insert(self.tasks, td)
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
--update tasks for some amount of time
|
--update tasks for some amount of time
|
||||||
function async:update_for_time(t)
|
function async:update_for_time(t, early_out_stalls)
|
||||||
local now = love.timer.getTime()
|
local now = love.timer.getTime()
|
||||||
while love.timer.getTime() - now < t do
|
while love.timer.getTime() - now < t do
|
||||||
if not self:update() then
|
if not self:update() then
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
|
--all stalled?
|
||||||
|
if early_out_stalls and #self.tasks == 0 then
|
||||||
|
break
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--add a function to run after a certain delay (in seconds)
|
||||||
|
function async:add_timeout(f, delay)
|
||||||
|
local trigger_time = love.timer.getTime() + delay
|
||||||
|
self:call(function()
|
||||||
|
while love.timer.getTime() < trigger_time do
|
||||||
|
coroutine.yield("stall")
|
||||||
|
end
|
||||||
|
f()
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
--add a function to run repeatedly every delay (in seconds)
|
||||||
|
--note: not super useful currently unless you plan to destroy the async object
|
||||||
|
-- as there's no way to remove tasks :)
|
||||||
|
function async:add_interval(f, delay)
|
||||||
|
local trigger_time = love.timer.getTime() + delay
|
||||||
|
self:call(function()
|
||||||
|
while true do
|
||||||
|
while love.timer.getTime() < trigger_time do
|
||||||
|
coroutine.yield("stall")
|
||||||
|
end
|
||||||
|
f()
|
||||||
|
trigger_time = trigger_time + delay
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
return async
|
return async
|
Loading…
Reference in New Issue
Block a user