This is the code I wrote with your ideas:
Lua Code:
local Routine = {} do
function Routine:Init(getterItems, chunkSize)
self.context, self.deadline = {}
self.context.currentIndex = 1
self.context.getterItems = getterItems
self.context.chunkSize = chunkSize
end
function Routine:Run(callback)
if (not self.context) then
return true
end
self.deadline = debugprofilestop() + 500/(tonumber(C_CVar.GetCVar("targetFPS")) or GetFrameRate() or 35)
repeat
local totalIndex = 1
local chunkIndex = 1
for key, value in pairs(self.context.getterItems()) do
if (totalIndex >= self.context.currentIndex) then
if (chunkIndex == self.context.chunkSize) then
return false
end
callback(self.context, key, value)
self.context.currentIndex = self.context.currentIndex + 1
chunkIndex = chunkIndex + 1
end
totalIndex = totalIndex + 1
end
self.context.finished = true
return true
until debugprofilestop() > self.deadline
end
function Routine:IsRunning()
if self.context and not self.context.finished then
return true
end
return false
end
function Routine:Reset()
self.context = {}
end
function Routine:New(routine)
routine = routine or {}
setmetatable(routine, self)
self.__index = self
return routine
end
end
And this is how I use it:
Lua Code:
local routine = Routine:New()
routine:Init(GetStuff, 100)
-- Using OnUpdate script
myFrame:SetScript("OnUpdate", function(self)
local finished = routine:Run(function(state, key, value)
doHeavyStuff(key, value)
end)
if (finished) then
routine:Reset()
self:SetScript("OnUpdate", nil)
end
end);
-- Using a ticker if the frame is hidden
C_Timer.NewTicker(0.5, function(self)
local finished = routine:Run(function(context, key, value)
doHeavyStuff(key, value)
end)
if (finished) then
routine:Reset()
self:Cancel()
end
end
So far this improves the performance a lot. It takes longer to finish, but I'm sure I can improve it changing the value of "state.chunkSize".
The issue I find with this code is that it loops through the table returned by GetStuff() several times and I don't see how to avoid it.
Thank you both!