async: Use function to capture ...

Instead of only capturing 8 temps, pass resume to a function so we can
capture all returned values as ...

I might be missing a reason why you wouldn't do it like this.

Test
    -- coro is an async() updated in love.update
    coro:call(
        function()
            coro.wait(1)

            print("jump")
            self.gravity.y = -900
            coro.wait(1)

            print("fall")
            self.gravity.y = 900
            coroutine.yield "hello"

            return "done"
        end,
        nil,
        function(...)
            print("complete", ...)
        end)
This commit is contained in:
David Briscoe 2022-03-02 08:10:56 -08:00
parent f6a18380d4
commit 585ba82e57

View File

@ -49,6 +49,35 @@ function async:add(co, args, callback, error_callback)
}) })
end end
local function process_resume(self, td, success, msg, ...)
local co, args, cb, error_cb = unpack(td)
--error?
if not success then
if error_cb then
error_cb(msg)
else
local err = ("failure in async task:\n\n\t%s\n")
:format(tostring(msg))
error(err)
end
end
--check done
if coroutine.status(co) == "dead" then
--done? run callback with result
if cb then
cb(msg, ...)
end
else
--if not completed, re-add to the appropriate queue
if msg == "stall" then
--add to stalled queue as signalled stall
table.insert(self.tasks_stalled, td)
else
table.insert(self.tasks, td)
end
end
end
--update some task in the kernel --update some task in the kernel
function async:update() function async:update()
--grab task definition --grab task definition
@ -65,34 +94,8 @@ function async:update()
end end
--run a step --run a step
--(using unpack because coroutine is also nyi and it's core to this async model) --(using unpack because coroutine is also nyi and it's core to this async model)
local co, args, cb, error_cb = unpack(td) local co, args = unpack(td)
--(8 temps rather than table churn capturing varargs) process_resume(self, td, coroutine.resume(co, unpack(args)))
local success, a, b, c, d, e, f, g, h = coroutine.resume(co, unpack(args))
--error?
if not success then
if error_cb then
error_cb(a)
else
local err = ("failure in async task:\n\n\t%s\n")
:format(tostring(a))
error(err)
end
end
--check done
if coroutine.status(co) == "dead" then
--done? run callback with result
if cb then
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
table.insert(self.tasks, td)
end
end
return true return true
end end