perf: prevent active waiting in coroutines. suspend/resume instead

This commit is contained in:
Folke Lemaitre 2024-06-27 13:06:39 +02:00
parent 79bcc02d17
commit 68cee30cdb
No known key found for this signature in database
GPG Key ID: 41F8B1FBACAE2040
3 changed files with 35 additions and 11 deletions

View File

@ -9,10 +9,14 @@ local M = {}
M._queue = {}
M._executor = assert(vim.loop.new_check())
M._running = false
M.SLEEP = "sleep"
---@type Async
M.current = nil
---@class Async
---@field co thread
---@field opts AsyncOpts
---@field sleeping? boolean
local Async = {}
---@param fn async fun()
@ -29,16 +33,38 @@ function Async:running()
return coroutine.status(self.co) ~= "dead"
end
function Async:sleep(ms)
self.sleeping = true
vim.defer_fn(function()
self.sleeping = false
end, ms)
end
function Async:suspend()
self.sleeping = true
end
function Async:resume()
self.sleeping = false
end
function Async:step()
if self.sleeping then
return true
end
local status = coroutine.status(self.co)
if status == "suspended" then
M.current = self
local ok, res = coroutine.resume(self.co)
M.current = nil
if not ok then
if self.opts.on_error then
self.opts.on_error(tostring(res))
end
elseif res then
if self.opts.on_yield then
if res == M.SLEEP then
self.sleeping = true
elseif self.opts.on_yield then
self.opts.on_yield(res)
end
end

View File

@ -222,6 +222,8 @@ function Task:spawn(cmd, opts)
end
end
self._running:suspend()
local running = true
local ret = true
---@param output string
@ -234,6 +236,7 @@ function Task:spawn(cmd, opts)
end
ret = ok
running = false
self._running:resume()
end
if headless then
@ -244,9 +247,8 @@ function Task:spawn(cmd, opts)
end
end
Process.spawn(cmd, opts)
while running do
coroutine.yield()
end
coroutine.yield()
assert(not running, "process still running?")
return ret
end

View File

@ -232,13 +232,9 @@ end
---@async
---@param ms number
function M.sleep(ms)
local continue = false
vim.defer_fn(function()
continue = true
end, ms)
while not continue do
coroutine.yield()
end
local async = require("lazy.async").current
assert(async, "Not in an async context")
async:sleep(ms)
end
function M._dump(value, result)