Async Logic - meldavy/ipf-documentation GitHub Wiki
Running asynchronous time based logic
There are a couple known approaches that are used to implement time based logic, each with specific advantages
timer
A control that is used to trigger a task on a set interval.
Code example
function SETUP_TIMER(frame)
local timer = frame:CreateOrGetControl("timer", "addontimer", 10, 10);
AUTO_CAST(timer);
timer:Stop();
timer:SetUpdateScript("AUTOAWAKENING_ON_AUTO_ATTEMPT_TIMER_TICK");
timer:Start(1);
end
function MY_FUNCTION(frame)
print("HI");
end
Advantages
- Very straightforward to setup and use. Call the
Stop()method of the timer to stop it.
Disadvantages
- It is a control object, meaning that we have to go through the regular boilerplate of setting up a ui control.
- Timer is paused from ticking when parent frame visibility becomes
false(although there is a workaround)
Note
- The first invocation always happen immediately after
Start()
FPS_UPDATE
A system message that is broadcasted almost on every frame. Thus if you need a process that needs to constantly check for a certain condition, and if you need a very fine grain frequency, you can register to the FPS_UPDATE message. Within the game client, this message is used to update FPS text. But many addons use it as a good-for-almost-everything hook.
Code Example
function MYADDON_ON_INIT(addon, frame)
addon:RegisterMsg('FPS_UPDATE', 'ON_FPS_UPDATE')
end
function ON_FPS_UPDATE(frame, msg, argStr, argNum)
... do stuff
end
Advantages
- Useful if you need to constantly update some permanent UI element
Disadvantages
- Hook always runs even if frame is not visible. Thus it can be a resource hog if not used properly. I would recommend using
timerif possible.
ReserveScript(funcName, delay)
Used to invoke a function on a delay in seconds, can be as low as 0.01 second. The function is invoked only once.
Code Example
function MY_FUNC()
ReserveScript("MY_OTHER_FUNCTION()", 2);
end
function MY_OTHER_FUNCTION()
print("I'm invoked after a 2 second delay");
end
Advantages
- Since we do not have mechanisms to sleep or wait without completely freezing the game, if we have some script that we want to run after an
namount of seconds,ReserveScriptis the best mechanisms. - Unlike
timerwhich always initially have an invocation immediately on callingtimer:Start(),ReserveScript()always invokes the script after the provided delay. - Useful when trying to prevent race conditions by delaying an operation
0.01seconds later
Disadvantages
- When you want to chain multiple
ReserveScriptthrough recursion, improper recursion may cause stack overflows. - Each
ReserveScriptcreates a new background thread (or at least that's what it feels like). Thus, an uncontrolled usage ofReserveScriptcan spawn unwanted amount of threads, and crash the game. - Let's say you want to call
ReserveScriptwhen a user clicks on a button, or presses a certain key. You might want to use a higher scopeboolean"isWaiting" variable accompanied with a conditional statement so that you don't invoke reserve a million scripts if the user decides to mash on the button.
frame:RunUpdateScript(funcName, delay)
Similar to a timer, but without the timer control.
Code Example
func START_UPDATE(frame)
frame:RunUpdateScript("ON_TICK", 1);
end
function ON_TICK(frame)
if (condition) then
return 1;
end
return 0;
end
RunUpdateScript works almost exactly like how a timer works. However, the tick only continues as long as the UpdateScript continues to return 1. If anything other than 1 is returned (or if nothing is returned), the UpdateScript stops running.
You can also manually stop the script through StopUpdateScript(funcName)
Advantages
- No need to create a control
- Because the timer keeps ticking as long as
1is returned, if you know the condition of when you want to continue running or stopping the timer,RunUpdateScript()can be much easier to use than thetimercontrol. - Same other advantages as
timer
Disadvantages
- Same disadvantages as
timer - The UpdateScript is paused from ticking when parent frame visibility becomes
false(you can use same workaround as that oftimercontrol)