mirror of
https://github.com/hexedtech/codemp-nvim.git
synced 2024-11-21 15:04:52 +01:00
feat: improved async poller for events
now, when :abort() is available, it properly cancels promises so that we dont get dangling references
This commit is contained in:
parent
e8005fbeab
commit
5ae49d3c49
2 changed files with 59 additions and 13 deletions
|
@ -29,18 +29,44 @@ local function color(name)
|
|||
}
|
||||
end
|
||||
|
||||
---@class AsyncPoller
|
||||
---@field promise WorkspaceEventPromise | nil
|
||||
---@field timer luv.Timer
|
||||
---@field generator fun(): WorkspaceEventPromise
|
||||
---@field callback fun(e: WorkspaceEvent)
|
||||
---@field stop fun(self: AsyncPoller)
|
||||
|
||||
---@return AsyncPoller
|
||||
local function async_poller(generator, callback)
|
||||
local promise = nil
|
||||
local timer = vim.loop.new_timer()
|
||||
timer:start(500, 500, function()
|
||||
if promise == nil then promise = generator() end
|
||||
if promise.ready then
|
||||
local res = promise:await()
|
||||
vim.schedule(function() callback(res) end)
|
||||
promise = nil
|
||||
---@type AsyncPoller
|
||||
local poller = {
|
||||
promise = nil,
|
||||
generator = generator,
|
||||
callback = callback,
|
||||
timer = vim.uv.new_timer(),
|
||||
stop = function (this)
|
||||
print("stopping async poller")
|
||||
if this.promise ~= nil then
|
||||
-- TODO the :abort() change still hasnt been merged, so check for its presence!
|
||||
if this.promise.abort ~= nil then
|
||||
this.promise:abort()
|
||||
end
|
||||
end
|
||||
this.timer:stop()
|
||||
this.timer:close()
|
||||
end
|
||||
}
|
||||
poller.timer:start(500, 500, function()
|
||||
print("ticking poller")
|
||||
if poller.promise == nil then poller.promise = poller.generator() end
|
||||
if poller.promise.ready then
|
||||
print("spawning callback")
|
||||
local res = poller.promise:await()
|
||||
vim.schedule(function() poller.callback(res) end)
|
||||
poller.promise = nil
|
||||
end
|
||||
end)
|
||||
|
||||
return poller
|
||||
end
|
||||
|
||||
---@param first integer
|
||||
|
|
|
@ -150,6 +150,8 @@ local function register_cursor_handler(controller)
|
|||
controller:callback(function (_controller) async:send() end)
|
||||
end
|
||||
|
||||
local events_poller = nil
|
||||
|
||||
---@param workspace string workspace name to join
|
||||
---join a workspace and register event handlers
|
||||
local function join(workspace)
|
||||
|
@ -169,8 +171,14 @@ local function join(workspace)
|
|||
}
|
||||
end
|
||||
require('codemp.window').update()
|
||||
utils.poller(
|
||||
function() return ws:event() end,
|
||||
local ws_name = ws.name
|
||||
events_poller = utils.poller(
|
||||
function()
|
||||
if CODEMP.client == nil then return nil end
|
||||
local wspace = CODEMP.client:get_workspace(ws_name)
|
||||
if wspace == nil then return nil end
|
||||
return wspace:event()
|
||||
end,
|
||||
function(event)
|
||||
if event.type == "leave" then
|
||||
if buffers.users[event.value] ~= nil then
|
||||
|
@ -198,9 +206,21 @@ local function join(workspace)
|
|||
end
|
||||
|
||||
local function leave()
|
||||
CODEMP.client:leave_workspace(CODEMP.workspace.name)
|
||||
print(" -- left workspace")
|
||||
local name = CODEMP.workspace.name
|
||||
CODEMP.workspace = nil
|
||||
if events_poller ~= nil then
|
||||
events_poller:stop()
|
||||
events_poller = nil
|
||||
end
|
||||
if not CODEMP.client:leave_workspace(name) then
|
||||
collectgarbage("collect")
|
||||
-- TODO codemp disconnects when all references to its objects are dropped. since it
|
||||
-- hands out Arc<> of things, all references still not garbage collected in Lua will
|
||||
-- prevent it from disconnecting. while running a full cycle may be a bit slow, this
|
||||
-- only happens when manually requested, and it's not like the extra garbage collection
|
||||
-- is an effort for nothing... still it would be more elegant to not need this!!
|
||||
end
|
||||
print(" -- left workspace " .. name)
|
||||
require('codemp.window').update()
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in a new issue